diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ddb8b56 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +bin/ +obj/ +*.pidb +*.userprefs +*.suo diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..8ef8fe6 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,15 @@ +[submodule "lib/SDL2-CS"] + path = lib/SDL2-CS + url = git://github.com/flibitijibibo/SDL2-CS.git +[submodule "lib/OpenAL-CS"] + path = lib/OpenAL-CS + url = git://github.com/flibitijibibo/OpenAL-CS.git +[submodule "lib/MojoShader-CS"] + path = lib/MojoShader-CS + url = git://github.com/flibitijibibo/MojoShader-CS.git +[submodule "lib/Vorbisfile-CS"] + path = lib/Vorbisfile-CS + url = git://github.com/flibitijibibo/Vorbisfile-CS.git +[submodule "lib/TheoraPlay-CS"] + path = lib/TheoraPlay-CS + url = git://github.com/flibitijibibo/TheoraPlay-CS.git diff --git a/FNA.csproj b/FNA.csproj new file mode 100644 index 0000000..4439365 --- /dev/null +++ b/FNA.csproj @@ -0,0 +1,391 @@ + + + + Debug + x86 + 9.0.21022 + 2.0 + {35253CE1-C864-4CD3-8249-4D1319748E8F} + Library + Microsoft.Xna.Framework + FNA + + + True + full + False + bin\Debug + DEBUG; + prompt + 4 + x86 + False + True + + + none + True + bin\Release + prompt + 4 + x86 + False + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Always + + + + + Microsoft.Xna.Framework.Graphics.Effect.Resources.AlphaTestEffect.fxb + + + Microsoft.Xna.Framework.Graphics.Effect.Resources.BasicEffect.fxb + + + Microsoft.Xna.Framework.Graphics.Effect.Resources.DualTextureEffect.fxb + + + Microsoft.Xna.Framework.Graphics.Effect.Resources.EnvironmentMapEffect.fxb + + + Microsoft.Xna.Framework.Graphics.Effect.Resources.SkinnedEffect.fxb + + + Microsoft.Xna.Framework.Graphics.Effect.Resources.SpriteEffect.fxb + + + Microsoft.Xna.Framework.Graphics.Effect.Resources.YUVToRGBAEffect.fxb + + + diff --git a/FNA.dll.config b/FNA.dll.config new file mode 100644 index 0000000..730894d --- /dev/null +++ b/FNA.dll.config @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FNA.sln b/FNA.sln new file mode 100644 index 0000000..81084c0 --- /dev/null +++ b/FNA.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FNA", "FNA.csproj", "{35253CE1-C864-4CD3-8249-4D1319748E8F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {35253CE1-C864-4CD3-8249-4D1319748E8F}.Debug|x86.ActiveCfg = Debug|x86 + {35253CE1-C864-4CD3-8249-4D1319748E8F}.Debug|x86.Build.0 = Debug|x86 + {35253CE1-C864-4CD3-8249-4D1319748E8F}.Release|x86.ActiveCfg = Release|x86 + {35253CE1-C864-4CD3-8249-4D1319748E8F}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = FNA.csproj + EndGlobalSection +EndGlobal diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a3f8632 --- /dev/null +++ b/Makefile @@ -0,0 +1,350 @@ +# Makefile for FNA +# Written by Ethan "flibitijibibo" Lee + +# Source Lists +SRC = \ + src/Audio/AudioCategory.cs \ + src/Audio/AudioChannels.cs \ + src/Audio/AudioDevice.cs \ + src/Audio/AudioEmitter.cs \ + src/Audio/AudioEngine.cs \ + src/Audio/AudioListener.cs \ + src/Audio/AudioStopOptions.cs \ + src/Audio/Cue.cs \ + src/Audio/CueData.cs \ + src/Audio/DynamicSoundEffectInstance.cs \ + src/Audio/IALDevice.cs \ + src/Audio/InstancePlayLimitException.cs \ + src/Audio/Microphone.cs \ + src/Audio/MicrophoneState.cs \ + src/Audio/NoAudioHardwareException.cs \ + src/Audio/NoMicrophoneConnectedException.cs \ + src/Audio/NullDevice.cs \ + src/Audio/OpenALDevice.cs \ + src/Audio/RendererDetail.cs \ + src/Audio/SoundBank.cs \ + src/Audio/SoundEffect.cs \ + src/Audio/SoundEffectInstance.cs \ + src/Audio/SoundState.cs \ + src/Audio/WaveBank.cs \ + src/Audio/XACTInternal.cs \ + src/BoundingBox.cs \ + src/BoundingFrustum.cs \ + src/BoundingSphere.cs \ + src/Color.cs \ + src/ContainmentType.cs \ + src/Content/ContentExtensions.cs \ + src/Content/ContentLoadException.cs \ + src/Content/ContentManager.cs \ + src/Content/ContentReader.cs \ + src/Content/ContentReaders/AlphaTestEffectReader.cs \ + src/Content/ContentReaders/ArrayReader.cs \ + src/Content/ContentReaders/BasicEffectReader.cs \ + src/Content/ContentReaders/BooleanReader.cs \ + src/Content/ContentReaders/BoundingBoxReader.cs \ + src/Content/ContentReaders/BoundingFrustumReader.cs \ + src/Content/ContentReaders/BoundingSphereReader.cs \ + src/Content/ContentReaders/ByteReader.cs \ + src/Content/ContentReaders/CharReader.cs \ + src/Content/ContentReaders/ColorReader.cs \ + src/Content/ContentReaders/CurveReader.cs \ + src/Content/ContentReaders/DateTimeReader.cs \ + src/Content/ContentReaders/DecimalReader.cs \ + src/Content/ContentReaders/DictionaryReader.cs \ + src/Content/ContentReaders/DoubleReader.cs \ + src/Content/ContentReaders/DualTextureEffectReader.cs \ + src/Content/ContentReaders/EffectMaterialReader.cs \ + src/Content/ContentReaders/EffectReader.cs \ + src/Content/ContentReaders/EnumReader.cs \ + src/Content/ContentReaders/EnvironmentMapEffectReader.cs \ + src/Content/ContentReaders/ExternalReferenceReader.cs \ + src/Content/ContentReaders/IndexBufferReader.cs \ + src/Content/ContentReaders/Int16Reader.cs \ + src/Content/ContentReaders/Int32Reader.cs \ + src/Content/ContentReaders/Int64Reader.cs \ + src/Content/ContentReaders/ListReader.cs \ + src/Content/ContentReaders/MatrixReader.cs \ + src/Content/ContentReaders/ModelReader.cs \ + src/Content/ContentReaders/NullableReader.cs \ + src/Content/ContentReaders/PlaneReader.cs \ + src/Content/ContentReaders/PointReader.cs \ + src/Content/ContentReaders/QuaternionReader.cs \ + src/Content/ContentReaders/RayReader.cs \ + src/Content/ContentReaders/RectangleReader.cs \ + src/Content/ContentReaders/ReflectiveReader.cs \ + src/Content/ContentReaders/SByteReader.cs \ + src/Content/ContentReaders/SingleReader.cs \ + src/Content/ContentReaders/SkinnedEffectReader.cs \ + src/Content/ContentReaders/SongReader.cs \ + src/Content/ContentReaders/SoundEffectReader.cs \ + src/Content/ContentReaders/SpriteFontReader.cs \ + src/Content/ContentReaders/StringReader.cs \ + src/Content/ContentReaders/Texture2DReader.cs \ + src/Content/ContentReaders/Texture3DReader.cs \ + src/Content/ContentReaders/TextureCubeReader.cs \ + src/Content/ContentReaders/TextureReader.cs \ + src/Content/ContentReaders/TimeSpanReader.cs \ + src/Content/ContentReaders/UInt16Reader.cs \ + src/Content/ContentReaders/UInt32Reader.cs \ + src/Content/ContentReaders/UInt64Reader.cs \ + src/Content/ContentReaders/Vector2Reader.cs \ + src/Content/ContentReaders/Vector3Reader.cs \ + src/Content/ContentReaders/Vector4Reader.cs \ + src/Content/ContentReaders/VertexBufferReader.cs \ + src/Content/ContentReaders/VertexDeclarationReader.cs \ + src/Content/ContentReaders/VideoReader.cs \ + src/Content/ContentSerializerAttribute.cs \ + src/Content/ContentSerializerCollectionItemNameAttribute.cs \ + src/Content/ContentSerializerIgnoreAttribute.cs \ + src/Content/ContentSerializerRuntimeTypeAttribute.cs \ + src/Content/ContentSerializerTypeVersionAttribute.cs \ + src/Content/ContentTypeReader.cs \ + src/Content/ContentTypeReaderManager.cs \ + src/Content/LzxDecoder.cs \ + src/Content/ResourceContentManager.cs \ + src/Curve.cs \ + src/CurveContinuity.cs \ + src/CurveKey.cs \ + src/CurveKeyCollection.cs \ + src/CurveLoopType.cs \ + src/CurveTangent.cs \ + src/Design/BoundingBoxConverter.cs \ + src/Design/BoundingSphereConverter.cs \ + src/Design/ColorConverter.cs \ + src/Design/MathTypeConverter.cs \ + src/Design/MatrixConverter.cs \ + src/Design/PlaneConverter.cs \ + src/Design/PointConverter.cs \ + src/Design/QuaternionConverter.cs \ + src/Design/RayConverter.cs \ + src/Design/RectangleConverter.cs \ + src/Design/Vector2Converter.cs \ + src/Design/Vector3Converter.cs \ + src/Design/Vector4Converter.cs \ + src/DisplayOrientation.cs \ + src/DrawableGameComponent.cs \ + src/FrameworkDispatcher.cs \ + src/Game.cs \ + src/GameComponent.cs \ + src/GameComponentCollection.cs \ + src/GameComponentCollectionEventArgs.cs \ + src/GamePlatform.cs \ + src/GameServiceContainer.cs \ + src/GameTime.cs \ + src/GameWindow.cs \ + src/Graphics/ClearOptions.cs \ + src/Graphics/ColorWriteChannels.cs \ + src/Graphics/CubeMapFace.cs \ + src/Graphics/DepthFormat.cs \ + src/Graphics/DeviceLostException.cs \ + src/Graphics/DeviceNotResetException.cs \ + src/Graphics/DirectionalLight.cs \ + src/Graphics/DisplayMode.cs \ + src/Graphics/DisplayModeCollection.cs \ + src/Graphics/DxtUtil.cs \ + src/Graphics/Effect/Effect.cs \ + src/Graphics/Effect/EffectAnnotation.cs \ + src/Graphics/Effect/EffectAnnotationCollection.cs \ + src/Graphics/Effect/EffectMaterial.cs \ + src/Graphics/Effect/EffectParameter.cs \ + src/Graphics/Effect/EffectParameterClass.cs \ + src/Graphics/Effect/EffectParameterCollection.cs \ + src/Graphics/Effect/EffectParameterType.cs \ + src/Graphics/Effect/EffectPass.cs \ + src/Graphics/Effect/EffectPassCollection.cs \ + src/Graphics/Effect/EffectTechnique.cs \ + src/Graphics/Effect/EffectTechniqueCollection.cs \ + src/Graphics/Effect/IEffectFog.cs \ + src/Graphics/Effect/IEffectLights.cs \ + src/Graphics/Effect/IEffectMatrices.cs \ + src/Graphics/Effect/Resources.cs \ + src/Graphics/Effect/StockEffects/AlphaTestEffect.cs \ + src/Graphics/Effect/StockEffects/BasicEffect.cs \ + src/Graphics/Effect/StockEffects/DualTextureEffect.cs \ + src/Graphics/Effect/StockEffects/EffectHelpers.cs \ + src/Graphics/Effect/StockEffects/EnvironmentMapEffect.cs \ + src/Graphics/Effect/StockEffects/SkinnedEffect.cs \ + src/Graphics/Effect/StockEffects/SpriteEffect.cs \ + src/Graphics/GraphicsAdapter.cs \ + src/Graphics/GraphicsDevice.cs \ + src/Graphics/GraphicsDeviceStatus.cs \ + src/Graphics/GraphicsProfile.cs \ + src/Graphics/GraphicsResource.cs \ + src/Graphics/IGLDevice.cs \ + src/Graphics/IGraphicsDeviceService.cs \ + src/Graphics/IRenderTarget.cs \ + src/Graphics/Model.cs \ + src/Graphics/ModelBone.cs \ + src/Graphics/ModelBoneCollection.cs \ + src/Graphics/ModelEffectCollection.cs \ + src/Graphics/ModelMesh.cs \ + src/Graphics/ModelMeshCollection.cs \ + src/Graphics/ModelMeshPart.cs \ + src/Graphics/ModelMeshPartCollection.cs \ + src/Graphics/NoSuitableGraphicsDeviceException.cs \ + src/Graphics/OcclusionQuery.cs \ + src/Graphics/OpenGLDevice.cs \ + src/Graphics/OpenGLDevice_GL.cs \ + src/Graphics/PackedVector/Alpha8.cs \ + src/Graphics/PackedVector/Bgr565.cs \ + src/Graphics/PackedVector/Bgra4444.cs \ + src/Graphics/PackedVector/Bgra5551.cs \ + src/Graphics/PackedVector/Byte4.cs \ + src/Graphics/PackedVector/HalfSingle.cs \ + src/Graphics/PackedVector/HalfTypeHelper.cs \ + src/Graphics/PackedVector/HalfVector2.cs \ + src/Graphics/PackedVector/HalfVector4.cs \ + src/Graphics/PackedVector/IPackedVector.cs \ + src/Graphics/PackedVector/NormalizedByte2.cs \ + src/Graphics/PackedVector/NormalizedByte4.cs \ + src/Graphics/PackedVector/NormalizedShort2.cs \ + src/Graphics/PackedVector/NormalizedShort4.cs \ + src/Graphics/PackedVector/Rg32.cs \ + src/Graphics/PackedVector/Rgba64.cs \ + src/Graphics/PackedVector/Rgba1010102.cs \ + src/Graphics/PackedVector/Short2.cs \ + src/Graphics/PackedVector/Short4.cs \ + src/Graphics/PresentationParameters.cs \ + src/Graphics/PresentInterval.cs \ + src/Graphics/PrimitiveType.cs \ + src/Graphics/RenderTarget2D.cs \ + src/Graphics/RenderTargetBinding.cs \ + src/Graphics/RenderTargetCube.cs \ + src/Graphics/RenderTargetUsage.cs \ + src/Graphics/ResourceCreatedEventArgs.cs \ + src/Graphics/ResourceDestroyedEventArgs.cs \ + src/Graphics/SamplerStateCollection.cs \ + src/Graphics/SetDataOptions.cs \ + src/Graphics/SpriteBatch.cs \ + src/Graphics/SpriteEffects.cs \ + src/Graphics/SpriteFont.cs \ + src/Graphics/SpriteSortMode.cs \ + src/Graphics/States/Blend.cs \ + src/Graphics/States/BlendFunction.cs \ + src/Graphics/States/BlendState.cs \ + src/Graphics/States/CompareFunction.cs \ + src/Graphics/States/CullMode.cs \ + src/Graphics/States/DepthStencilState.cs \ + src/Graphics/States/FillMode.cs \ + src/Graphics/States/RasterizerState.cs \ + src/Graphics/States/SamplerState.cs \ + src/Graphics/States/StencilOperation.cs \ + src/Graphics/States/TextureAddressMode.cs \ + src/Graphics/States/TextureFilter.cs \ + src/Graphics/SurfaceFormat.cs \ + src/Graphics/Texture.cs \ + src/Graphics/Texture2D.cs \ + src/Graphics/Texture3D.cs \ + src/Graphics/TextureCollection.cs \ + src/Graphics/TextureCube.cs \ + src/Graphics/Vertices/BufferUsage.cs \ + src/Graphics/Vertices/DynamicIndexBuffer.cs \ + src/Graphics/Vertices/DynamicVertexBuffer.cs \ + src/Graphics/Vertices/IndexBuffer.cs \ + src/Graphics/Vertices/IndexElementSize.cs \ + src/Graphics/Vertices/IVertexType.cs \ + src/Graphics/Vertices/VertexBuffer.cs \ + src/Graphics/Vertices/VertexBufferBinding.cs \ + src/Graphics/Vertices/VertexDeclaration.cs \ + src/Graphics/Vertices/VertexDeclarationCache.cs \ + src/Graphics/Vertices/VertexElement.cs \ + src/Graphics/Vertices/VertexElementFormat.cs \ + src/Graphics/Vertices/VertexElementUsage.cs \ + src/Graphics/Vertices/VertexPositionColor.cs \ + src/Graphics/Vertices/VertexPositionColorTexture.cs \ + src/Graphics/Vertices/VertexPositionNormalTexture.cs \ + src/Graphics/Vertices/VertexPositionTexture.cs \ + src/Graphics/Viewport.cs \ + src/GraphicsDeviceInformation.cs \ + src/GraphicsDeviceManager.cs \ + src/IDrawable.cs \ + src/IGameComponent.cs \ + src/IGraphicsDeviceManager.cs \ + src/Input/Buttons.cs \ + src/Input/ButtonState.cs \ + src/Input/GamePadButtons.cs \ + src/Input/GamePadCapabilities.cs \ + src/Input/GamePadDeadZone.cs \ + src/Input/GamePadDPad.cs \ + src/Input/GamePadState.cs \ + src/Input/GamePadThumbSticks.cs \ + src/Input/GamePadTriggers.cs \ + src/Input/GamePadType.cs \ + src/Input/Keyboard.cs \ + src/Input/KeyboardState.cs \ + src/Input/Keys.cs \ + src/Input/KeyState.cs \ + src/Input/MouseState.cs \ + src/Input/TextInputEXT.cs \ + src/IUpdateable.cs \ + src/LaunchParameters.cs \ + src/MathHelper.cs \ + src/Matrix.cs \ + src/Media/MediaPlayer.cs \ + src/Media/MediaQueue.cs \ + src/Media/MediaState.cs \ + src/Media/SongCollection.cs \ + src/Media/VideoSoundtrackType.cs \ + src/Media/VisualizationData.cs \ + src/Media/Xiph/Song.cs \ + src/Media/Xiph/Video.cs \ + src/Media/Xiph/VideoPlayer.cs \ + src/NamespaceDocs.cs \ + src/Plane.cs \ + src/PlaneIntersectionType.cs \ + src/PlayerIndex.cs \ + src/Point.cs \ + src/PreparingDeviceSettingsEventArgs.cs \ + src/Properties/AssemblyInfo.cs \ + src/Quaternion.cs \ + src/Ray.cs \ + src/Rectangle.cs \ + src/SDL2/Input/SDL2_GamePad.cs \ + src/SDL2/Input/SDL2_KeyboardUtil.cs \ + src/SDL2/Input/SDL2_Mouse.cs \ + src/SDL2/SDL2_GamePlatform.cs \ + src/SDL2/SDL2_GameWindow.cs \ + src/Storage/StorageContainer.cs \ + src/Storage/StorageDevice.cs \ + src/Storage/StorageDeviceNotConnectedException.cs \ + src/TitleContainer.cs \ + src/Utilities/AssemblyHelper.cs \ + src/Utilities/FileHelpers.cs \ + src/Vector2.cs \ + src/Vector3.cs \ + src/Vector4.cs \ + lib/SDL2-CS/src/SDL2.cs \ + lib/SDL2-CS/src/SDL2_image.cs \ + lib/SDL2-CS/src/LPUtf8StrMarshaler.cs \ + lib/OpenAL-CS/src/ALC10.cs \ + lib/OpenAL-CS/src/ALC11.cs \ + lib/OpenAL-CS/src/AL10.cs \ + lib/OpenAL-CS/src/AL11.cs \ + lib/OpenAL-CS/src/ALEXT.cs \ + lib/OpenAL-CS/src/EFX.cs \ + lib/MojoShader-CS/MojoShader.cs \ + lib/Vorbisfile-CS/Vorbisfile.cs \ + lib/TheoraPlay-CS/TheoraPlay.cs + +# Targets + +debug: clean-debug + mkdir -p bin/Debug + cp FNA.dll.config bin/Debug + dmcs /unsafe -debug -out:bin/Debug/FNA.dll -target:library $(SRC) + +clean-debug: + rm -rf bin/Debug + +release: clean-release + mkdir -p bin/Release + cp FNA.dll.config bin/Release + dmcs /unsafe -optimize -out:bin/Release/FNA.dll -target:library $(SRC) + +clean-release: + rm -rf bin/Release + +clean: clean-debug clean-release + rm -rf bin + +all: debug release diff --git a/README b/README new file mode 100644 index 0000000..108403c --- /dev/null +++ b/README @@ -0,0 +1,29 @@ +This is FNA, an XNA4 reimplementation that focuses solely on developing a fully +accurate XNA4 runtime for the desktop. + +Project Website: http://fna-xna.github.io/ + +License +------- +FNA is released under the Microsoft Public License. See LICENSE for details. + +FNA uses LzxDecoder.cs, released under a dual MSPL/LGPL license. +See lzxdecoder.LICENSE for details. + +FNA uses code from the unxwb project, specially released under the MonoGame +project license. See unxwb.LICENSE for details. + +FNA uses code from the Mono.Xna project, released under the MIT license. +See monoxna.LICENSE for details. + +Documentation +------------- +Documentation for FNA can be found on the FNA wiki: + +https://github.com/FNA-XNA/FNA/wiki + +Found an issue? +--------------- +Issues and patches can be reported via GitHub: + +https://github.com/FNA-XNA/FNA/issues diff --git a/gendarme/fna.ignore b/gendarme/fna.ignore new file mode 100644 index 0000000..7d420d7 --- /dev/null +++ b/gendarme/fna.ignore @@ -0,0 +1,12 @@ +R: Gendarme.Rules.Design.AvoidRefAndOutParametersRule +A: FNA + +R: Gendarme.Rules.Naming.AvoidDeepNamespaceHierarchyRule +A: FNA + +# Ignore everything from the lib folder +@ sdl2.ignore +@ openal.ignore +@ mojoshader.ignore +@ vorbisfile.ignore +@ theoraplay.ignore diff --git a/gendarme/mojoshader.ignore b/gendarme/mojoshader.ignore new file mode 100644 index 0000000..894c34f --- /dev/null +++ b/gendarme/mojoshader.ignore @@ -0,0 +1,339 @@ +R: Gendarme.Rules.Design.Generic.AvoidDeclaringCustomDelegatesRule +T: MojoShader/MOJOSHADER_malloc +T: MojoShader/MOJOSHADER_free +T: MojoShader/MOJOSHADER_glGetProcAddress + +R: Gendarme.Rules.Performance.AvoidLargeStructureRule +T: MojoShader/MOJOSHADER_symbol +T: MojoShader/MOJOSHADER_preshaderInstruction +T: MojoShader/MOJOSHADER_parseData +T: MojoShader/MOJOSHADER_effectValue +T: MojoShader/MOJOSHADER_effectState +T: MojoShader/MOJOSHADER_effectSamplerState +T: MojoShader/MOJOSHADER_effectAnnotation +T: MojoShader/MOJOSHADER_effectParam +T: MojoShader/MOJOSHADER_effectShader +T: MojoShader/MOJOSHADER_effectObject +T: MojoShader/MOJOSHADER_effect + +R: Gendarme.Rules.Naming.AvoidNonAlphanumericIdentifierRule +T: MojoShader +M: System.Int32 MojoShader::MOJOSHADER_version() +M: System.IntPtr MojoShader::MOJOSHADER_changeset() +M: System.Int32 MojoShader::MOJOSHADER_maxShaderModel(System.String) +M: System.IntPtr MojoShader::MOJOSHADER_parse(System.String,System.Byte[],System.UInt32,MojoShader/MOJOSHADER_swizzle[],System.UInt32,MojoShader/MOJOSHADER_samplerMap[],System.UInt32,MojoShader/MOJOSHADER_malloc,MojoShader/MOJOSHADER_free,System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_freeParseData(System.IntPtr) +M: System.IntPtr MojoShader::MOJOSHADER_parsePreshader(System.Byte[],System.UInt32,MojoShader/MOJOSHADER_malloc,MojoShader/MOJOSHADER_free,System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_freePreshader(System.IntPtr) +M: System.IntPtr MojoShader::MOJOSHADER_parseEffect(System.String,System.Byte[],System.UInt32,MojoShader/MOJOSHADER_swizzle[],System.UInt32,MojoShader/MOJOSHADER_samplerMap[],System.UInt32,MojoShader/MOJOSHADER_malloc,MojoShader/MOJOSHADER_free,System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_freeEffect(System.IntPtr) +M: System.IntPtr MojoShader::MOJOSHADER_cloneEffect(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_effectSetRawValueHandle(System.IntPtr,System.IntPtr,System.UInt32,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_effectSetRawValueName(System.IntPtr,System.String,System.IntPtr,System.UInt32,System.UInt32) +M: System.IntPtr MojoShader::MOJOSHADER_effectGetCurrentTechnique(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_effectSetTechnique(System.IntPtr,System.IntPtr) +M: System.IntPtr MojoShader::MOJOSHADER_effectFindNextValidTechnique(System.IntPtr,System.IntPtr) +M: System.IntPtr MojoShader::MOJOSHADER_glCompileEffect(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glDeleteEffect(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glEffectBegin(System.IntPtr,System.UInt32&,System.Int32,MojoShader/MOJOSHADER_effectStateChanges&) +M: System.Void MojoShader::MOJOSHADER_glEffectBeginPass(System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glEffectCommitChanges(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glEffectEndPass(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glEffectEnd(System.IntPtr) +M: System.Int32 MojoShader::MOJOSHADER_glAvailableProfiles(MojoShader/MOJOSHADER_glGetProcAddress,System.IntPtr,System.IntPtr,System.Int32,MojoShader/MOJOSHADER_malloc,MojoShader/MOJOSHADER_free,System.IntPtr) +M: System.String MojoShader::MOJOSHADER_glBestProfile(MojoShader/MOJOSHADER_glGetProcAddress,System.IntPtr,MojoShader/MOJOSHADER_malloc,MojoShader/MOJOSHADER_free,System.IntPtr) +M: System.IntPtr MojoShader::MOJOSHADER_glCreateContext(System.String,MojoShader/MOJOSHADER_glGetProcAddress,System.IntPtr,MojoShader/MOJOSHADER_malloc,MojoShader/MOJOSHADER_free,System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glMakeContextCurrent(System.IntPtr) +M: System.String MojoShader::MOJOSHADER_glGetError() +M: System.Int32 MojoShader::MOJOSHADER_glMaxUniforms(MojoShader/MOJOSHADER_shaderType) +M: System.IntPtr MojoShader::MOJOSHADER_glCompileShader(System.Byte[],System.UInt32,MojoShader/MOJOSHADER_swizzle[],System.UInt32,MojoShader/MOJOSHADER_samplerMap[],System.UInt32) +M: System.IntPtr MojoShader::MOJOSHADER_glGetShaderParseData(System.IntPtr) +M: System.IntPtr MojoShader::MOJOSHADER_glLinkProgram(System.IntPtr,System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glBindProgram(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glBindShaders(System.IntPtr,System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glSetVertexShaderUniformF(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glGetVertexShaderUniformF(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glSetVertexShaderUniformI(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glGetVertexShaderUniformI(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glSetVertexShaderUniformB(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glGetVertexShaderUniformB(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glSetPixelShaderUniformF(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glGetPixelShaderUniformF(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glSetPixelShaderUniformI(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glGetPixelShaderUniformI(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glSetPixelShaderUniformB(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glGetPixelShaderUniformB(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glSetLegacyBumpMapEnv(System.UInt32,System.Single,System.Single,System.Single,System.Single,System.Single,System.Single) +M: System.Int32 MojoShader::MOJOSHADER_glGetVertexAttribLocation(MojoShader/MOJOSHADER_usage,System.Int32) +M: System.Void MojoShader::MOJOSHADER_glSetVertexAttribute(MojoShader/MOJOSHADER_usage,System.Int32,System.UInt32,MojoShader/MOJOSHADER_attributeType,System.Int32,System.UInt32,System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glSetVertexAttribDivisor(MojoShader/MOJOSHADER_usage,System.Int32,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glProgramReady() +M: System.Void MojoShader::MOJOSHADER_glProgramViewportFlip(System.Int32) +M: System.Void MojoShader::MOJOSHADER_glDeleteProgram(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glDeleteShader(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glDestroyContext(System.IntPtr) +T: MojoShader/MOJOSHADER_malloc +T: MojoShader/MOJOSHADER_free +T: MojoShader/MOJOSHADER_shaderType +T: MojoShader/MOJOSHADER_attributeType +T: MojoShader/MOJOSHADER_uniformType +T: MojoShader/MOJOSHADER_uniform +T: MojoShader/MOJOSHADER_constant +T: MojoShader/MOJOSHADER_samplerType +T: MojoShader/MOJOSHADER_sampler +T: MojoShader/MOJOSHADER_samplerMap +T: MojoShader/MOJOSHADER_usage +T: MojoShader/MOJOSHADER_attribute +T: MojoShader/MOJOSHADER_swizzle +T: MojoShader/MOJOSHADER_symbolRegisterSet +T: MojoShader/MOJOSHADER_symbolClass +T: MojoShader/MOJOSHADER_symbolType +T: MojoShader/MOJOSHADER_symbolTypeInfo +T: MojoShader/MOJOSHADER_symbolStructMember +T: MojoShader/MOJOSHADER_symbol +T: MojoShader/MOJOSHADER_error +T: MojoShader/MOJOSHADER_preshaderOpcode +T: MojoShader/MOJOSHADER_preshaderOperandType +T: MojoShader/MOJOSHADER_preshaderOperand +T: MojoShader/MOJOSHADER_preshaderInstruction +T: MojoShader/MOJOSHADER_preshader +T: MojoShader/MOJOSHADER_parseData +T: MojoShader/MOJOSHADER_renderStateType +T: MojoShader/MOJOSHADER_zBufferType +T: MojoShader/MOJOSHADER_fillMode +T: MojoShader/MOJOSHADER_shadeMode +T: MojoShader/MOJOSHADER_blendMode +T: MojoShader/MOJOSHADER_cullMode +T: MojoShader/MOJOSHADER_compareFunc +T: MojoShader/MOJOSHADER_fogMode +T: MojoShader/MOJOSHADER_stencilOp +T: MojoShader/MOJOSHADER_materialColorSource +T: MojoShader/MOJOSHADER_vertexBlendFlags +T: MojoShader/MOJOSHADER_patchedEdgeStyle +T: MojoShader/MOJOSHADER_debugMonitorTokens +T: MojoShader/MOJOSHADER_blendOp +T: MojoShader/MOJOSHADER_degreeType +T: MojoShader/MOJOSHADER_samplerStateType +T: MojoShader/MOJOSHADER_textureAddress +T: MojoShader/MOJOSHADER_textureFilterType +T: MojoShader/MOJOSHADER_effectValue +T: MojoShader/MOJOSHADER_effectState +T: MojoShader/MOJOSHADER_effectSamplerState +T: MojoShader/MOJOSHADER_effectAnnotation +T: MojoShader/MOJOSHADER_effectParam +T: MojoShader/MOJOSHADER_effectPass +T: MojoShader/MOJOSHADER_effectTechnique +T: MojoShader/MOJOSHADER_effectShader +T: MojoShader/MOJOSHADER_effectSamplerMap +T: MojoShader/MOJOSHADER_effectString +T: MojoShader/MOJOSHADER_effectTexture +T: MojoShader/MOJOSHADER_effectObject +T: MojoShader/MOJOSHADER_samplerStateRegister +T: MojoShader/MOJOSHADER_effectStateChanges +T: MojoShader/MOJOSHADER_effect +T: MojoShader/MOJOSHADER_glGetProcAddress + +R: Gendarme.Rules.BadPractice.AvoidVisibleConstantFieldRule +T: MojoShader + +R: Gendarme.Rules.Design.AvoidVisibleFieldsRule +T: MojoShader/MOJOSHADER_uniform +T: MojoShader/MOJOSHADER_constant +T: MojoShader/MOJOSHADER_sampler +T: MojoShader/MOJOSHADER_samplerMap +T: MojoShader/MOJOSHADER_attribute +T: MojoShader/MOJOSHADER_swizzle +T: MojoShader/MOJOSHADER_symbolTypeInfo +T: MojoShader/MOJOSHADER_symbolStructMember +T: MojoShader/MOJOSHADER_symbol +T: MojoShader/MOJOSHADER_error +T: MojoShader/MOJOSHADER_preshaderOperand +T: MojoShader/MOJOSHADER_preshaderInstruction +T: MojoShader/MOJOSHADER_preshader +T: MojoShader/MOJOSHADER_parseData +T: MojoShader/MOJOSHADER_effectValue +T: MojoShader/MOJOSHADER_effectState +T: MojoShader/MOJOSHADER_effectSamplerState +T: MojoShader/MOJOSHADER_effectAnnotation +T: MojoShader/MOJOSHADER_effectParam +T: MojoShader/MOJOSHADER_effectPass +T: MojoShader/MOJOSHADER_effectTechnique +T: MojoShader/MOJOSHADER_effectShader +T: MojoShader/MOJOSHADER_effectSamplerMap +T: MojoShader/MOJOSHADER_effectString +T: MojoShader/MOJOSHADER_effectTexture +T: MojoShader/MOJOSHADER_effectObject +T: MojoShader/MOJOSHADER_samplerStateRegister +T: MojoShader/MOJOSHADER_effectStateChanges +T: MojoShader/MOJOSHADER_effect + +R: Gendarme.Rules.Design.AvoidVisibleNestedTypesRule +T: MojoShader/MOJOSHADER_malloc +T: MojoShader/MOJOSHADER_free +T: MojoShader/MOJOSHADER_shaderType +T: MojoShader/MOJOSHADER_attributeType +T: MojoShader/MOJOSHADER_uniformType +T: MojoShader/MOJOSHADER_uniform +T: MojoShader/MOJOSHADER_constant +T: MojoShader/MOJOSHADER_constant/__FixedBuffer0 +T: MojoShader/MOJOSHADER_constant/__FixedBuffer1 +T: MojoShader/MOJOSHADER_samplerType +T: MojoShader/MOJOSHADER_sampler +T: MojoShader/MOJOSHADER_samplerMap +T: MojoShader/MOJOSHADER_usage +T: MojoShader/MOJOSHADER_attribute +T: MojoShader/MOJOSHADER_swizzle +T: MojoShader/MOJOSHADER_swizzle/__FixedBuffer2 +T: MojoShader/MOJOSHADER_symbolRegisterSet +T: MojoShader/MOJOSHADER_symbolClass +T: MojoShader/MOJOSHADER_symbolType +T: MojoShader/MOJOSHADER_symbolTypeInfo +T: MojoShader/MOJOSHADER_symbolStructMember +T: MojoShader/MOJOSHADER_symbol +T: MojoShader/MOJOSHADER_error +T: MojoShader/MOJOSHADER_preshaderOpcode +T: MojoShader/MOJOSHADER_preshaderOperandType +T: MojoShader/MOJOSHADER_preshaderOperand +T: MojoShader/MOJOSHADER_preshaderInstruction +T: MojoShader/MOJOSHADER_preshader +T: MojoShader/MOJOSHADER_parseData +T: MojoShader/MOJOSHADER_renderStateType +T: MojoShader/MOJOSHADER_zBufferType +T: MojoShader/MOJOSHADER_fillMode +T: MojoShader/MOJOSHADER_shadeMode +T: MojoShader/MOJOSHADER_blendMode +T: MojoShader/MOJOSHADER_cullMode +T: MojoShader/MOJOSHADER_compareFunc +T: MojoShader/MOJOSHADER_fogMode +T: MojoShader/MOJOSHADER_stencilOp +T: MojoShader/MOJOSHADER_materialColorSource +T: MojoShader/MOJOSHADER_vertexBlendFlags +T: MojoShader/MOJOSHADER_patchedEdgeStyle +T: MojoShader/MOJOSHADER_debugMonitorTokens +T: MojoShader/MOJOSHADER_blendOp +T: MojoShader/MOJOSHADER_degreeType +T: MojoShader/MOJOSHADER_samplerStateType +T: MojoShader/MOJOSHADER_textureAddress +T: MojoShader/MOJOSHADER_textureFilterType +T: MojoShader/MOJOSHADER_effectValue +T: MojoShader/MOJOSHADER_effectState +T: MojoShader/MOJOSHADER_effectSamplerState +T: MojoShader/MOJOSHADER_effectAnnotation +T: MojoShader/MOJOSHADER_effectParam +T: MojoShader/MOJOSHADER_effectPass +T: MojoShader/MOJOSHADER_effectTechnique +T: MojoShader/MOJOSHADER_effectShader +T: MojoShader/MOJOSHADER_effectSamplerMap +T: MojoShader/MOJOSHADER_effectString +T: MojoShader/MOJOSHADER_effectTexture +T: MojoShader/MOJOSHADER_effectObject +T: MojoShader/MOJOSHADER_samplerStateRegister +T: MojoShader/MOJOSHADER_effectStateChanges +T: MojoShader/MOJOSHADER_effect +T: MojoShader/MOJOSHADER_glGetProcAddress + +R: Gendarme.Rules.Interoperability.CentralizePInvokesIntoNativeMethodsTypeRule +M: System.Int32 MojoShader::MOJOSHADER_version() +M: System.IntPtr MojoShader::MOJOSHADER_changeset() +M: System.Int32 MojoShader::MOJOSHADER_maxShaderModel(System.String) +M: System.IntPtr MojoShader::MOJOSHADER_parse(System.String,System.Byte[],System.UInt32,MojoShader/MOJOSHADER_swizzle[],System.UInt32,MojoShader/MOJOSHADER_samplerMap[],System.UInt32,MojoShader/MOJOSHADER_malloc,MojoShader/MOJOSHADER_free,System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_freeParseData(System.IntPtr) +M: System.IntPtr MojoShader::MOJOSHADER_parsePreshader(System.Byte[],System.UInt32,MojoShader/MOJOSHADER_malloc,MojoShader/MOJOSHADER_free,System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_freePreshader(System.IntPtr) +M: System.IntPtr MojoShader::MOJOSHADER_parseEffect(System.String,System.Byte[],System.UInt32,MojoShader/MOJOSHADER_swizzle[],System.UInt32,MojoShader/MOJOSHADER_samplerMap[],System.UInt32,MojoShader/MOJOSHADER_malloc,MojoShader/MOJOSHADER_free,System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_freeEffect(System.IntPtr) +M: System.IntPtr MojoShader::MOJOSHADER_cloneEffect(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_effectSetRawValueHandle(System.IntPtr,System.IntPtr,System.UInt32,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_effectSetRawValueName(System.IntPtr,System.String,System.IntPtr,System.UInt32,System.UInt32) +M: System.IntPtr MojoShader::MOJOSHADER_effectGetCurrentTechnique(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_effectSetTechnique(System.IntPtr,System.IntPtr) +M: System.IntPtr MojoShader::MOJOSHADER_effectFindNextValidTechnique(System.IntPtr,System.IntPtr) +M: System.IntPtr MojoShader::MOJOSHADER_glCompileEffect(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glDeleteEffect(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glEffectBegin(System.IntPtr,System.UInt32&,System.Int32,MojoShader/MOJOSHADER_effectStateChanges&) +M: System.Void MojoShader::MOJOSHADER_glEffectBeginPass(System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glEffectCommitChanges(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glEffectEndPass(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glEffectEnd(System.IntPtr) +M: System.Int32 MojoShader::MOJOSHADER_glAvailableProfiles(MojoShader/MOJOSHADER_glGetProcAddress,System.IntPtr,System.IntPtr,System.Int32,MojoShader/MOJOSHADER_malloc,MojoShader/MOJOSHADER_free,System.IntPtr) +M: System.IntPtr MojoShader::INTERNAL_glBestProfile(MojoShader/MOJOSHADER_glGetProcAddress,System.IntPtr,MojoShader/MOJOSHADER_malloc,MojoShader/MOJOSHADER_free,System.IntPtr) +M: System.IntPtr MojoShader::MOJOSHADER_glCreateContext(System.String,MojoShader/MOJOSHADER_glGetProcAddress,System.IntPtr,MojoShader/MOJOSHADER_malloc,MojoShader/MOJOSHADER_free,System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glMakeContextCurrent(System.IntPtr) +M: System.IntPtr MojoShader::INTERNAL_glGetError() +M: System.Int32 MojoShader::MOJOSHADER_glMaxUniforms(MojoShader/MOJOSHADER_shaderType) +M: System.IntPtr MojoShader::MOJOSHADER_glCompileShader(System.Byte[],System.UInt32,MojoShader/MOJOSHADER_swizzle[],System.UInt32,MojoShader/MOJOSHADER_samplerMap[],System.UInt32) +M: System.IntPtr MojoShader::MOJOSHADER_glGetShaderParseData(System.IntPtr) +M: System.IntPtr MojoShader::MOJOSHADER_glLinkProgram(System.IntPtr,System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glBindProgram(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glBindShaders(System.IntPtr,System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glSetVertexShaderUniformF(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glGetVertexShaderUniformF(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glSetVertexShaderUniformI(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glGetVertexShaderUniformI(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glSetVertexShaderUniformB(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glGetVertexShaderUniformB(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glSetPixelShaderUniformF(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glGetPixelShaderUniformF(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glSetPixelShaderUniformI(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glGetPixelShaderUniformI(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glSetPixelShaderUniformB(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glGetPixelShaderUniformB(System.UInt32,System.IntPtr,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glSetLegacyBumpMapEnv(System.UInt32,System.Single,System.Single,System.Single,System.Single,System.Single,System.Single) +M: System.Int32 MojoShader::MOJOSHADER_glGetVertexAttribLocation(MojoShader/MOJOSHADER_usage,System.Int32) +M: System.Void MojoShader::MOJOSHADER_glSetVertexAttribute(MojoShader/MOJOSHADER_usage,System.Int32,System.UInt32,MojoShader/MOJOSHADER_attributeType,System.Int32,System.UInt32,System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glSetVertexAttribDivisor(MojoShader/MOJOSHADER_usage,System.Int32,System.UInt32) +M: System.Void MojoShader::MOJOSHADER_glProgramReady() +M: System.Void MojoShader::MOJOSHADER_glProgramViewportFlip(System.Int32) +M: System.Void MojoShader::MOJOSHADER_glDeleteProgram(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glDeleteShader(System.IntPtr) +M: System.Void MojoShader::MOJOSHADER_glDestroyContext(System.IntPtr) + +R: Gendarme.Rules.Naming.DoNotPrefixValuesWithEnumNameRule +T: MojoShader/MOJOSHADER_usage +T: MojoShader/MOJOSHADER_stencilOp +T: MojoShader/MOJOSHADER_blendOp + +R: Gendarme.Rules.Design.MarkAssemblyWithAssemblyVersionRule +A: MojoShader-CS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + +R: Gendarme.Rules.Design.MarkAssemblyWithCLSCompliantRule +A: MojoShader-CS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + +R: Gendarme.Rules.Design.MarkAssemblyWithComVisibleRule +A: MojoShader-CS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + +R: Gendarme.Rules.Security.NativeFieldsShouldNotBeVisibleRule +T: MojoShader/MOJOSHADER_uniform +T: MojoShader/MOJOSHADER_sampler +T: MojoShader/MOJOSHADER_attribute +T: MojoShader/MOJOSHADER_symbolTypeInfo +T: MojoShader/MOJOSHADER_symbolStructMember +T: MojoShader/MOJOSHADER_symbol +T: MojoShader/MOJOSHADER_error +T: MojoShader/MOJOSHADER_preshader +T: MojoShader/MOJOSHADER_parseData +T: MojoShader/MOJOSHADER_effectValue +T: MojoShader/MOJOSHADER_effectAnnotation +T: MojoShader/MOJOSHADER_effectParam +T: MojoShader/MOJOSHADER_effectPass +T: MojoShader/MOJOSHADER_effectTechnique +T: MojoShader/MOJOSHADER_effectShader +T: MojoShader/MOJOSHADER_effectSamplerMap +T: MojoShader/MOJOSHADER_effectString +T: MojoShader/MOJOSHADER_samplerStateRegister +T: MojoShader/MOJOSHADER_effectStateChanges +T: MojoShader/MOJOSHADER_effect + +R: Gendarme.Rules.Naming.UseCorrectCasingRule +M: System.IntPtr MojoShader::MOJOSHADER_parseEffect(System.String,System.Byte[],System.UInt32,MojoShader/MOJOSHADER_swizzle[],System.UInt32,MojoShader/MOJOSHADER_samplerMap[],System.UInt32,MojoShader/MOJOSHADER_malloc,MojoShader/MOJOSHADER_free,System.IntPtr) + +R: Gendarme.Rules.Naming.UseCorrectSuffixRule +T: MojoShader/MOJOSHADER_attribute +T: MojoShader/MOJOSHADER_vertexBlendFlags + +R: Gendarme.Rules.Naming.UseSingularNameInEnumsUnlessAreFlagsRule +T: MojoShader/MOJOSHADER_symbolClass +T: MojoShader/MOJOSHADER_vertexBlendFlags +T: MojoShader/MOJOSHADER_debugMonitorTokens +T: MojoShader/MOJOSHADER_textureAddress + diff --git a/gendarme/openal.ignore b/gendarme/openal.ignore new file mode 100644 index 0000000..8e6b289 --- /dev/null +++ b/gendarme/openal.ignore @@ -0,0 +1,320 @@ +R: Gendarme.Rules.Naming.AvoidNonAlphanumericIdentifierRule +T: OpenAL.ALC10 +T: OpenAL.ALC11 +T: OpenAL.AL10 +T: OpenAL.AL11 +T: OpenAL.ALEXT +T: OpenAL.EFX + +R: Gendarme.Rules.BadPractice.AvoidVisibleConstantFieldRule +T: OpenAL.ALC10 +T: OpenAL.ALC11 +T: OpenAL.AL10 +T: OpenAL.AL11 +T: OpenAL.ALEXT +T: OpenAL.EFX + +R: Gendarme.Rules.Interoperability.CentralizePInvokesIntoNativeMethodsTypeRule +M: System.IntPtr OpenAL.ALC10::alcCreateContext(System.IntPtr,System.Int32[]) +M: System.Boolean OpenAL.ALC10::alcMakeContextCurrent(System.IntPtr) +M: System.Void OpenAL.ALC10::alcDestroyContext(System.IntPtr) +M: System.IntPtr OpenAL.ALC10::alcGetCurrentContext() +M: System.IntPtr OpenAL.ALC10::alcGetContextsDevice(System.IntPtr) +M: System.IntPtr OpenAL.ALC10::alcOpenDevice(System.String) +M: System.Boolean OpenAL.ALC10::alcCloseDevice(System.IntPtr) +M: System.Int32 OpenAL.ALC10::alcGetError(System.IntPtr) +M: System.IntPtr OpenAL.ALC10::alcGetProcAddress(System.IntPtr,System.String) +M: System.Int32 OpenAL.ALC10::alcGetEnumValue(System.IntPtr,System.String) +M: System.IntPtr OpenAL.ALC10::alcGetString(System.IntPtr,System.Int32) +M: System.Void OpenAL.ALC10::alcGetIntegerv(System.IntPtr,System.Int32,System.IntPtr,System.Int32[]) +M: System.Void OpenAL.ALC11::alcProcessContext(System.IntPtr) +M: System.Void OpenAL.ALC11::alcSuspendContext(System.IntPtr) +M: System.Boolean OpenAL.ALC11::alcIsExtensionPresent(System.IntPtr,System.String) +M: System.IntPtr OpenAL.ALC11::alcCaptureOpenDevice(System.String,System.UInt32,System.Int32,System.IntPtr) +M: System.Boolean OpenAL.ALC11::alcCaptureCloseDevice(System.IntPtr) +M: System.Void OpenAL.ALC11::alcCaptureStart(System.IntPtr) +M: System.Void OpenAL.ALC11::alcCaptureStop(System.IntPtr) +M: System.Void OpenAL.ALC11::alcCaptureSamples(System.IntPtr,System.IntPtr,System.IntPtr) +M: System.Void OpenAL.AL10::alDistanceModel(System.Int32) +M: System.Void OpenAL.AL10::alEnable(System.Int32) +M: System.Void OpenAL.AL10::alDisable(System.Int32) +M: System.Boolean OpenAL.AL10::alIsEnabled(System.Int32) +M: System.IntPtr OpenAL.AL10::INTERNAL_alGetString(System.Int32) +M: System.Void OpenAL.AL10::alGetBooleanv(System.Int32,System.Boolean[]) +M: System.Void OpenAL.AL10::alGetIntegerv(System.Int32,System.Int32[]) +M: System.Void OpenAL.AL10::alGetFloatv(System.Int32,System.Single[]) +M: System.Void OpenAL.AL10::alGetDoublev(System.Int32,System.Double[]) +M: System.Boolean OpenAL.AL10::alGetBoolean(System.Int32) +M: System.Int32 OpenAL.AL10::alGetInteger(System.Int32) +M: System.Single OpenAL.AL10::alGetFloat(System.Int32) +M: System.Double OpenAL.AL10::alGetDouble(System.Int32) +M: System.Int32 OpenAL.AL10::alGetError() +M: System.Boolean OpenAL.AL10::alIsExtensionPresent(System.String) +M: System.IntPtr OpenAL.AL10::alGetProcAddress(System.String) +M: System.Int32 OpenAL.AL10::alGetEnumValue(System.String) +M: System.Void OpenAL.AL10::alListenerf(System.Int32,System.Single) +M: System.Void OpenAL.AL10::alListener3f(System.Int32,System.Single,System.Single,System.Single) +M: System.Void OpenAL.AL10::alListenerfv(System.Int32,System.Single[]) +M: System.Void OpenAL.AL10::alListeneri(System.Int32,System.Int32) +M: System.Void OpenAL.AL10::alListener3i(System.Int32,System.Int32,System.Int32,System.Int32) +M: System.Void OpenAL.AL10::alListeneriv(System.Int32,System.Int32[]) +M: System.Void OpenAL.AL10::alGetListenerf(System.Int32,System.Single&) +M: System.Void OpenAL.AL10::alGetListener3f(System.Int32,System.Single&,System.Single&,System.Single&) +M: System.Void OpenAL.AL10::alGetListenerfv(System.Int32,System.Single[]) +M: System.Void OpenAL.AL10::alGetListeneri(System.Int32,System.Int32&) +M: System.Void OpenAL.AL10::alGetListener3i(System.Int32,System.Int32&,System.Int32&,System.Int32&) +M: System.Void OpenAL.AL10::alGetListeneriv(System.Int32,System.Int32[]) +M: System.Void OpenAL.AL10::alGenSources(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alGenSources(System.IntPtr,System.UInt32&) +M: System.Void OpenAL.AL10::alDeleteSources(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alDeleteSources(System.IntPtr,System.UInt32&) +M: System.Boolean OpenAL.AL10::alIsSource(System.UInt32) +M: System.Void OpenAL.AL10::alSourcef(System.UInt32,System.Int32,System.Single) +M: System.Void OpenAL.AL10::alSource3f(System.UInt32,System.Int32,System.Single,System.Single,System.Single) +M: System.Void OpenAL.AL10::alSourcefv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.AL10::alSourcei(System.UInt32,System.Int32,System.Int32) +M: System.Void OpenAL.AL10::alSource3i(System.UInt32,System.Int32,System.Int32,System.Int32,System.Int32) +M: System.Void OpenAL.AL10::alSourceiv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.AL10::alGetSourcef(System.UInt32,System.Int32,System.Single&) +M: System.Void OpenAL.AL10::alGetSource3f(System.UInt32,System.Int32,System.Single&,System.Single&,System.Single&) +M: System.Void OpenAL.AL10::alGetSourcefv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.AL10::alGetSourcei(System.UInt32,System.Int32,System.Int32&) +M: System.Void OpenAL.AL10::alGetSource3i(System.UInt32,System.Int32,System.Int32&,System.Int32&,System.Int32&) +M: System.Void OpenAL.AL10::alGetSourceiv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.AL10::alSourcePlayv(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alSourceStopv(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alSourceRewindv(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alSourcePausev(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alSourcePlay(System.UInt32) +M: System.Void OpenAL.AL10::alSourceStop(System.UInt32) +M: System.Void OpenAL.AL10::alSourceRewind(System.UInt32) +M: System.Void OpenAL.AL10::alSourcePause(System.UInt32) +M: System.Void OpenAL.AL10::alSourceQueueBuffers(System.UInt32,System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alSourceQueueBuffers(System.UInt32,System.IntPtr,System.UInt32&) +M: System.Void OpenAL.AL10::alSourceUnqueueBuffers(System.UInt32,System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alSourceUnqueueBuffers(System.UInt32,System.IntPtr,System.UInt32&) +M: System.Void OpenAL.AL10::alGenBuffers(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alGenBuffers(System.IntPtr,System.UInt32&) +M: System.Void OpenAL.AL10::alDeleteBuffers(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alDeleteBuffers(System.IntPtr,System.UInt32&) +M: System.Boolean OpenAL.AL10::alIsBuffer(System.UInt32) +M: System.Void OpenAL.AL10::alBufferData(System.UInt32,System.Int32,System.Byte[],System.IntPtr,System.IntPtr) +M: System.Void OpenAL.AL10::alBufferData(System.UInt32,System.Int32,System.Int16[],System.IntPtr,System.IntPtr) +M: System.Void OpenAL.AL10::alBufferData(System.UInt32,System.Int32,System.Single[],System.IntPtr,System.IntPtr) +M: System.Void OpenAL.AL10::alBufferf(System.UInt32,System.Int32,System.Single) +M: System.Void OpenAL.AL10::alBuffer3f(System.UInt32,System.Int32,System.Single,System.Single,System.Single) +M: System.Void OpenAL.AL10::alBufferfv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.AL10::alBufferi(System.UInt32,System.Int32,System.Int32) +M: System.Void OpenAL.AL10::alBuffer3i(System.UInt32,System.Int32,System.Int32,System.Int32,System.Int32) +M: System.Void OpenAL.AL10::alBufferiv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.AL10::alGetBufferf(System.UInt32,System.Int32,System.Single&) +M: System.Void OpenAL.AL10::alGetBuffer3f(System.UInt32,System.Int32,System.Single&,System.Single&,System.Single&) +M: System.Void OpenAL.AL10::alGetBufferfv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.AL10::alGetBufferi(System.UInt32,System.Int32,System.Int32&) +M: System.Void OpenAL.AL10::alGetBuffer3i(System.UInt32,System.Int32,System.Int32&,System.Int32&,System.Int32&) +M: System.Void OpenAL.AL10::alGetBufferiv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.ALEXT::alGetBufferSamplesSOFT(System.UInt32,System.Int32,System.Int32,System.Int32,System.Int32,System.IntPtr) +M: System.Void OpenAL.EFX::alGenEffects(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.EFX::alGenEffects(System.IntPtr,System.UInt32&) +M: System.Void OpenAL.EFX::alDeleteEffects(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.EFX::alDeleteEffects(System.IntPtr,System.UInt32&) +M: System.Boolean OpenAL.EFX::alIsEffect(System.UInt32) +M: System.Void OpenAL.EFX::alEffecti(System.UInt32,System.Int32,System.Int32) +M: System.Void OpenAL.EFX::alEffectiv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.EFX::alEffectf(System.UInt32,System.Int32,System.Single) +M: System.Void OpenAL.EFX::alEffectfv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.EFX::alGetEffecti(System.UInt32,System.Int32,System.Int32&) +M: System.Void OpenAL.EFX::alGetEffectiv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.EFX::alGetEffectf(System.UInt32,System.Int32,System.Single&) +M: System.Void OpenAL.EFX::alGetEffectfv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.EFX::alGenFilters(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.EFX::alGenFilters(System.IntPtr,System.UInt32&) +M: System.Void OpenAL.EFX::alDeleteFilters(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.EFX::alDeleteFilters(System.IntPtr,System.UInt32&) +M: System.Boolean OpenAL.EFX::alIsFilter(System.UInt32) +M: System.Void OpenAL.EFX::alFilteri(System.UInt32,System.Int32,System.Int32) +M: System.Void OpenAL.EFX::alFilteriv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.EFX::alFilterf(System.UInt32,System.Int32,System.Single) +M: System.Void OpenAL.EFX::alFilterfv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.EFX::alGetFilteri(System.UInt32,System.Int32,System.Int32&) +M: System.Void OpenAL.EFX::alGetFilteriv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.EFX::alGetFilterf(System.UInt32,System.Int32,System.Single&) +M: System.Void OpenAL.EFX::alGetFilterfv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.EFX::alGenAuxiliaryEffectSlots(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.EFX::alGenAuxiliaryEffectSlots(System.IntPtr,System.UInt32&) +M: System.Void OpenAL.EFX::alDeleteAuxiliaryEffectSlots(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.EFX::alDeleteAuxiliaryEffectSlots(System.IntPtr,System.UInt32&) +M: System.Boolean OpenAL.EFX::alIsAuxiliaryEffectSlot(System.UInt32) +M: System.Void OpenAL.EFX::alAuxiliaryEffectSloti(System.UInt32,System.Int32,System.Int32) +M: System.Void OpenAL.EFX::alAuxiliaryEffectSlotiv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.EFX::alAuxiliaryEffectSlotf(System.UInt32,System.Int32,System.Single) +M: System.Void OpenAL.EFX::alAuxiliaryEffectSlotfv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.EFX::alGetAuxiliaryEffectSloti(System.UInt32,System.Int32,System.Int32&) +M: System.Void OpenAL.EFX::alGetAuxiliaryEffectSlotiv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.EFX::alGetAuxiliaryEffectSlotf(System.UInt32,System.Int32,System.Single&) +M: System.Void OpenAL.EFX::alGetAuxiliaryEffectSlotfv(System.UInt32,System.Int32,System.Single[]) + +R: Gendarme.Rules.Design.MarkAssemblyWithAssemblyVersionRule +A: OpenAL-CS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + +R: Gendarme.Rules.Design.MarkAssemblyWithCLSCompliantRule +A: OpenAL-CS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + +R: Gendarme.Rules.Design.MarkAssemblyWithComVisibleRule +A: OpenAL-CS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + +R: Gendarme.Rules.Interoperability.MarshalBooleansInPInvokeDeclarationsRule +M: System.Boolean OpenAL.ALC10::alcMakeContextCurrent(System.IntPtr) +M: System.Boolean OpenAL.ALC10::alcCloseDevice(System.IntPtr) +M: System.Boolean OpenAL.ALC11::alcIsExtensionPresent(System.IntPtr,System.String) +M: System.Boolean OpenAL.ALC11::alcCaptureCloseDevice(System.IntPtr) +M: System.Boolean OpenAL.AL10::alIsEnabled(System.Int32) +M: System.Void OpenAL.AL10::alGetBooleanv(System.Int32,System.Boolean[]) +M: System.Boolean OpenAL.AL10::alGetBoolean(System.Int32) +M: System.Boolean OpenAL.AL10::alIsExtensionPresent(System.String) +M: System.Boolean OpenAL.AL10::alIsSource(System.UInt32) +M: System.Boolean OpenAL.AL10::alIsBuffer(System.UInt32) +M: System.Boolean OpenAL.EFX::alIsEffect(System.UInt32) +M: System.Boolean OpenAL.EFX::alIsFilter(System.UInt32) +M: System.Boolean OpenAL.EFX::alIsAuxiliaryEffectSlot(System.UInt32) + +R: Gendarme.Rules.Naming.UseCorrectCasingRule +M: System.IntPtr OpenAL.ALC10::alcCreateContext(System.IntPtr,System.Int32[]) +M: System.Boolean OpenAL.ALC10::alcMakeContextCurrent(System.IntPtr) +M: System.Void OpenAL.ALC10::alcDestroyContext(System.IntPtr) +M: System.IntPtr OpenAL.ALC10::alcGetCurrentContext() +M: System.IntPtr OpenAL.ALC10::alcGetContextsDevice(System.IntPtr) +M: System.IntPtr OpenAL.ALC10::alcOpenDevice(System.String) +M: System.Boolean OpenAL.ALC10::alcCloseDevice(System.IntPtr) +M: System.Int32 OpenAL.ALC10::alcGetError(System.IntPtr) +M: System.IntPtr OpenAL.ALC10::alcGetProcAddress(System.IntPtr,System.String) +M: System.Int32 OpenAL.ALC10::alcGetEnumValue(System.IntPtr,System.String) +M: System.IntPtr OpenAL.ALC10::alcGetString(System.IntPtr,System.Int32) +M: System.Void OpenAL.ALC10::alcGetIntegerv(System.IntPtr,System.Int32,System.IntPtr,System.Int32[]) +M: System.Void OpenAL.ALC11::alcProcessContext(System.IntPtr) +M: System.Void OpenAL.ALC11::alcSuspendContext(System.IntPtr) +M: System.Boolean OpenAL.ALC11::alcIsExtensionPresent(System.IntPtr,System.String) +M: System.IntPtr OpenAL.ALC11::alcCaptureOpenDevice(System.String,System.UInt32,System.Int32,System.IntPtr) +M: System.Boolean OpenAL.ALC11::alcCaptureCloseDevice(System.IntPtr) +M: System.Void OpenAL.ALC11::alcCaptureStart(System.IntPtr) +M: System.Void OpenAL.ALC11::alcCaptureStop(System.IntPtr) +M: System.Void OpenAL.ALC11::alcCaptureSamples(System.IntPtr,System.IntPtr,System.IntPtr) +M: System.Void OpenAL.AL10::alDistanceModel(System.Int32) +M: System.Void OpenAL.AL10::alEnable(System.Int32) +M: System.Void OpenAL.AL10::alDisable(System.Int32) +M: System.Boolean OpenAL.AL10::alIsEnabled(System.Int32) +M: System.String OpenAL.AL10::alGetString(System.Int32) +M: System.Void OpenAL.AL10::alGetBooleanv(System.Int32,System.Boolean[]) +M: System.Void OpenAL.AL10::alGetIntegerv(System.Int32,System.Int32[]) +M: System.Void OpenAL.AL10::alGetFloatv(System.Int32,System.Single[]) +M: System.Void OpenAL.AL10::alGetDoublev(System.Int32,System.Double[]) +M: System.Boolean OpenAL.AL10::alGetBoolean(System.Int32) +M: System.Int32 OpenAL.AL10::alGetInteger(System.Int32) +M: System.Single OpenAL.AL10::alGetFloat(System.Int32) +M: System.Double OpenAL.AL10::alGetDouble(System.Int32) +M: System.Int32 OpenAL.AL10::alGetError() +M: System.Boolean OpenAL.AL10::alIsExtensionPresent(System.String) +M: System.IntPtr OpenAL.AL10::alGetProcAddress(System.String) +M: System.Int32 OpenAL.AL10::alGetEnumValue(System.String) +M: System.Void OpenAL.AL10::alListenerf(System.Int32,System.Single) +M: System.Void OpenAL.AL10::alListener3f(System.Int32,System.Single,System.Single,System.Single) +M: System.Void OpenAL.AL10::alListenerfv(System.Int32,System.Single[]) +M: System.Void OpenAL.AL10::alListeneri(System.Int32,System.Int32) +M: System.Void OpenAL.AL10::alListener3i(System.Int32,System.Int32,System.Int32,System.Int32) +M: System.Void OpenAL.AL10::alListeneriv(System.Int32,System.Int32[]) +M: System.Void OpenAL.AL10::alGetListenerf(System.Int32,System.Single&) +M: System.Void OpenAL.AL10::alGetListener3f(System.Int32,System.Single&,System.Single&,System.Single&) +M: System.Void OpenAL.AL10::alGetListenerfv(System.Int32,System.Single[]) +M: System.Void OpenAL.AL10::alGetListeneri(System.Int32,System.Int32&) +M: System.Void OpenAL.AL10::alGetListener3i(System.Int32,System.Int32&,System.Int32&,System.Int32&) +M: System.Void OpenAL.AL10::alGetListeneriv(System.Int32,System.Int32[]) +M: System.Void OpenAL.AL10::alGenSources(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alGenSources(System.IntPtr,System.UInt32&) +M: System.Void OpenAL.AL10::alDeleteSources(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alDeleteSources(System.IntPtr,System.UInt32&) +M: System.Boolean OpenAL.AL10::alIsSource(System.UInt32) +M: System.Void OpenAL.AL10::alSourcef(System.UInt32,System.Int32,System.Single) +M: System.Void OpenAL.AL10::alSource3f(System.UInt32,System.Int32,System.Single,System.Single,System.Single) +M: System.Void OpenAL.AL10::alSourcefv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.AL10::alSourcei(System.UInt32,System.Int32,System.Int32) +M: System.Void OpenAL.AL10::alSource3i(System.UInt32,System.Int32,System.Int32,System.Int32,System.Int32) +M: System.Void OpenAL.AL10::alSourceiv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.AL10::alGetSourcef(System.UInt32,System.Int32,System.Single&) +M: System.Void OpenAL.AL10::alGetSource3f(System.UInt32,System.Int32,System.Single&,System.Single&,System.Single&) +M: System.Void OpenAL.AL10::alGetSourcefv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.AL10::alGetSourcei(System.UInt32,System.Int32,System.Int32&) +M: System.Void OpenAL.AL10::alGetSource3i(System.UInt32,System.Int32,System.Int32&,System.Int32&,System.Int32&) +M: System.Void OpenAL.AL10::alGetSourceiv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.AL10::alSourcePlayv(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alSourceStopv(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alSourceRewindv(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alSourcePausev(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alSourcePlay(System.UInt32) +M: System.Void OpenAL.AL10::alSourceStop(System.UInt32) +M: System.Void OpenAL.AL10::alSourceRewind(System.UInt32) +M: System.Void OpenAL.AL10::alSourcePause(System.UInt32) +M: System.Void OpenAL.AL10::alSourceQueueBuffers(System.UInt32,System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alSourceQueueBuffers(System.UInt32,System.IntPtr,System.UInt32&) +M: System.Void OpenAL.AL10::alSourceUnqueueBuffers(System.UInt32,System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alSourceUnqueueBuffers(System.UInt32,System.IntPtr,System.UInt32&) +M: System.Void OpenAL.AL10::alGenBuffers(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alGenBuffers(System.IntPtr,System.UInt32&) +M: System.Void OpenAL.AL10::alDeleteBuffers(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.AL10::alDeleteBuffers(System.IntPtr,System.UInt32&) +M: System.Boolean OpenAL.AL10::alIsBuffer(System.UInt32) +M: System.Void OpenAL.AL10::alBufferData(System.UInt32,System.Int32,System.Byte[],System.IntPtr,System.IntPtr) +M: System.Void OpenAL.AL10::alBufferData(System.UInt32,System.Int32,System.Int16[],System.IntPtr,System.IntPtr) +M: System.Void OpenAL.AL10::alBufferData(System.UInt32,System.Int32,System.Single[],System.IntPtr,System.IntPtr) +M: System.Void OpenAL.AL10::alBufferf(System.UInt32,System.Int32,System.Single) +M: System.Void OpenAL.AL10::alBuffer3f(System.UInt32,System.Int32,System.Single,System.Single,System.Single) +M: System.Void OpenAL.AL10::alBufferfv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.AL10::alBufferi(System.UInt32,System.Int32,System.Int32) +M: System.Void OpenAL.AL10::alBuffer3i(System.UInt32,System.Int32,System.Int32,System.Int32,System.Int32) +M: System.Void OpenAL.AL10::alBufferiv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.AL10::alGetBufferf(System.UInt32,System.Int32,System.Single&) +M: System.Void OpenAL.AL10::alGetBuffer3f(System.UInt32,System.Int32,System.Single&,System.Single&,System.Single&) +M: System.Void OpenAL.AL10::alGetBufferfv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.AL10::alGetBufferi(System.UInt32,System.Int32,System.Int32&) +M: System.Void OpenAL.AL10::alGetBuffer3i(System.UInt32,System.Int32,System.Int32&,System.Int32&,System.Int32&) +M: System.Void OpenAL.AL10::alGetBufferiv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.ALEXT::alGetBufferSamplesSOFT(System.UInt32,System.Int32,System.Int32,System.Int32,System.Int32,System.IntPtr) +M: System.Void OpenAL.EFX::alGenEffects(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.EFX::alGenEffects(System.IntPtr,System.UInt32&) +M: System.Void OpenAL.EFX::alDeleteEffects(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.EFX::alDeleteEffects(System.IntPtr,System.UInt32&) +M: System.Boolean OpenAL.EFX::alIsEffect(System.UInt32) +M: System.Void OpenAL.EFX::alEffecti(System.UInt32,System.Int32,System.Int32) +M: System.Void OpenAL.EFX::alEffectiv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.EFX::alEffectf(System.UInt32,System.Int32,System.Single) +M: System.Void OpenAL.EFX::alEffectfv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.EFX::alGetEffecti(System.UInt32,System.Int32,System.Int32&) +M: System.Void OpenAL.EFX::alGetEffectiv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.EFX::alGetEffectf(System.UInt32,System.Int32,System.Single&) +M: System.Void OpenAL.EFX::alGetEffectfv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.EFX::alGenFilters(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.EFX::alGenFilters(System.IntPtr,System.UInt32&) +M: System.Void OpenAL.EFX::alDeleteFilters(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.EFX::alDeleteFilters(System.IntPtr,System.UInt32&) +M: System.Boolean OpenAL.EFX::alIsFilter(System.UInt32) +M: System.Void OpenAL.EFX::alFilteri(System.UInt32,System.Int32,System.Int32) +M: System.Void OpenAL.EFX::alFilteriv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.EFX::alFilterf(System.UInt32,System.Int32,System.Single) +M: System.Void OpenAL.EFX::alFilterfv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.EFX::alGetFilteri(System.UInt32,System.Int32,System.Int32&) +M: System.Void OpenAL.EFX::alGetFilteriv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.EFX::alGetFilterf(System.UInt32,System.Int32,System.Single&) +M: System.Void OpenAL.EFX::alGetFilterfv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.EFX::alGenAuxiliaryEffectSlots(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.EFX::alGenAuxiliaryEffectSlots(System.IntPtr,System.UInt32&) +M: System.Void OpenAL.EFX::alDeleteAuxiliaryEffectSlots(System.IntPtr,System.UInt32[]) +M: System.Void OpenAL.EFX::alDeleteAuxiliaryEffectSlots(System.IntPtr,System.UInt32&) +M: System.Boolean OpenAL.EFX::alIsAuxiliaryEffectSlot(System.UInt32) +M: System.Void OpenAL.EFX::alAuxiliaryEffectSloti(System.UInt32,System.Int32,System.Int32) +M: System.Void OpenAL.EFX::alAuxiliaryEffectSlotiv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.EFX::alAuxiliaryEffectSlotf(System.UInt32,System.Int32,System.Single) +M: System.Void OpenAL.EFX::alAuxiliaryEffectSlotfv(System.UInt32,System.Int32,System.Single[]) +M: System.Void OpenAL.EFX::alGetAuxiliaryEffectSloti(System.UInt32,System.Int32,System.Int32&) +M: System.Void OpenAL.EFX::alGetAuxiliaryEffectSlotiv(System.UInt32,System.Int32,System.Int32[]) +M: System.Void OpenAL.EFX::alGetAuxiliaryEffectSlotf(System.UInt32,System.Int32,System.Single&) +M: System.Void OpenAL.EFX::alGetAuxiliaryEffectSlotfv(System.UInt32,System.Int32,System.Single[]) + diff --git a/gendarme/runGendarme.sh b/gendarme/runGendarme.sh new file mode 100755 index 0000000..9019789 --- /dev/null +++ b/gendarme/runGendarme.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# Filename of the FNA assembly output +ASSEMBLYNAME="../bin/Debug/FNA.dll" + +# Move to script's directory +cd "`dirname "$0"`" + +# Run Gendarme using the FNA ruleset +gendarme --ignore fna.ignore --html gendarme.html $ASSEMBLYNAME diff --git a/gendarme/sdl2.ignore b/gendarme/sdl2.ignore new file mode 100644 index 0000000..55a1ea1 --- /dev/null +++ b/gendarme/sdl2.ignore @@ -0,0 +1,1527 @@ +R: Gendarme.Rules.Design.Generic.AvoidDeclaringCustomDelegatesRule +T: SDL2.SDL/SDL_LogOutputFunction +T: SDL2.SDL/SDL_EventFilter +T: SDL2.SDL/SDL_AudioCallback +T: SDL2.SDL/SDL_TimerCallback +T: SDL2.SDL_mixer/MixFuncDelegate +T: SDL2.SDL_mixer/Mix_EffectFunc_t +T: SDL2.SDL_mixer/Mix_EffectDone_t +T: SDL2.SDL_mixer/MusicFinishedDelegate +T: SDL2.SDL_mixer/ChannelFinishedDelegate +T: SDL2.SDL_mixer/SoundFontDelegate + +R: Gendarme.Rules.Performance.AvoidLargeStructureRule +T: SDL2.SDL/SDL_PixelFormat +T: SDL2.SDL/SDL_Surface +T: SDL2.SDL/SDL_MouseMotionEvent +T: SDL2.SDL/SDL_TouchFingerEvent +T: SDL2.SDL/SDL_MultiGestureEvent +T: SDL2.SDL/SDL_DollarGestureEvent +T: SDL2.SDL/SDL_Event +T: SDL2.SDL/SDL_HapticPeriodic +T: SDL2.SDL/SDL_HapticCondition +T: SDL2.SDL/SDL_HapticRamp +T: SDL2.SDL/SDL_HapticCustom +T: SDL2.SDL/SDL_HapticEffect +T: SDL2.SDL/SDL_SysWMinfo + +R: Gendarme.Rules.Naming.AvoidNonAlphanumericIdentifierRule +T: SDL2.SDL +M: System.UInt32 SDL2.SDL::SDL_FOURCC(System.Byte,System.Byte,System.Byte,System.Byte) +M: System.IntPtr SDL2.SDL::SDL_RWFromMem(System.Byte[],System.Int32) +M: System.Void SDL2.SDL::SDL_SetMainReady() +M: System.Int32 SDL2.SDL::SDL_Init(System.UInt32) +M: System.Int32 SDL2.SDL::SDL_InitSubSystem(System.UInt32) +M: System.Void SDL2.SDL::SDL_Quit() +M: System.Void SDL2.SDL::SDL_QuitSubSystem(System.UInt32) +M: System.UInt32 SDL2.SDL::SDL_WasInit(System.UInt32) +M: System.String SDL2.SDL::SDL_GetPlatform() +M: System.Void SDL2.SDL::SDL_ClearHints() +M: System.String SDL2.SDL::SDL_GetHint(System.String) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_SetHint(System.String,System.String) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_SetHintWithPriority(System.String,System.String,SDL2.SDL/SDL_HintPriority) +M: System.Void SDL2.SDL::SDL_ClearError() +M: System.String SDL2.SDL::SDL_GetError() +M: System.Void SDL2.SDL::SDL_SetError(System.String) +M: System.Void SDL2.SDL::SDL_Log(System.String) +M: System.Void SDL2.SDL::SDL_LogVerbose(System.Int32,System.String) +M: System.Void SDL2.SDL::SDL_LogDebug(System.Int32,System.String) +M: System.Void SDL2.SDL::SDL_LogInfo(System.Int32,System.String) +M: System.Void SDL2.SDL::SDL_LogWarn(System.Int32,System.String) +M: System.Void SDL2.SDL::SDL_LogError(System.Int32,System.String) +M: System.Void SDL2.SDL::SDL_LogCritical(System.Int32,System.String) +M: System.Void SDL2.SDL::SDL_LogMessage(System.Int32,SDL2.SDL/SDL_LogPriority,System.String) +M: System.Void SDL2.SDL::SDL_LogMessageV(System.Int32,SDL2.SDL/SDL_LogPriority,System.String) +M: SDL2.SDL/SDL_LogPriority SDL2.SDL::SDL_LogGetPriority(System.Int32) +M: System.Void SDL2.SDL::SDL_LogSetPriority(System.Int32,SDL2.SDL/SDL_LogPriority) +M: System.Void SDL2.SDL::SDL_LogSetAllPriority(SDL2.SDL/SDL_LogPriority) +M: System.Void SDL2.SDL::SDL_LogResetPriorities() +M: System.Void SDL2.SDL::SDL_LogGetOutputFunction(SDL2.SDL/SDL_LogOutputFunction&,System.IntPtr&) +M: System.Void SDL2.SDL::SDL_LogSetOutputFunction(SDL2.SDL/SDL_LogOutputFunction,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_ShowMessageBox(SDL2.SDL/SDL_MessageBoxData&,System.Int32&) +M: System.Int32 SDL2.SDL::SDL_ShowSimpleMessageBox(SDL2.SDL/SDL_MessageBoxFlags,System.String,System.String,System.IntPtr) +M: System.Void SDL2.SDL::SDL_VERSION(SDL2.SDL/SDL_version&) +M: System.Int32 SDL2.SDL::SDL_VERSIONNUM(System.Int32,System.Int32,System.Int32) +M: System.Boolean SDL2.SDL::SDL_VERSION_ATLEAST(System.Int32,System.Int32,System.Int32) +M: System.Void SDL2.SDL::SDL_GetVersion(SDL2.SDL/SDL_version&) +M: System.String SDL2.SDL::SDL_GetRevision() +M: System.Int32 SDL2.SDL::SDL_GetRevisionNumber() +M: System.Int32 SDL2.SDL::SDL_WINDOWPOS_UNDEFINED_DISPLAY(System.Int32) +M: System.Boolean SDL2.SDL::SDL_WINDOWPOS_ISUNDEFINED(System.Int32) +M: System.Int32 SDL2.SDL::SDL_WINDOWPOS_CENTERED_DISPLAY(System.Int32) +M: System.Boolean SDL2.SDL::SDL_WINDOWPOS_ISCENTERED(System.Int32) +M: System.IntPtr SDL2.SDL::SDL_CreateWindow(System.String,System.Int32,System.Int32,System.Int32,System.Int32,SDL2.SDL/SDL_WindowFlags) +M: System.Int32 SDL2.SDL::SDL_CreateWindowAndRenderer(System.Int32,System.Int32,SDL2.SDL/SDL_WindowFlags,System.IntPtr&,System.IntPtr&) +M: System.IntPtr SDL2.SDL::SDL_CreateWindowFrom(System.IntPtr) +M: System.Void SDL2.SDL::SDL_DestroyWindow(System.IntPtr) +M: System.Void SDL2.SDL::SDL_DisableScreenSaver() +M: System.Void SDL2.SDL::SDL_EnableScreenSaver() +M: System.IntPtr SDL2.SDL::SDL_GetClosestDisplayMode(System.Int32,SDL2.SDL/SDL_DisplayMode&,SDL2.SDL/SDL_DisplayMode&) +M: System.Int32 SDL2.SDL::SDL_GetCurrentDisplayMode(System.Int32,SDL2.SDL/SDL_DisplayMode&) +M: System.String SDL2.SDL::SDL_GetCurrentVideoDriver() +M: System.Int32 SDL2.SDL::SDL_GetDesktopDisplayMode(System.Int32,SDL2.SDL/SDL_DisplayMode&) +M: System.Int32 SDL2.SDL::SDL_GetDisplayBounds(System.Int32,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_GetDisplayMode(System.Int32,System.Int32,SDL2.SDL/SDL_DisplayMode&) +M: System.Int32 SDL2.SDL::SDL_GetNumDisplayModes(System.Int32) +M: System.Int32 SDL2.SDL::SDL_GetNumVideoDisplays() +M: System.Int32 SDL2.SDL::SDL_GetNumVideoDrivers() +M: System.String SDL2.SDL::SDL_GetVideoDriver(System.Int32) +M: System.Single SDL2.SDL::SDL_GetWindowBrightness(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_GetWindowData(System.IntPtr,System.String) +M: System.Int32 SDL2.SDL::SDL_GetWindowDisplayIndex(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_GetWindowDisplayMode(System.IntPtr,SDL2.SDL/SDL_DisplayMode&) +M: System.UInt32 SDL2.SDL::SDL_GetWindowFlags(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_GetWindowFromID(System.UInt32) +M: System.Int32 SDL2.SDL::SDL_GetWindowGammaRamp(System.IntPtr,System.UInt16[],System.UInt16[],System.UInt16[]) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_GetWindowGrab(System.IntPtr) +M: System.UInt32 SDL2.SDL::SDL_GetWindowID(System.IntPtr) +M: System.UInt32 SDL2.SDL::SDL_GetWindowPixelFormat(System.IntPtr) +M: System.Void SDL2.SDL::SDL_GetWindowMaximumSize(System.IntPtr,System.Int32&,System.Int32&) +M: System.Void SDL2.SDL::SDL_GetWindowMinimumSize(System.IntPtr,System.Int32&,System.Int32&) +M: System.Void SDL2.SDL::SDL_GetWindowPosition(System.IntPtr,System.Int32&,System.Int32&) +M: System.Void SDL2.SDL::SDL_GetWindowSize(System.IntPtr,System.Int32&,System.Int32&) +M: System.IntPtr SDL2.SDL::SDL_GetWindowSurface(System.IntPtr) +M: System.String SDL2.SDL::SDL_GetWindowTitle(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_GL_BindTexture(System.IntPtr,System.Single&,System.Single&) +M: System.IntPtr SDL2.SDL::SDL_GL_CreateContext(System.IntPtr) +M: System.Void SDL2.SDL::SDL_GL_DeleteContext(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_GL_GetProcAddress(System.String) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_GL_ExtensionSupported(System.String) +M: System.Void SDL2.SDL::SDL_GL_ResetAttributes() +M: System.Int32 SDL2.SDL::SDL_GL_GetAttribute(SDL2.SDL/SDL_GLattr,System.Int32&) +M: System.Int32 SDL2.SDL::SDL_GL_GetSwapInterval() +M: System.Int32 SDL2.SDL::SDL_GL_MakeCurrent(System.IntPtr,System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_GL_GetCurrentWindow() +M: System.IntPtr SDL2.SDL::SDL_GL_GetCurrentContext() +M: System.Void SDL2.SDL::SDL_GL_GetDrawableSize(System.IntPtr,System.Int32&,System.Int32&) +M: System.Int32 SDL2.SDL::SDL_GL_SetAttribute(SDL2.SDL/SDL_GLattr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_GL_SetSwapInterval(System.Int32) +M: System.Void SDL2.SDL::SDL_GL_SwapWindow(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_GL_UnbindTexture(System.IntPtr) +M: System.Void SDL2.SDL::SDL_HideWindow(System.IntPtr) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_IsScreenSaverEnabled() +M: System.Void SDL2.SDL::SDL_MaximizeWindow(System.IntPtr) +M: System.Void SDL2.SDL::SDL_MinimizeWindow(System.IntPtr) +M: System.Void SDL2.SDL::SDL_RaiseWindow(System.IntPtr) +M: System.Void SDL2.SDL::SDL_RestoreWindow(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_SetWindowBrightness(System.IntPtr,System.Single) +M: System.IntPtr SDL2.SDL::SDL_SetWindowData(System.IntPtr,System.String,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_SetWindowDisplayMode(System.IntPtr,SDL2.SDL/SDL_DisplayMode&) +M: System.Int32 SDL2.SDL::SDL_SetWindowFullscreen(System.IntPtr,System.UInt32) +M: System.Int32 SDL2.SDL::SDL_SetWindowGammaRamp(System.IntPtr,System.UInt16[],System.UInt16[],System.UInt16[]) +M: System.Void SDL2.SDL::SDL_SetWindowGrab(System.IntPtr,SDL2.SDL/SDL_bool) +M: System.Void SDL2.SDL::SDL_SetWindowIcon(System.IntPtr,System.IntPtr) +M: System.Void SDL2.SDL::SDL_SetWindowMaximumSize(System.IntPtr,System.Int32,System.Int32) +M: System.Void SDL2.SDL::SDL_SetWindowMinimumSize(System.IntPtr,System.Int32,System.Int32) +M: System.Void SDL2.SDL::SDL_SetWindowPosition(System.IntPtr,System.Int32,System.Int32) +M: System.Void SDL2.SDL::SDL_SetWindowSize(System.IntPtr,System.Int32,System.Int32) +M: System.Void SDL2.SDL::SDL_SetWindowBordered(System.IntPtr,SDL2.SDL/SDL_bool) +M: System.Void SDL2.SDL::SDL_SetWindowTitle(System.IntPtr,System.String) +M: System.Void SDL2.SDL::SDL_ShowWindow(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_UpdateWindowSurface(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_UpdateWindowSurfaceRects(System.IntPtr,SDL2.SDL/SDL_Rect[],System.Int32) +M: System.Int32 SDL2.SDL::SDL_VideoInit(System.String) +M: System.Void SDL2.SDL::SDL_VideoQuit() +M: System.IntPtr SDL2.SDL::SDL_CreateRenderer(System.IntPtr,System.Int32,SDL2.SDL/SDL_RendererFlags) +M: System.IntPtr SDL2.SDL::SDL_CreateSoftwareRenderer(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_CreateTexture(System.IntPtr,System.UInt32,System.Int32,System.Int32,System.Int32) +M: System.IntPtr SDL2.SDL::SDL_CreateTextureFromSurface(System.IntPtr,System.IntPtr) +M: System.Void SDL2.SDL::SDL_DestroyRenderer(System.IntPtr) +M: System.Void SDL2.SDL::SDL_DestroyTexture(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_GetNumRenderDrivers() +M: System.Int32 SDL2.SDL::SDL_GetRenderDrawBlendMode(System.IntPtr,SDL2.SDL/SDL_BlendMode&) +M: System.Int32 SDL2.SDL::SDL_GetRenderDrawColor(System.IntPtr,System.Byte&,System.Byte&,System.Byte&,System.Byte&) +M: System.Int32 SDL2.SDL::SDL_GetRenderDriverInfo(System.Int32,SDL2.SDL/SDL_RendererInfo&) +M: System.IntPtr SDL2.SDL::SDL_GetRenderer(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_GetRendererInfo(System.IntPtr,SDL2.SDL/SDL_RendererInfo&) +M: System.Int32 SDL2.SDL::SDL_GetRendererOutputSize(System.IntPtr,System.Int32&,System.Int32&) +M: System.Int32 SDL2.SDL::SDL_GetTextureAlphaMod(System.IntPtr,System.Byte&) +M: System.Int32 SDL2.SDL::SDL_GetTextureBlendMode(System.IntPtr,SDL2.SDL/SDL_BlendMode&) +M: System.Int32 SDL2.SDL::SDL_GetTextureColorMod(System.IntPtr,System.Byte&,System.Byte&,System.Byte&) +M: System.Int32 SDL2.SDL::SDL_LockTexture(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr&,System.Int32&) +M: System.Int32 SDL2.SDL::SDL_LockTexture(System.IntPtr,System.IntPtr,System.IntPtr&,System.Int32&) +M: System.Int32 SDL2.SDL::SDL_QueryTexture(System.IntPtr,System.UInt32&,System.Int32&,System.Int32&,System.Int32&) +M: System.Int32 SDL2.SDL::SDL_QueryTexturePixels(System.IntPtr,System.IntPtr&,System.Int32&) +M: System.Int32 SDL2.SDL::SDL_RenderClear(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_RenderCopy(System.IntPtr,System.IntPtr,SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_RenderCopy(System.IntPtr,System.IntPtr,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_RenderCopy(System.IntPtr,System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_RenderCopy(System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_RenderCopyEx(System.IntPtr,System.IntPtr,SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&,System.Double,SDL2.SDL/SDL_Point&,SDL2.SDL/SDL_RendererFlip) +M: System.Int32 SDL2.SDL::SDL_RenderDrawLine(System.IntPtr,System.Int32,System.Int32,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL::SDL_RenderDrawLines(System.IntPtr,SDL2.SDL/SDL_Point[],System.Int32) +M: System.Int32 SDL2.SDL::SDL_RenderDrawPoint(System.IntPtr,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL::SDL_RenderDrawPoints(System.IntPtr,SDL2.SDL/SDL_Point[],System.Int32) +M: System.Int32 SDL2.SDL::SDL_RenderDrawRect(System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_RenderDrawRect(System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_RenderDrawRects(System.IntPtr,SDL2.SDL/SDL_Rect[],System.Int32) +M: System.Int32 SDL2.SDL::SDL_RenderFillRect(System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_RenderFillRect(System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_RenderFillRects(System.IntPtr,SDL2.SDL/SDL_Rect[],System.Int32) +M: System.Void SDL2.SDL::SDL_RenderGetClipRect(System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Void SDL2.SDL::SDL_RenderGetLogicalSize(System.IntPtr,System.Int32&,System.Int32&) +M: System.Void SDL2.SDL::SDL_RenderGetScale(System.IntPtr,System.Single&,System.Single&) +M: System.Int32 SDL2.SDL::SDL_RenderGetViewport(System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Void SDL2.SDL::SDL_RenderPresent(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_RenderReadPixels(System.IntPtr,SDL2.SDL/SDL_Rect&,System.UInt32,System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_RenderSetClipRect(System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_RenderSetClipRect(System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_RenderSetLogicalSize(System.IntPtr,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL::SDL_RenderSetScale(System.IntPtr,System.Single,System.Single) +M: System.Int32 SDL2.SDL::SDL_RenderSetViewport(System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_SetRenderDrawBlendMode(System.IntPtr,SDL2.SDL/SDL_BlendMode) +M: System.Int32 SDL2.SDL::SDL_SetRenderDrawColor(System.IntPtr,System.Byte,System.Byte,System.Byte,System.Byte) +M: System.Int32 SDL2.SDL::SDL_SetRenderTarget(System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_SetTextureAlphaMod(System.IntPtr,System.Byte) +M: System.Int32 SDL2.SDL::SDL_SetTextureBlendMode(System.IntPtr,SDL2.SDL/SDL_BlendMode) +M: System.Int32 SDL2.SDL::SDL_SetTextureColorMod(System.IntPtr,System.Byte,System.Byte,System.Byte) +M: System.Void SDL2.SDL::SDL_UnlockTexture(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_UpdateTexture(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,System.Int32) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_RenderTargetSupported(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_GetRenderTarget(System.IntPtr) +M: System.UInt32 SDL2.SDL::SDL_DEFINE_PIXELFOURCC(System.Byte,System.Byte,System.Byte,System.Byte) +M: System.UInt32 SDL2.SDL::SDL_DEFINE_PIXELFORMAT(SDL2.SDL/SDL_PIXELTYPE_ENUM,SDL2.SDL/SDL_PIXELORDER_ENUM,SDL2.SDL/SDL_PACKEDLAYOUT_ENUM,System.Byte,System.Byte) +M: System.Byte SDL2.SDL::SDL_PIXELFLAG(System.UInt32) +M: System.Byte SDL2.SDL::SDL_PIXELTYPE(System.UInt32) +M: System.Byte SDL2.SDL::SDL_PIXELORDER(System.UInt32) +M: System.Byte SDL2.SDL::SDL_PIXELLAYOUT(System.UInt32) +M: System.Byte SDL2.SDL::SDL_BITSPERPIXEL(System.UInt32) +M: System.Byte SDL2.SDL::SDL_BYTESPERPIXEL(System.UInt32) +M: System.Boolean SDL2.SDL::SDL_ISPIXELFORMAT_INDEXED(System.UInt32) +M: System.Boolean SDL2.SDL::SDL_ISPIXELFORMAT_ALPHA(System.UInt32) +M: System.Boolean SDL2.SDL::SDL_ISPIXELFORMAT_FOURCC(System.UInt32) +M: System.IntPtr SDL2.SDL::SDL_AllocFormat(System.UInt32) +M: System.IntPtr SDL2.SDL::SDL_AllocPalette(System.Int32) +M: System.Void SDL2.SDL::SDL_CalculateGammaRamp(System.Single,System.UInt16[]) +M: System.Void SDL2.SDL::SDL_FreeFormat(System.IntPtr) +M: System.Void SDL2.SDL::SDL_FreePalette(System.IntPtr) +M: System.String SDL2.SDL::SDL_GetPixelFormatName(System.UInt32) +M: System.Void SDL2.SDL::SDL_GetRGB(System.UInt32,System.IntPtr,System.Byte&,System.Byte&,System.Byte&) +M: System.Void SDL2.SDL::SDL_GetRGBA(System.UInt32,System.IntPtr,System.Byte&,System.Byte&,System.Byte&,System.Byte&) +M: System.UInt32 SDL2.SDL::SDL_MapRGB(System.IntPtr,System.Byte,System.Byte,System.Byte) +M: System.UInt32 SDL2.SDL::SDL_MapRGBA(System.IntPtr,System.Byte,System.Byte,System.Byte,System.Byte) +M: System.UInt32 SDL2.SDL::SDL_MasksToPixelFormatEnum(System.Int32,System.UInt32,System.UInt32,System.UInt32,System.UInt32) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_PixelFormatEnumToMasks(System.UInt32,System.Int32&,System.UInt32&,System.UInt32&,System.UInt32&,System.UInt32&) +M: System.Int32 SDL2.SDL::SDL_SetPaletteColors(System.IntPtr,SDL2.SDL/SDL_Color[],System.Int32,System.Int32) +M: System.Int32 SDL2.SDL::SDL_SetPixelFormatPalette(System.IntPtr,System.IntPtr) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_EnclosePoints(SDL2.SDL/SDL_Point[],System.Int32,SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_HasIntersection(SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_IntersectRect(SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_IntersectRectAndLine(SDL2.SDL/SDL_Rect&,System.Int32&,System.Int32&,System.Int32&,System.Int32&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_RectEmpty(SDL2.SDL/SDL_Rect&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_RectEquals(SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&) +M: System.Void SDL2.SDL::SDL_UnionRect(SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&) +M: System.Boolean SDL2.SDL::SDL_MUSTLOCK(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_BlitSurface(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_BlitSurface(System.IntPtr,System.IntPtr,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_BlitSurface(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_BlitSurface(System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_BlitScaled(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_BlitScaled(System.IntPtr,System.IntPtr,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_BlitScaled(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_BlitScaled(System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_ConvertPixels(System.Int32,System.Int32,System.UInt32,System.IntPtr,System.Int32,System.UInt32,System.IntPtr,System.Int32) +M: System.IntPtr SDL2.SDL::SDL_ConvertSurface(System.IntPtr,System.IntPtr,System.UInt32) +M: System.IntPtr SDL2.SDL::SDL_ConvertSurfaceFormat(System.IntPtr,System.UInt32,System.UInt32) +M: System.IntPtr SDL2.SDL::SDL_CreateRGBSurface(System.UInt32,System.Int32,System.Int32,System.Int32,System.UInt32,System.UInt32,System.UInt32,System.UInt32) +M: System.IntPtr SDL2.SDL::SDL_CreateRGBSurfaceFrom(System.IntPtr,System.Int32,System.Int32,System.Int32,System.Int32,System.UInt32,System.UInt32,System.UInt32,System.UInt32) +M: System.Int32 SDL2.SDL::SDL_FillRect(System.IntPtr,SDL2.SDL/SDL_Rect&,System.UInt32) +M: System.Int32 SDL2.SDL::SDL_FillRects(System.IntPtr,SDL2.SDL/SDL_Rect[],System.Int32,System.UInt32) +M: System.Void SDL2.SDL::SDL_FreeSurface(System.IntPtr) +M: System.Void SDL2.SDL::SDL_GetClipRect(System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_GetColorKey(System.IntPtr,System.UInt32&) +M: System.Int32 SDL2.SDL::SDL_GetSurfaceAlphaMod(System.IntPtr,System.Byte&) +M: System.Int32 SDL2.SDL::SDL_GetSurfaceBlendMode(System.IntPtr,SDL2.SDL/SDL_BlendMode&) +M: System.Int32 SDL2.SDL::SDL_GetSurfaceColorMod(System.IntPtr,System.Byte&,System.Byte&,System.Byte&) +M: System.IntPtr SDL2.SDL::SDL_LoadBMP(System.String) +M: System.Int32 SDL2.SDL::SDL_LockSurface(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_LowerBlit(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_LowerBlitScaled(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_SaveBMP(System.IntPtr,System.String) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_SetClipRect(System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_SetColorKey(System.IntPtr,System.Int32,System.UInt32) +M: System.Int32 SDL2.SDL::SDL_SetSurfaceAlphaMod(System.IntPtr,System.Byte) +M: System.Int32 SDL2.SDL::SDL_SetSurfaceBlendMode(System.IntPtr,SDL2.SDL/SDL_BlendMode) +M: System.Int32 SDL2.SDL::SDL_SetSurfaceColorMod(System.IntPtr,System.Byte,System.Byte,System.Byte) +M: System.Int32 SDL2.SDL::SDL_SetSurfacePalette(System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_SetSurfaceRLE(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_SoftStretch(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Void SDL2.SDL::SDL_UnlockSurface(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_UpperBlit(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_UpperBlitScaled(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_HasClipboardText() +M: System.String SDL2.SDL::SDL_GetClipboardText() +M: System.Int32 SDL2.SDL::SDL_SetClipboardText(System.String) +M: System.Void SDL2.SDL::SDL_PumpEvents() +M: System.Int32 SDL2.SDL::SDL_PeepEvents(SDL2.SDL/SDL_Event[],System.Int32,SDL2.SDL/SDL_eventaction,SDL2.SDL/SDL_EventType,SDL2.SDL/SDL_EventType) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_HasEvent(SDL2.SDL/SDL_EventType) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_HasEvents(SDL2.SDL/SDL_EventType,SDL2.SDL/SDL_EventType) +M: System.Void SDL2.SDL::SDL_FlushEvent(SDL2.SDL/SDL_EventType) +M: System.Void SDL2.SDL::SDL_FlushEvents(SDL2.SDL/SDL_EventType,SDL2.SDL/SDL_EventType) +M: System.Int32 SDL2.SDL::SDL_PollEvent(SDL2.SDL/SDL_Event&) +M: System.Int32 SDL2.SDL::SDL_WaitEvent(SDL2.SDL/SDL_Event&) +M: System.Int32 SDL2.SDL::SDL_WaitEventTimeout(SDL2.SDL/SDL_Event&,System.Int32) +M: System.Int32 SDL2.SDL::SDL_PushEvent(SDL2.SDL/SDL_Event&) +M: System.Void SDL2.SDL::SDL_SetEventFilter(SDL2.SDL/SDL_EventFilter,System.IntPtr) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_GetEventFilter(SDL2.SDL/SDL_EventFilter&,System.IntPtr&) +M: System.Void SDL2.SDL::SDL_AddEventWatch(SDL2.SDL/SDL_EventFilter,System.IntPtr) +M: System.Void SDL2.SDL::SDL_DelEventWatch(SDL2.SDL/SDL_EventFilter,System.IntPtr) +M: System.Void SDL2.SDL::SDL_FilterEvents(SDL2.SDL/SDL_EventFilter,System.IntPtr) +M: System.Byte SDL2.SDL::SDL_EventState(SDL2.SDL/SDL_EventType,System.Int32) +M: System.Byte SDL2.SDL::SDL_GetEventState(SDL2.SDL/SDL_EventType) +M: System.UInt32 SDL2.SDL::SDL_RegisterEvents(System.Int32) +M: SDL2.SDL/SDL_Keycode SDL2.SDL::SDL_SCANCODE_TO_KEYCODE(SDL2.SDL/SDL_Scancode) +M: System.IntPtr SDL2.SDL::SDL_GetKeyboardFocus() +M: System.IntPtr SDL2.SDL::SDL_GetKeyboardState(System.Int32&) +M: SDL2.SDL/SDL_Keymod SDL2.SDL::SDL_GetModState() +M: System.Void SDL2.SDL::SDL_SetModState(SDL2.SDL/SDL_Keymod) +M: SDL2.SDL/SDL_Keycode SDL2.SDL::SDL_GetKeyFromScancode(SDL2.SDL/SDL_Scancode) +M: SDL2.SDL/SDL_Scancode SDL2.SDL::SDL_GetScancodeFromKey(SDL2.SDL/SDL_Keycode) +M: System.String SDL2.SDL::SDL_GetScancodeName(SDL2.SDL/SDL_Scancode) +M: SDL2.SDL/SDL_Scancode SDL2.SDL::SDL_GetScancodeFromName(System.String) +M: System.String SDL2.SDL::SDL_GetKeyName(SDL2.SDL/SDL_Keycode) +M: SDL2.SDL/SDL_Keycode SDL2.SDL::SDL_GetKeyFromName(System.String) +M: System.Void SDL2.SDL::SDL_StartTextInput() +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_IsTextInputActive() +M: System.Void SDL2.SDL::SDL_StopTextInput() +M: System.Void SDL2.SDL::SDL_SetTextInputRect(SDL2.SDL/SDL_Rect&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_HasScreenKeyboardSupport() +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_IsScreenKeyboardShown(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_GetMouseFocus() +M: System.UInt32 SDL2.SDL::SDL_GetMouseState(System.Int32&,System.Int32&) +M: System.UInt32 SDL2.SDL::SDL_GetMouseState(System.IntPtr,System.Int32&) +M: System.UInt32 SDL2.SDL::SDL_GetMouseState(System.Int32&,System.IntPtr) +M: System.UInt32 SDL2.SDL::SDL_GetMouseState(System.IntPtr,System.IntPtr) +M: System.UInt32 SDL2.SDL::SDL_GetRelativeMouseState(System.Int32&,System.Int32&) +M: System.Void SDL2.SDL::SDL_WarpMouseInWindow(System.IntPtr,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL::SDL_SetRelativeMouseMode(SDL2.SDL/SDL_bool) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_GetRelativeMouseMode() +M: System.IntPtr SDL2.SDL::SDL_CreateCursor(System.IntPtr,System.IntPtr,System.Int32,System.Int32,System.Int32,System.Int32) +M: System.IntPtr SDL2.SDL::SDL_CreateColorCursor(System.IntPtr,System.Int32,System.Int32) +M: System.IntPtr SDL2.SDL::SDL_CreateSystemCursor(SDL2.SDL/SDL_SystemCursor) +M: System.Void SDL2.SDL::SDL_SetCursor(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_GetCursor() +M: System.Void SDL2.SDL::SDL_FreeCursor(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_ShowCursor(System.Int32) +M: System.UInt32 SDL2.SDL::SDL_BUTTON(System.UInt32) +M: System.Int32 SDL2.SDL::SDL_GetNumTouchDevices() +M: System.Int64 SDL2.SDL::SDL_GetTouchDevice(System.Int32) +M: System.Int32 SDL2.SDL::SDL_GetNumTouchFingers(System.Int64) +M: System.IntPtr SDL2.SDL::SDL_GetTouchFinger(System.Int64,System.Int32) +M: System.Void SDL2.SDL::SDL_JoystickClose(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_JoystickEventState(System.Int32) +M: System.Int16 SDL2.SDL::SDL_JoystickGetAxis(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_JoystickGetBall(System.IntPtr,System.Int32,System.Int32&,System.Int32&) +M: System.Byte SDL2.SDL::SDL_JoystickGetButton(System.IntPtr,System.Int32) +M: System.Byte SDL2.SDL::SDL_JoystickGetHat(System.IntPtr,System.Int32) +M: System.String SDL2.SDL::SDL_JoystickName(System.IntPtr) +M: System.String SDL2.SDL::SDL_JoystickNameForIndex(System.Int32) +M: System.Int32 SDL2.SDL::SDL_JoystickNumAxes(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_JoystickNumBalls(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_JoystickNumButtons(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_JoystickNumHats(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_JoystickOpen(System.Int32) +M: System.Int32 SDL2.SDL::SDL_JoystickOpened(System.Int32) +M: System.Void SDL2.SDL::SDL_JoystickUpdate() +M: System.Int32 SDL2.SDL::SDL_NumJoysticks() +M: System.Guid SDL2.SDL::SDL_JoystickGetDeviceGUID(System.Int32) +M: System.Guid SDL2.SDL::SDL_JoystickGetGUID(System.IntPtr) +M: System.Void SDL2.SDL::SDL_JoystickGetGUIDString(System.Guid,System.Byte[],System.Int32) +M: System.Guid SDL2.SDL::SDL_JoystickGetGUIDFromString(System.String) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_JoystickGetAttached(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_JoystickInstanceID(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_GameControllerAddMapping(System.String) +M: System.Int32 SDL2.SDL::SDL_GameControllerAddMappingsFromFile(System.String) +M: System.String SDL2.SDL::SDL_GameControllerMappingForGUID(System.Guid) +M: System.String SDL2.SDL::SDL_GameControllerMapping(System.IntPtr) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_IsGameController(System.Int32) +M: System.String SDL2.SDL::SDL_GameControllerNameForIndex(System.Int32) +M: System.IntPtr SDL2.SDL::SDL_GameControllerOpen(System.Int32) +M: System.String SDL2.SDL::SDL_GameControllerName(System.IntPtr) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_GameControllerGetAttached(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_GameControllerGetJoystick(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_GameControllerEventState(System.Int32) +M: System.Void SDL2.SDL::SDL_GameControllerUpdate() +M: SDL2.SDL/SDL_GameControllerAxis SDL2.SDL::SDL_GameControllerGetAxisFromString(System.String) +M: System.String SDL2.SDL::SDL_GameControllerGetStringForAxis(SDL2.SDL/SDL_GameControllerAxis) +M: SDL2.SDL/SDL_GameControllerButtonBind SDL2.SDL::SDL_GameControllerGetBindForAxis(System.IntPtr,SDL2.SDL/SDL_GameControllerAxis) +M: System.Int16 SDL2.SDL::SDL_GameControllerGetAxis(System.IntPtr,SDL2.SDL/SDL_GameControllerAxis) +M: SDL2.SDL/SDL_GameControllerButton SDL2.SDL::SDL_GameControllerGetButtonFromString(System.String) +M: System.String SDL2.SDL::SDL_GameControllerGetStringForButton(SDL2.SDL/SDL_GameControllerButton) +M: SDL2.SDL/SDL_GameControllerButtonBind SDL2.SDL::SDL_GameControllerGetBindForButton(System.IntPtr,SDL2.SDL/SDL_GameControllerButton) +M: System.Byte SDL2.SDL::SDL_GameControllerGetButton(System.IntPtr,SDL2.SDL/SDL_GameControllerButton) +M: System.Void SDL2.SDL::SDL_GameControllerClose(System.IntPtr) +M: System.Void SDL2.SDL::SDL_HapticClose(System.IntPtr) +M: System.Void SDL2.SDL::SDL_HapticDestroyEffect(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_HapticEffectSupported(System.IntPtr,SDL2.SDL/SDL_HapticEffect&) +M: System.Int32 SDL2.SDL::SDL_HapticGetEffectStatus(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_HapticIndex(System.IntPtr) +M: System.String SDL2.SDL::SDL_HapticName(System.Int32) +M: System.Int32 SDL2.SDL::SDL_HapticNewEffect(System.IntPtr,SDL2.SDL/SDL_HapticEffect&) +M: System.Int32 SDL2.SDL::SDL_HapticNumAxes(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_HapticNumEffects(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_HapticNumEffectsPlaying(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_HapticOpen(System.Int32) +M: System.Int32 SDL2.SDL::SDL_HapticOpened(System.Int32) +M: System.IntPtr SDL2.SDL::SDL_HapticOpenFromJoystick(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_HapticOpenFromMouse() +M: System.Int32 SDL2.SDL::SDL_HapticPause(System.IntPtr) +M: System.UInt32 SDL2.SDL::SDL_HapticQuery(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_HapticRumbleInit(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_HapticRumblePlay(System.IntPtr,System.Single,System.UInt32) +M: System.Int32 SDL2.SDL::SDL_HapticRumbleStop(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_HapticRumbleSupported(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_HapticRunEffect(System.IntPtr,System.Int32,System.UInt32) +M: System.Int32 SDL2.SDL::SDL_HapticSetAutocenter(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_HapticSetGain(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_HapticStopAll(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_HapticStopEffect(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_HapticUnpause(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_HapticUpdateEffect(System.IntPtr,System.Int32,SDL2.SDL/SDL_HapticEffect&) +M: System.Int32 SDL2.SDL::SDL_JoystickIsHaptic(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_MouseIsHaptic() +M: System.Int32 SDL2.SDL::SDL_NumHaptics() +M: System.UInt16 SDL2.SDL::SDL_AUDIO_BITSIZE(System.UInt16) +M: System.Boolean SDL2.SDL::SDL_AUDIO_ISFLOAT(System.UInt16) +M: System.Boolean SDL2.SDL::SDL_AUDIO_ISBIGENDIAN(System.UInt16) +M: System.Boolean SDL2.SDL::SDL_AUDIO_ISSIGNED(System.UInt16) +M: System.Boolean SDL2.SDL::SDL_AUDIO_ISINT(System.UInt16) +M: System.Boolean SDL2.SDL::SDL_AUDIO_ISLITTLEENDIAN(System.UInt16) +M: System.Boolean SDL2.SDL::SDL_AUDIO_ISUNSIGNED(System.UInt16) +M: System.Int32 SDL2.SDL::SDL_AudioDeviceConnected(System.UInt32) +M: System.Int32 SDL2.SDL::SDL_AudioInit(System.String) +M: System.Void SDL2.SDL::SDL_AudioQuit() +M: System.Void SDL2.SDL::SDL_CloseAudio() +M: System.Void SDL2.SDL::SDL_CloseAudioDevice(System.UInt32) +M: System.Void SDL2.SDL::SDL_FreeWAV(System.IntPtr) +M: System.String SDL2.SDL::SDL_GetAudioDeviceName(System.Int32,System.Int32) +M: SDL2.SDL/SDL_AudioStatus SDL2.SDL::SDL_GetAudioDeviceStatus(System.UInt32) +M: System.String SDL2.SDL::SDL_GetAudioDriver(System.Int32) +M: SDL2.SDL/SDL_AudioStatus SDL2.SDL::SDL_GetAudioStatus() +M: System.String SDL2.SDL::SDL_GetCurrentAudioDriver() +M: System.Int32 SDL2.SDL::SDL_GetNumAudioDevices(System.Int32) +M: System.Int32 SDL2.SDL::SDL_GetNumAudioDrivers() +M: SDL2.SDL/SDL_AudioSpec SDL2.SDL::SDL_LoadWAV(System.String,SDL2.SDL/SDL_AudioSpec&,System.IntPtr&,System.UInt32&) +M: System.Void SDL2.SDL::SDL_LockAudio() +M: System.Void SDL2.SDL::SDL_LockAudioDevice(System.UInt32) +M: System.Void SDL2.SDL::SDL_MixAudio(System.Byte[],System.Byte[],System.UInt32,System.Int32) +M: System.Void SDL2.SDL::SDL_MixAudioFormat(System.Byte[],System.Byte[],System.UInt16,System.UInt32,System.Int32) +M: System.Int32 SDL2.SDL::SDL_OpenAudio(SDL2.SDL/SDL_AudioSpec&,SDL2.SDL/SDL_AudioSpec&) +M: System.UInt32 SDL2.SDL::SDL_OpenAudioDevice(System.String,System.Int32,SDL2.SDL/SDL_AudioSpec&,SDL2.SDL/SDL_AudioSpec&,System.Int32) +M: System.Void SDL2.SDL::SDL_PauseAudio(System.Int32) +M: System.Void SDL2.SDL::SDL_PauseAudioDevice(System.UInt32,System.Int32) +M: System.Void SDL2.SDL::SDL_UnlockAudio() +M: System.Void SDL2.SDL::SDL_UnlockAudioDevice(System.UInt32) +M: System.Boolean SDL2.SDL::SDL_TICKS_PASSED(System.UInt32,System.UInt32) +M: System.Void SDL2.SDL::SDL_Delay(System.UInt32) +M: System.UInt32 SDL2.SDL::SDL_GetTicks() +M: System.UInt64 SDL2.SDL::SDL_GetPerformanceCounter() +M: System.UInt64 SDL2.SDL::SDL_GetPerformanceFrequency() +M: System.Int32 SDL2.SDL::SDL_AddTimer(System.UInt32,SDL2.SDL/SDL_TimerCallback,System.IntPtr) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_RemoveTimer(System.Int32) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_GetWindowWMInfo(System.IntPtr,SDL2.SDL/SDL_SysWMinfo&) +M: System.String SDL2.SDL::SDL_GetBasePath() +M: System.String SDL2.SDL::SDL_GetPrefPath(System.String,System.String) +M: System.Int32 SDL2.SDL::SDL_GetCPUCount() +M: System.Int32 SDL2.SDL::SDL_GetSystemRAM() +T: SDL2.SDL/SDL_bool +T: SDL2.SDL/SDL_HintPriority +T: SDL2.SDL/SDL_LogPriority +T: SDL2.SDL/SDL_LogOutputFunction +T: SDL2.SDL/SDL_MessageBoxFlags +T: SDL2.SDL/SDL_MessageBoxButtonFlags +T: SDL2.SDL/SDL_MessageBoxButtonData +T: SDL2.SDL/SDL_MessageBoxColor +T: SDL2.SDL/SDL_MessageBoxColorType +T: SDL2.SDL/SDL_MessageBoxColorScheme +T: SDL2.SDL/SDL_MessageBoxData +T: SDL2.SDL/SDL_version +T: SDL2.SDL/SDL_BlendMode +T: SDL2.SDL/SDL_GLattr +T: SDL2.SDL/SDL_GLprofile +T: SDL2.SDL/SDL_GLcontext +T: SDL2.SDL/SDL_WindowEventID +T: SDL2.SDL/SDL_WindowFlags +T: SDL2.SDL/SDL_DisplayMode +T: SDL2.SDL/SDL_RendererFlags +T: SDL2.SDL/SDL_RendererFlip +T: SDL2.SDL/SDL_TextureAccess +T: SDL2.SDL/SDL_TextureModulate +T: SDL2.SDL/SDL_RendererInfo +T: SDL2.SDL/SDL_PIXELTYPE_ENUM +T: SDL2.SDL/SDL_PIXELORDER_ENUM +T: SDL2.SDL/SDL_PACKEDLAYOUT_ENUM +T: SDL2.SDL/SDL_Color +T: SDL2.SDL/SDL_Palette +T: SDL2.SDL/SDL_PixelFormat +T: SDL2.SDL/SDL_Point +T: SDL2.SDL/SDL_Rect +T: SDL2.SDL/SDL_Surface +T: SDL2.SDL/SDL_EventType +T: SDL2.SDL/SDL_GenericEvent +T: SDL2.SDL/SDL_WindowEvent +T: SDL2.SDL/SDL_KeyboardEvent +T: SDL2.SDL/SDL_TextEditingEvent +T: SDL2.SDL/SDL_TextInputEvent +T: SDL2.SDL/SDL_MouseMotionEvent +T: SDL2.SDL/SDL_MouseButtonEvent +T: SDL2.SDL/SDL_MouseWheelEvent +T: SDL2.SDL/SDL_JoyAxisEvent +T: SDL2.SDL/SDL_JoyBallEvent +T: SDL2.SDL/SDL_JoyHatEvent +T: SDL2.SDL/SDL_JoyButtonEvent +T: SDL2.SDL/SDL_JoyDeviceEvent +T: SDL2.SDL/SDL_ControllerAxisEvent +T: SDL2.SDL/SDL_ControllerButtonEvent +T: SDL2.SDL/SDL_ControllerDeviceEvent +T: SDL2.SDL/SDL_TouchFingerEvent +T: SDL2.SDL/SDL_MultiGestureEvent +T: SDL2.SDL/SDL_DollarGestureEvent +T: SDL2.SDL/SDL_DropEvent +T: SDL2.SDL/SDL_QuitEvent +T: SDL2.SDL/SDL_UserEvent +T: SDL2.SDL/SDL_SysWMEvent +T: SDL2.SDL/SDL_Event +T: SDL2.SDL/SDL_EventFilter +T: SDL2.SDL/SDL_eventaction +T: SDL2.SDL/SDL_Scancode +T: SDL2.SDL/SDL_Keycode +T: SDL2.SDL/SDL_Keymod +T: SDL2.SDL/SDL_Keysym +T: SDL2.SDL/SDL_SystemCursor +T: SDL2.SDL/SDL_Finger +T: SDL2.SDL/SDL_GameControllerBindType +T: SDL2.SDL/SDL_GameControllerAxis +T: SDL2.SDL/SDL_GameControllerButton +T: SDL2.SDL/INTERNAL_GameControllerButtonBind_hat +T: SDL2.SDL/SDL_GameControllerButtonBind +T: SDL2.SDL/SDL_HapticDirection +T: SDL2.SDL/SDL_HapticConstant +T: SDL2.SDL/SDL_HapticPeriodic +T: SDL2.SDL/SDL_HapticCondition +T: SDL2.SDL/SDL_HapticRamp +T: SDL2.SDL/SDL_HapticLeftRight +T: SDL2.SDL/SDL_HapticCustom +T: SDL2.SDL/SDL_HapticEffect +T: SDL2.SDL/SDL_AudioStatus +T: SDL2.SDL/SDL_AudioSpec +T: SDL2.SDL/SDL_AudioCallback +T: SDL2.SDL/SDL_TimerCallback +T: SDL2.SDL/SDL_SYSWM_TYPE +T: SDL2.SDL/INTERNAL_windows_wminfo +T: SDL2.SDL/INTERNAL_x11_wminfo +T: SDL2.SDL/INTERNAL_directfb_wminfo +T: SDL2.SDL/INTERNAL_cocoa_wminfo +T: SDL2.SDL/INTERNAL_uikit_wminfo +T: SDL2.SDL/INTERNAL_SysWMDriverUnion +T: SDL2.SDL/SDL_SysWMinfo +T: SDL2.SDL_image +M: System.Void SDL2.SDL_image::SDL_IMAGE_VERSION(SDL2.SDL/SDL_version&) +M: SDL2.SDL/SDL_version SDL2.SDL_image::IMG_LinkedVersion() +M: System.Int32 SDL2.SDL_image::IMG_Init(SDL2.SDL_image/IMG_InitFlags) +M: System.Void SDL2.SDL_image::IMG_Quit() +M: System.IntPtr SDL2.SDL_image::IMG_Load(System.String) +M: System.IntPtr SDL2.SDL_image::IMG_Load_RW(System.IntPtr,System.Int32) +M: System.IntPtr SDL2.SDL_image::IMG_LoadTyped_RW(System.IntPtr,System.Int32,System.String) +M: System.IntPtr SDL2.SDL_image::IMG_LoadTexture(System.IntPtr,System.String) +M: System.IntPtr SDL2.SDL_image::IMG_LoadTexture_RW(System.IntPtr,System.IntPtr,System.Int32) +M: System.IntPtr SDL2.SDL_image::IMG_LoadTextureTyped_RW(System.IntPtr,System.IntPtr,System.Int32,System.String) +M: System.Int32 SDL2.SDL_image::IMG_InvertAlpha(System.Int32) +M: System.IntPtr SDL2.SDL_image::IMG_ReadXPMFromArray(System.String[]) +M: System.Int32 SDL2.SDL_image::IMG_SavePNG(System.IntPtr,System.String) +M: System.Int32 SDL2.SDL_image::IMG_SavePNG_RW(System.IntPtr,System.IntPtr,System.Int32) +T: SDL2.SDL_image/IMG_InitFlags +T: SDL2.SDL_mixer +M: System.Void SDL2.SDL_mixer::SDL_MIXER_VERSION(SDL2.SDL/SDL_version&) +M: SDL2.SDL/SDL_version SDL2.SDL_mixer::MIX_Linked_Version() +M: System.Int32 SDL2.SDL_mixer::Mix_Init(SDL2.SDL_mixer/MIX_InitFlags) +M: System.Void SDL2.SDL_mixer::Mix_Quit() +M: System.Int32 SDL2.SDL_mixer::Mix_OpenAudio(System.Int32,System.UInt16,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_AllocateChannels(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_QuerySpec(System.Int32&,System.UInt16&,System.Int32&) +M: System.IntPtr SDL2.SDL_mixer::Mix_LoadWAV_RW(System.IntPtr,System.Int32) +M: System.IntPtr SDL2.SDL_mixer::Mix_LoadWAV(System.String) +M: System.IntPtr SDL2.SDL_mixer::Mix_LoadMUS(System.String) +M: System.IntPtr SDL2.SDL_mixer::Mix_QuickLoad_WAV(System.Byte[]) +M: System.IntPtr SDL2.SDL_mixer::Mix_QuickLoad_RAW(System.Byte[],System.UInt32) +M: System.Void SDL2.SDL_mixer::Mix_FreeChunk(System.IntPtr) +M: System.Void SDL2.SDL_mixer::Mix_FreeMusic(System.IntPtr) +M: System.Int32 SDL2.SDL_mixer::Mix_GetNumChunkDecoders() +M: System.String SDL2.SDL_mixer::Mix_GetChunkDecoder(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_GetNumMusicDecoders() +M: System.String SDL2.SDL_mixer::Mix_GetMusicDecoder(System.Int32) +M: SDL2.SDL_mixer/Mix_MusicType SDL2.SDL_mixer::Mix_GetMusicType(System.IntPtr) +M: System.Void SDL2.SDL_mixer::Mix_SetPostMix(SDL2.SDL_mixer/MixFuncDelegate,System.IntPtr) +M: System.Void SDL2.SDL_mixer::Mix_HookMusic(SDL2.SDL_mixer/MixFuncDelegate,System.IntPtr) +M: System.Void SDL2.SDL_mixer::Mix_HookMusicFinished(SDL2.SDL_mixer/MusicFinishedDelegate) +M: System.IntPtr SDL2.SDL_mixer::Mix_GetMusicHookData() +M: System.Void SDL2.SDL_mixer::Mix_ChannelFinished(SDL2.SDL_mixer/ChannelFinishedDelegate) +M: System.Int32 SDL2.SDL_mixer::Mix_RegisterEffect(System.Int32,SDL2.SDL_mixer/Mix_EffectFunc_t,SDL2.SDL_mixer/Mix_EffectDone_t,System.IntPtr) +M: System.Int32 SDL2.SDL_mixer::Mix_UnregisterEffect(System.Int32,SDL2.SDL_mixer/Mix_EffectFunc_t) +M: System.Int32 SDL2.SDL_mixer::Mix_UnregisterAllEffects(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_SetPanning(System.Int32,System.Byte,System.Byte) +M: System.Int32 SDL2.SDL_mixer::Mix_SetPosition(System.Int32,System.Int16,System.Byte) +M: System.Int32 SDL2.SDL_mixer::Mix_SetDistance(System.Int32,System.Byte) +M: System.Int32 SDL2.SDL_mixer::Mix_SetReverseStereo(System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_ReserveChannels(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_GroupChannel(System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_GroupChannels(System.Int32,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_GroupAvailable(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_GroupCount(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_GroupOldest(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_GroupNewer(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_PlayChannel(System.Int32,System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_PlayChannelTimed(System.Int32,System.IntPtr,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_PlayMusic(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_FadeInMusic(System.IntPtr,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_FadeInMusicPos(System.IntPtr,System.Int32,System.Int32,System.Double) +M: System.Int32 SDL2.SDL_mixer::Mix_FadeInChannel(System.Int32,System.IntPtr,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_FadeInChannelTimed(System.Int32,System.IntPtr,System.Int32,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_Volume(System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_VolumeChunk(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_VolumeMusic(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_HaltChannel(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_HaltGroup(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_HaltMusic() +M: System.Int32 SDL2.SDL_mixer::Mix_ExpireChannel(System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_FadeOutChannel(System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_FadeOutGroup(System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_FadeOutMusic(System.Int32) +M: SDL2.SDL_mixer/Mix_Fading SDL2.SDL_mixer::Mix_FadingMusic() +M: SDL2.SDL_mixer/Mix_Fading SDL2.SDL_mixer::Mix_FadingChannel(System.Int32) +M: System.Void SDL2.SDL_mixer::Mix_Pause(System.Int32) +M: System.Void SDL2.SDL_mixer::Mix_Resume(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_Paused(System.Int32) +M: System.Void SDL2.SDL_mixer::Mix_PauseMusic() +M: System.Void SDL2.SDL_mixer::Mix_ResumeMusic() +M: System.Void SDL2.SDL_mixer::Mix_RewindMusic() +M: System.Int32 SDL2.SDL_mixer::Mix_PausedMusic() +M: System.Int32 SDL2.SDL_mixer::Mix_SetMusicPosition(System.Double) +M: System.Int32 SDL2.SDL_mixer::Mix_Playing(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_PlayingMusic() +M: System.Int32 SDL2.SDL_mixer::Mix_SetMusicCMD(System.String) +M: System.Int32 SDL2.SDL_mixer::Mix_SetSynchroValue(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_GetSynchroValue() +M: System.Int32 SDL2.SDL_mixer::Mix_SetSoundFonts(System.String) +M: System.String SDL2.SDL_mixer::Mix_GetSoundFonts() +M: System.Int32 SDL2.SDL_mixer::Mix_EachSoundFont(SDL2.SDL_mixer/SoundFontDelegate,System.IntPtr) +M: System.IntPtr SDL2.SDL_mixer::Mix_GetChunk(System.Int32) +M: System.Void SDL2.SDL_mixer::Mix_CloseAudio() +T: SDL2.SDL_mixer/MIX_InitFlags +T: SDL2.SDL_mixer/Mix_Fading +T: SDL2.SDL_mixer/Mix_MusicType +T: SDL2.SDL_mixer/Mix_EffectFunc_t +T: SDL2.SDL_mixer/Mix_EffectDone_t +T: SDL2.SDL_ttf +M: System.Void SDL2.SDL_ttf::SDL_TTF_VERSION(SDL2.SDL/SDL_version&) +M: SDL2.SDL/SDL_version SDL2.SDL_ttf::TTF_LinkedVersion() +M: System.Void SDL2.SDL_ttf::TTF_ByteSwappedUNICODE(System.Int32) +M: System.Int32 SDL2.SDL_ttf::TTF_Init() +M: System.IntPtr SDL2.SDL_ttf::TTF_OpenFont(System.String,System.Int32) +M: System.IntPtr SDL2.SDL_ttf::TTF_OpenFontRW(System.IntPtr,System.Int32,System.Int32) +M: System.IntPtr SDL2.SDL_ttf::TTF_OpenFontIndex(System.String,System.Int32,System.Int64) +M: System.IntPtr SDL2.SDL_ttf::TTF_OpenFontIndexRW(System.IntPtr,System.Int32,System.Int32,System.Int64) +M: System.Int32 SDL2.SDL_ttf::TTF_GetFontStyle(System.IntPtr) +M: System.Void SDL2.SDL_ttf::TTF_SetFontStyle(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL_ttf::TTF_GetFontOutline(System.IntPtr) +M: System.Void SDL2.SDL_ttf::TTF_SetFontOutline(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL_ttf::TTF_GetFontHinting(System.IntPtr) +M: System.Void SDL2.SDL_ttf::TTF_SetFontHinting(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL_ttf::TTF_FontHeight(System.IntPtr) +M: System.Int32 SDL2.SDL_ttf::TTF_FontAscent(System.IntPtr) +M: System.Int32 SDL2.SDL_ttf::TTF_FontDescent(System.IntPtr) +M: System.Int32 SDL2.SDL_ttf::TTF_FontLineSkip(System.IntPtr) +M: System.Int32 SDL2.SDL_ttf::TTF_GetFontKerning(System.IntPtr) +M: System.Void SDL2.SDL_ttf::TTF_SetFontKerning(System.IntPtr,System.Int32) +M: System.Int64 SDL2.SDL_ttf::TTF_FontFaces(System.IntPtr) +M: System.Int32 SDL2.SDL_ttf::TTF_FontFaceIsFixedWidth(System.IntPtr) +M: System.String SDL2.SDL_ttf::TTF_FontFaceFamilyName(System.IntPtr) +M: System.String SDL2.SDL_ttf::TTF_FontFaceStyleName(System.IntPtr) +M: System.Int32 SDL2.SDL_ttf::TTF_GlyphIsProvided(System.IntPtr,System.UInt16) +M: System.Int32 SDL2.SDL_ttf::TTF_GlyphMetrics(System.IntPtr,System.UInt16,System.Int32&,System.Int32&,System.Int32&,System.Int32&,System.Int32&) +M: System.Int32 SDL2.SDL_ttf::TTF_SizeText(System.IntPtr,System.String,System.Int32&,System.Int32&) +M: System.Int32 SDL2.SDL_ttf::TTF_SizeUTF8(System.IntPtr,System.String,System.Int32&,System.Int32&) +M: System.Int32 SDL2.SDL_ttf::TTF_SizeUNICODE(System.IntPtr,System.String,System.Int32&,System.Int32&) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderText_Solid(System.IntPtr,System.String,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderUTF8_Solid(System.IntPtr,System.String,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderUNICODE_Solid(System.IntPtr,System.String,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderGlyph_Solid(System.IntPtr,System.UInt16,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderText_Shaded(System.IntPtr,System.String,SDL2.SDL/SDL_Color,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderUTF8_Shaded(System.IntPtr,System.String,SDL2.SDL/SDL_Color,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderUNICODE_Shaded(System.IntPtr,System.String,SDL2.SDL/SDL_Color,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderGlyph_Shaded(System.IntPtr,System.UInt16,SDL2.SDL/SDL_Color,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderText_Blended(System.IntPtr,System.String,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderUTF8_Blended(System.IntPtr,System.String,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderUNICODE_Blended(System.IntPtr,System.String,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderText_Blended_Wrapped(System.IntPtr,System.String,SDL2.SDL/SDL_Color,System.UInt32) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderUTF8_Blended_Wrapped(System.IntPtr,System.String,SDL2.SDL/SDL_Color,System.UInt32) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderUNICODE_Blended_Wrapped(System.IntPtr,System.String,SDL2.SDL/SDL_Color,System.UInt32) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderGlyph_Blended(System.IntPtr,System.UInt16,SDL2.SDL/SDL_Color) +M: System.Void SDL2.SDL_ttf::TTF_CloseFont(System.IntPtr) +M: System.Void SDL2.SDL_ttf::TTF_Quit() +M: System.Int32 SDL2.SDL_ttf::TTF_WasInit() +M: System.Int32 SDL2.SDL_ttf::SDL_GetFontKerningSize(System.IntPtr,System.Int32,System.Int32) + +R: Gendarme.Rules.Design.AvoidRefAndOutParametersRule +M: System.Int32 SDL2.SDL::SDL_ShowMessageBox(SDL2.SDL/SDL_MessageBoxData&,System.Int32&) +M: System.Void SDL2.SDL::SDL_VERSION(SDL2.SDL/SDL_version&) +M: SDL2.SDL/SDL_AudioSpec SDL2.SDL::SDL_LoadWAV(System.String,SDL2.SDL/SDL_AudioSpec&,System.IntPtr&,System.UInt32&) +M: System.Void SDL2.SDL_image::SDL_IMAGE_VERSION(SDL2.SDL/SDL_version&) +M: System.Void SDL2.SDL_mixer::SDL_MIXER_VERSION(SDL2.SDL/SDL_version&) +M: System.Void SDL2.SDL_ttf::SDL_TTF_VERSION(SDL2.SDL/SDL_version&) + +R: Gendarme.Rules.Performance.AvoidUnneededFieldInitializationRule +M: System.Void SDL2.SDL::.cctor() + +R: Gendarme.Rules.Performance.AvoidUnsealedUninheritedInternalTypeRule +T: SDL2.LPUtf8StrMarshaler + +R: Gendarme.Rules.Performance.AvoidUnusedPrivateFieldsRule +T: SDL2.SDL/SDL_WindowEvent +T: SDL2.SDL/SDL_KeyboardEvent +T: SDL2.SDL/SDL_MouseMotionEvent +T: SDL2.SDL/SDL_MouseButtonEvent +T: SDL2.SDL/SDL_JoyAxisEvent +T: SDL2.SDL/SDL_JoyBallEvent +T: SDL2.SDL/SDL_JoyHatEvent +T: SDL2.SDL/SDL_JoyButtonEvent +T: SDL2.SDL/SDL_ControllerAxisEvent +T: SDL2.SDL/SDL_ControllerButtonEvent + +R: Gendarme.Rules.BadPractice.AvoidVisibleConstantFieldRule +T: SDL2.SDL +T: SDL2.SDL_image +T: SDL2.SDL_mixer +T: SDL2.SDL_ttf + +R: Gendarme.Rules.Design.AvoidVisibleFieldsRule +T: SDL2.SDL/SDL_MessageBoxButtonData +T: SDL2.SDL/SDL_MessageBoxColor +T: SDL2.SDL/SDL_MessageBoxColorScheme +T: SDL2.SDL/SDL_MessageBoxData +T: SDL2.SDL/SDL_version +T: SDL2.SDL/SDL_DisplayMode +T: SDL2.SDL/SDL_RendererInfo +T: SDL2.SDL/SDL_Color +T: SDL2.SDL/SDL_Palette +T: SDL2.SDL/SDL_PixelFormat +T: SDL2.SDL/SDL_Point +T: SDL2.SDL/SDL_Rect +T: SDL2.SDL/SDL_Surface +T: SDL2.SDL/SDL_GenericEvent +T: SDL2.SDL/SDL_WindowEvent +T: SDL2.SDL/SDL_KeyboardEvent +T: SDL2.SDL/SDL_TextEditingEvent +T: SDL2.SDL/SDL_TextInputEvent +T: SDL2.SDL/SDL_MouseMotionEvent +T: SDL2.SDL/SDL_MouseButtonEvent +T: SDL2.SDL/SDL_MouseWheelEvent +T: SDL2.SDL/SDL_JoyAxisEvent +T: SDL2.SDL/SDL_JoyBallEvent +T: SDL2.SDL/SDL_JoyHatEvent +T: SDL2.SDL/SDL_JoyButtonEvent +T: SDL2.SDL/SDL_JoyDeviceEvent +T: SDL2.SDL/SDL_ControllerAxisEvent +T: SDL2.SDL/SDL_ControllerButtonEvent +T: SDL2.SDL/SDL_ControllerDeviceEvent +T: SDL2.SDL/SDL_TouchFingerEvent +T: SDL2.SDL/SDL_MultiGestureEvent +T: SDL2.SDL/SDL_DollarGestureEvent +T: SDL2.SDL/SDL_DropEvent +T: SDL2.SDL/SDL_QuitEvent +T: SDL2.SDL/SDL_UserEvent +T: SDL2.SDL/SDL_SysWMEvent +T: SDL2.SDL/SDL_Event +T: SDL2.SDL/SDL_Keysym +T: SDL2.SDL/SDL_Finger +T: SDL2.SDL/INTERNAL_GameControllerButtonBind_hat +T: SDL2.SDL/SDL_GameControllerButtonBind +T: SDL2.SDL/SDL_HapticDirection +T: SDL2.SDL/SDL_HapticConstant +T: SDL2.SDL/SDL_HapticPeriodic +T: SDL2.SDL/SDL_HapticCondition +T: SDL2.SDL/SDL_HapticRamp +T: SDL2.SDL/SDL_HapticLeftRight +T: SDL2.SDL/SDL_HapticCustom +T: SDL2.SDL/SDL_HapticEffect +T: SDL2.SDL/SDL_AudioSpec +T: SDL2.SDL/INTERNAL_windows_wminfo +T: SDL2.SDL/INTERNAL_x11_wminfo +T: SDL2.SDL/INTERNAL_directfb_wminfo +T: SDL2.SDL/INTERNAL_cocoa_wminfo +T: SDL2.SDL/INTERNAL_uikit_wminfo +T: SDL2.SDL/INTERNAL_SysWMDriverUnion +T: SDL2.SDL/SDL_SysWMinfo + +R: Gendarme.Rules.Design.AvoidVisibleNestedTypesRule +T: SDL2.SDL/SDL_bool +T: SDL2.SDL/SDL_HintPriority +T: SDL2.SDL/SDL_LogPriority +T: SDL2.SDL/SDL_LogOutputFunction +T: SDL2.SDL/SDL_MessageBoxFlags +T: SDL2.SDL/SDL_MessageBoxButtonFlags +T: SDL2.SDL/SDL_MessageBoxButtonData +T: SDL2.SDL/SDL_MessageBoxColor +T: SDL2.SDL/SDL_MessageBoxColorType +T: SDL2.SDL/SDL_MessageBoxColorScheme +T: SDL2.SDL/SDL_MessageBoxData +T: SDL2.SDL/SDL_version +T: SDL2.SDL/SDL_BlendMode +T: SDL2.SDL/SDL_GLattr +T: SDL2.SDL/SDL_GLprofile +T: SDL2.SDL/SDL_GLcontext +T: SDL2.SDL/SDL_WindowEventID +T: SDL2.SDL/SDL_WindowFlags +T: SDL2.SDL/SDL_DisplayMode +T: SDL2.SDL/SDL_RendererFlags +T: SDL2.SDL/SDL_RendererFlip +T: SDL2.SDL/SDL_TextureAccess +T: SDL2.SDL/SDL_TextureModulate +T: SDL2.SDL/SDL_RendererInfo +T: SDL2.SDL/SDL_RendererInfo/__FixedBuffer0 +T: SDL2.SDL/SDL_PIXELTYPE_ENUM +T: SDL2.SDL/SDL_PIXELORDER_ENUM +T: SDL2.SDL/SDL_PACKEDLAYOUT_ENUM +T: SDL2.SDL/SDL_Color +T: SDL2.SDL/SDL_Palette +T: SDL2.SDL/SDL_PixelFormat +T: SDL2.SDL/SDL_Point +T: SDL2.SDL/SDL_Rect +T: SDL2.SDL/SDL_Surface +T: SDL2.SDL/SDL_EventType +T: SDL2.SDL/SDL_GenericEvent +T: SDL2.SDL/SDL_WindowEvent +T: SDL2.SDL/SDL_KeyboardEvent +T: SDL2.SDL/SDL_TextEditingEvent +T: SDL2.SDL/SDL_TextEditingEvent/__FixedBuffer1 +T: SDL2.SDL/SDL_TextInputEvent +T: SDL2.SDL/SDL_TextInputEvent/__FixedBuffer2 +T: SDL2.SDL/SDL_MouseMotionEvent +T: SDL2.SDL/SDL_MouseButtonEvent +T: SDL2.SDL/SDL_MouseWheelEvent +T: SDL2.SDL/SDL_JoyAxisEvent +T: SDL2.SDL/SDL_JoyBallEvent +T: SDL2.SDL/SDL_JoyHatEvent +T: SDL2.SDL/SDL_JoyButtonEvent +T: SDL2.SDL/SDL_JoyDeviceEvent +T: SDL2.SDL/SDL_ControllerAxisEvent +T: SDL2.SDL/SDL_ControllerButtonEvent +T: SDL2.SDL/SDL_ControllerDeviceEvent +T: SDL2.SDL/SDL_TouchFingerEvent +T: SDL2.SDL/SDL_MultiGestureEvent +T: SDL2.SDL/SDL_DollarGestureEvent +T: SDL2.SDL/SDL_DropEvent +T: SDL2.SDL/SDL_QuitEvent +T: SDL2.SDL/SDL_UserEvent +T: SDL2.SDL/SDL_SysWMEvent +T: SDL2.SDL/SDL_Event +T: SDL2.SDL/SDL_EventFilter +T: SDL2.SDL/SDL_eventaction +T: SDL2.SDL/SDL_Scancode +T: SDL2.SDL/SDL_Keycode +T: SDL2.SDL/SDL_Keymod +T: SDL2.SDL/SDL_Keysym +T: SDL2.SDL/SDL_SystemCursor +T: SDL2.SDL/SDL_Finger +T: SDL2.SDL/SDL_GameControllerBindType +T: SDL2.SDL/SDL_GameControllerAxis +T: SDL2.SDL/SDL_GameControllerButton +T: SDL2.SDL/INTERNAL_GameControllerButtonBind_hat +T: SDL2.SDL/SDL_GameControllerButtonBind +T: SDL2.SDL/SDL_HapticDirection +T: SDL2.SDL/SDL_HapticDirection/__FixedBuffer3 +T: SDL2.SDL/SDL_HapticConstant +T: SDL2.SDL/SDL_HapticPeriodic +T: SDL2.SDL/SDL_HapticCondition +T: SDL2.SDL/SDL_HapticCondition/__FixedBuffer4 +T: SDL2.SDL/SDL_HapticCondition/__FixedBuffer5 +T: SDL2.SDL/SDL_HapticCondition/__FixedBuffer6 +T: SDL2.SDL/SDL_HapticCondition/__FixedBuffer7 +T: SDL2.SDL/SDL_HapticCondition/__FixedBuffer8 +T: SDL2.SDL/SDL_HapticCondition/
__FixedBuffer9 +T: SDL2.SDL/SDL_HapticRamp +T: SDL2.SDL/SDL_HapticLeftRight +T: SDL2.SDL/SDL_HapticCustom +T: SDL2.SDL/SDL_HapticEffect +T: SDL2.SDL/SDL_AudioStatus +T: SDL2.SDL/SDL_AudioSpec +T: SDL2.SDL/SDL_AudioCallback +T: SDL2.SDL/SDL_TimerCallback +T: SDL2.SDL/SDL_SYSWM_TYPE +T: SDL2.SDL/INTERNAL_windows_wminfo +T: SDL2.SDL/INTERNAL_x11_wminfo +T: SDL2.SDL/INTERNAL_directfb_wminfo +T: SDL2.SDL/INTERNAL_cocoa_wminfo +T: SDL2.SDL/INTERNAL_uikit_wminfo +T: SDL2.SDL/INTERNAL_SysWMDriverUnion +T: SDL2.SDL/SDL_SysWMinfo +T: SDL2.SDL_image/IMG_InitFlags +T: SDL2.SDL_mixer/MIX_InitFlags +T: SDL2.SDL_mixer/Mix_Fading +T: SDL2.SDL_mixer/Mix_MusicType +T: SDL2.SDL_mixer/MixFuncDelegate +T: SDL2.SDL_mixer/Mix_EffectFunc_t +T: SDL2.SDL_mixer/Mix_EffectDone_t +T: SDL2.SDL_mixer/MusicFinishedDelegate +T: SDL2.SDL_mixer/ChannelFinishedDelegate +T: SDL2.SDL_mixer/SoundFontDelegate + +R: Gendarme.Rules.Interoperability.CentralizePInvokesIntoNativeMethodsTypeRule +M: System.IntPtr SDL2.SDL::SDL_malloc(System.IntPtr) +M: System.Void SDL2.SDL::SDL_free(System.IntPtr) +M: System.IntPtr SDL2.SDL::INTERNAL_SDL_RWFromFile(System.String,System.String) +M: System.IntPtr SDL2.SDL::SDL_RWFromMem(System.Byte[],System.Int32) +M: System.Void SDL2.SDL::SDL_SetMainReady() +M: System.Int32 SDL2.SDL::SDL_Init(System.UInt32) +M: System.Int32 SDL2.SDL::SDL_InitSubSystem(System.UInt32) +M: System.Void SDL2.SDL::SDL_Quit() +M: System.Void SDL2.SDL::SDL_QuitSubSystem(System.UInt32) +M: System.UInt32 SDL2.SDL::SDL_WasInit(System.UInt32) +M: System.String SDL2.SDL::SDL_GetPlatform() +M: System.Void SDL2.SDL::SDL_ClearHints() +M: System.String SDL2.SDL::SDL_GetHint(System.String) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_SetHint(System.String,System.String) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_SetHintWithPriority(System.String,System.String,SDL2.SDL/SDL_HintPriority) +M: System.Void SDL2.SDL::SDL_ClearError() +M: System.String SDL2.SDL::SDL_GetError() +M: System.Void SDL2.SDL::SDL_SetError(System.String) +M: System.Void SDL2.SDL::SDL_Log(System.String) +M: System.Void SDL2.SDL::SDL_LogVerbose(System.Int32,System.String) +M: System.Void SDL2.SDL::SDL_LogDebug(System.Int32,System.String) +M: System.Void SDL2.SDL::SDL_LogInfo(System.Int32,System.String) +M: System.Void SDL2.SDL::SDL_LogWarn(System.Int32,System.String) +M: System.Void SDL2.SDL::SDL_LogError(System.Int32,System.String) +M: System.Void SDL2.SDL::SDL_LogCritical(System.Int32,System.String) +M: System.Void SDL2.SDL::SDL_LogMessage(System.Int32,SDL2.SDL/SDL_LogPriority,System.String) +M: System.Void SDL2.SDL::SDL_LogMessageV(System.Int32,SDL2.SDL/SDL_LogPriority,System.String) +M: SDL2.SDL/SDL_LogPriority SDL2.SDL::SDL_LogGetPriority(System.Int32) +M: System.Void SDL2.SDL::SDL_LogSetPriority(System.Int32,SDL2.SDL/SDL_LogPriority) +M: System.Void SDL2.SDL::SDL_LogSetAllPriority(SDL2.SDL/SDL_LogPriority) +M: System.Void SDL2.SDL::SDL_LogResetPriorities() +M: System.Void SDL2.SDL::SDL_LogGetOutputFunction(SDL2.SDL/SDL_LogOutputFunction&,System.IntPtr&) +M: System.Void SDL2.SDL::SDL_LogSetOutputFunction(SDL2.SDL/SDL_LogOutputFunction,System.IntPtr) +M: System.Int32 SDL2.SDL::INTERNAL_SDL_ShowMessageBox(SDL2.SDL/INTERNAL_SDL_MessageBoxData&,System.Int32&) +M: System.Int32 SDL2.SDL::SDL_ShowSimpleMessageBox(SDL2.SDL/SDL_MessageBoxFlags,System.String,System.String,System.IntPtr) +M: System.Void SDL2.SDL::SDL_GetVersion(SDL2.SDL/SDL_version&) +M: System.String SDL2.SDL::SDL_GetRevision() +M: System.Int32 SDL2.SDL::SDL_GetRevisionNumber() +M: System.IntPtr SDL2.SDL::SDL_CreateWindow(System.String,System.Int32,System.Int32,System.Int32,System.Int32,SDL2.SDL/SDL_WindowFlags) +M: System.Int32 SDL2.SDL::SDL_CreateWindowAndRenderer(System.Int32,System.Int32,SDL2.SDL/SDL_WindowFlags,System.IntPtr&,System.IntPtr&) +M: System.IntPtr SDL2.SDL::SDL_CreateWindowFrom(System.IntPtr) +M: System.Void SDL2.SDL::SDL_DestroyWindow(System.IntPtr) +M: System.Void SDL2.SDL::SDL_DisableScreenSaver() +M: System.Void SDL2.SDL::SDL_EnableScreenSaver() +M: System.IntPtr SDL2.SDL::SDL_GetClosestDisplayMode(System.Int32,SDL2.SDL/SDL_DisplayMode&,SDL2.SDL/SDL_DisplayMode&) +M: System.Int32 SDL2.SDL::SDL_GetCurrentDisplayMode(System.Int32,SDL2.SDL/SDL_DisplayMode&) +M: System.String SDL2.SDL::SDL_GetCurrentVideoDriver() +M: System.Int32 SDL2.SDL::SDL_GetDesktopDisplayMode(System.Int32,SDL2.SDL/SDL_DisplayMode&) +M: System.Int32 SDL2.SDL::SDL_GetDisplayBounds(System.Int32,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_GetDisplayMode(System.Int32,System.Int32,SDL2.SDL/SDL_DisplayMode&) +M: System.Int32 SDL2.SDL::SDL_GetNumDisplayModes(System.Int32) +M: System.Int32 SDL2.SDL::SDL_GetNumVideoDisplays() +M: System.Int32 SDL2.SDL::SDL_GetNumVideoDrivers() +M: System.String SDL2.SDL::SDL_GetVideoDriver(System.Int32) +M: System.Single SDL2.SDL::SDL_GetWindowBrightness(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_GetWindowData(System.IntPtr,System.String) +M: System.Int32 SDL2.SDL::SDL_GetWindowDisplayIndex(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_GetWindowDisplayMode(System.IntPtr,SDL2.SDL/SDL_DisplayMode&) +M: System.UInt32 SDL2.SDL::SDL_GetWindowFlags(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_GetWindowFromID(System.UInt32) +M: System.Int32 SDL2.SDL::SDL_GetWindowGammaRamp(System.IntPtr,System.UInt16[],System.UInt16[],System.UInt16[]) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_GetWindowGrab(System.IntPtr) +M: System.UInt32 SDL2.SDL::SDL_GetWindowID(System.IntPtr) +M: System.UInt32 SDL2.SDL::SDL_GetWindowPixelFormat(System.IntPtr) +M: System.Void SDL2.SDL::SDL_GetWindowMaximumSize(System.IntPtr,System.Int32&,System.Int32&) +M: System.Void SDL2.SDL::SDL_GetWindowMinimumSize(System.IntPtr,System.Int32&,System.Int32&) +M: System.Void SDL2.SDL::SDL_GetWindowPosition(System.IntPtr,System.Int32&,System.Int32&) +M: System.Void SDL2.SDL::SDL_GetWindowSize(System.IntPtr,System.Int32&,System.Int32&) +M: System.IntPtr SDL2.SDL::SDL_GetWindowSurface(System.IntPtr) +M: System.String SDL2.SDL::SDL_GetWindowTitle(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_GL_BindTexture(System.IntPtr,System.Single&,System.Single&) +M: System.IntPtr SDL2.SDL::SDL_GL_CreateContext(System.IntPtr) +M: System.Void SDL2.SDL::SDL_GL_DeleteContext(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_GL_GetProcAddress(System.String) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_GL_ExtensionSupported(System.String) +M: System.Void SDL2.SDL::SDL_GL_ResetAttributes() +M: System.Int32 SDL2.SDL::SDL_GL_GetAttribute(SDL2.SDL/SDL_GLattr,System.Int32&) +M: System.Int32 SDL2.SDL::SDL_GL_GetSwapInterval() +M: System.Int32 SDL2.SDL::SDL_GL_MakeCurrent(System.IntPtr,System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_GL_GetCurrentWindow() +M: System.IntPtr SDL2.SDL::SDL_GL_GetCurrentContext() +M: System.Void SDL2.SDL::SDL_GL_GetDrawableSize(System.IntPtr,System.Int32&,System.Int32&) +M: System.Int32 SDL2.SDL::SDL_GL_SetAttribute(SDL2.SDL/SDL_GLattr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_GL_SetSwapInterval(System.Int32) +M: System.Void SDL2.SDL::SDL_GL_SwapWindow(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_GL_UnbindTexture(System.IntPtr) +M: System.Void SDL2.SDL::SDL_HideWindow(System.IntPtr) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_IsScreenSaverEnabled() +M: System.Void SDL2.SDL::SDL_MaximizeWindow(System.IntPtr) +M: System.Void SDL2.SDL::SDL_MinimizeWindow(System.IntPtr) +M: System.Void SDL2.SDL::SDL_RaiseWindow(System.IntPtr) +M: System.Void SDL2.SDL::SDL_RestoreWindow(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_SetWindowBrightness(System.IntPtr,System.Single) +M: System.IntPtr SDL2.SDL::SDL_SetWindowData(System.IntPtr,System.String,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_SetWindowDisplayMode(System.IntPtr,SDL2.SDL/SDL_DisplayMode&) +M: System.Int32 SDL2.SDL::SDL_SetWindowFullscreen(System.IntPtr,System.UInt32) +M: System.Int32 SDL2.SDL::SDL_SetWindowGammaRamp(System.IntPtr,System.UInt16[],System.UInt16[],System.UInt16[]) +M: System.Void SDL2.SDL::SDL_SetWindowGrab(System.IntPtr,SDL2.SDL/SDL_bool) +M: System.Void SDL2.SDL::SDL_SetWindowIcon(System.IntPtr,System.IntPtr) +M: System.Void SDL2.SDL::SDL_SetWindowMaximumSize(System.IntPtr,System.Int32,System.Int32) +M: System.Void SDL2.SDL::SDL_SetWindowMinimumSize(System.IntPtr,System.Int32,System.Int32) +M: System.Void SDL2.SDL::SDL_SetWindowPosition(System.IntPtr,System.Int32,System.Int32) +M: System.Void SDL2.SDL::SDL_SetWindowSize(System.IntPtr,System.Int32,System.Int32) +M: System.Void SDL2.SDL::SDL_SetWindowBordered(System.IntPtr,SDL2.SDL/SDL_bool) +M: System.Void SDL2.SDL::SDL_SetWindowTitle(System.IntPtr,System.String) +M: System.Void SDL2.SDL::SDL_ShowWindow(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_UpdateWindowSurface(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_UpdateWindowSurfaceRects(System.IntPtr,SDL2.SDL/SDL_Rect[],System.Int32) +M: System.Int32 SDL2.SDL::SDL_VideoInit(System.String) +M: System.Void SDL2.SDL::SDL_VideoQuit() +M: System.IntPtr SDL2.SDL::SDL_CreateRenderer(System.IntPtr,System.Int32,SDL2.SDL/SDL_RendererFlags) +M: System.IntPtr SDL2.SDL::SDL_CreateSoftwareRenderer(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_CreateTexture(System.IntPtr,System.UInt32,System.Int32,System.Int32,System.Int32) +M: System.IntPtr SDL2.SDL::SDL_CreateTextureFromSurface(System.IntPtr,System.IntPtr) +M: System.Void SDL2.SDL::SDL_DestroyRenderer(System.IntPtr) +M: System.Void SDL2.SDL::SDL_DestroyTexture(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_GetNumRenderDrivers() +M: System.Int32 SDL2.SDL::SDL_GetRenderDrawBlendMode(System.IntPtr,SDL2.SDL/SDL_BlendMode&) +M: System.Int32 SDL2.SDL::SDL_GetRenderDrawColor(System.IntPtr,System.Byte&,System.Byte&,System.Byte&,System.Byte&) +M: System.Int32 SDL2.SDL::SDL_GetRenderDriverInfo(System.Int32,SDL2.SDL/SDL_RendererInfo&) +M: System.IntPtr SDL2.SDL::SDL_GetRenderer(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_GetRendererInfo(System.IntPtr,SDL2.SDL/SDL_RendererInfo&) +M: System.Int32 SDL2.SDL::SDL_GetRendererOutputSize(System.IntPtr,System.Int32&,System.Int32&) +M: System.Int32 SDL2.SDL::SDL_GetTextureAlphaMod(System.IntPtr,System.Byte&) +M: System.Int32 SDL2.SDL::SDL_GetTextureBlendMode(System.IntPtr,SDL2.SDL/SDL_BlendMode&) +M: System.Int32 SDL2.SDL::SDL_GetTextureColorMod(System.IntPtr,System.Byte&,System.Byte&,System.Byte&) +M: System.Int32 SDL2.SDL::SDL_LockTexture(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr&,System.Int32&) +M: System.Int32 SDL2.SDL::SDL_LockTexture(System.IntPtr,System.IntPtr,System.IntPtr&,System.Int32&) +M: System.Int32 SDL2.SDL::SDL_QueryTexture(System.IntPtr,System.UInt32&,System.Int32&,System.Int32&,System.Int32&) +M: System.Int32 SDL2.SDL::SDL_QueryTexturePixels(System.IntPtr,System.IntPtr&,System.Int32&) +M: System.Int32 SDL2.SDL::SDL_RenderClear(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_RenderCopy(System.IntPtr,System.IntPtr,SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_RenderCopy(System.IntPtr,System.IntPtr,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_RenderCopy(System.IntPtr,System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_RenderCopy(System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_RenderCopyEx(System.IntPtr,System.IntPtr,SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&,System.Double,SDL2.SDL/SDL_Point&,SDL2.SDL/SDL_RendererFlip) +M: System.Int32 SDL2.SDL::SDL_RenderDrawLine(System.IntPtr,System.Int32,System.Int32,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL::SDL_RenderDrawLines(System.IntPtr,SDL2.SDL/SDL_Point[],System.Int32) +M: System.Int32 SDL2.SDL::SDL_RenderDrawPoint(System.IntPtr,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL::SDL_RenderDrawPoints(System.IntPtr,SDL2.SDL/SDL_Point[],System.Int32) +M: System.Int32 SDL2.SDL::SDL_RenderDrawRect(System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_RenderDrawRect(System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_RenderDrawRects(System.IntPtr,SDL2.SDL/SDL_Rect[],System.Int32) +M: System.Int32 SDL2.SDL::SDL_RenderFillRect(System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_RenderFillRect(System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_RenderFillRects(System.IntPtr,SDL2.SDL/SDL_Rect[],System.Int32) +M: System.Void SDL2.SDL::SDL_RenderGetClipRect(System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Void SDL2.SDL::SDL_RenderGetLogicalSize(System.IntPtr,System.Int32&,System.Int32&) +M: System.Void SDL2.SDL::SDL_RenderGetScale(System.IntPtr,System.Single&,System.Single&) +M: System.Int32 SDL2.SDL::SDL_RenderGetViewport(System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Void SDL2.SDL::SDL_RenderPresent(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_RenderReadPixels(System.IntPtr,SDL2.SDL/SDL_Rect&,System.UInt32,System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_RenderSetClipRect(System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_RenderSetClipRect(System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_RenderSetLogicalSize(System.IntPtr,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL::SDL_RenderSetScale(System.IntPtr,System.Single,System.Single) +M: System.Int32 SDL2.SDL::SDL_RenderSetViewport(System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_SetRenderDrawBlendMode(System.IntPtr,SDL2.SDL/SDL_BlendMode) +M: System.Int32 SDL2.SDL::SDL_SetRenderDrawColor(System.IntPtr,System.Byte,System.Byte,System.Byte,System.Byte) +M: System.Int32 SDL2.SDL::SDL_SetRenderTarget(System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_SetTextureAlphaMod(System.IntPtr,System.Byte) +M: System.Int32 SDL2.SDL::SDL_SetTextureBlendMode(System.IntPtr,SDL2.SDL/SDL_BlendMode) +M: System.Int32 SDL2.SDL::SDL_SetTextureColorMod(System.IntPtr,System.Byte,System.Byte,System.Byte) +M: System.Void SDL2.SDL::SDL_UnlockTexture(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_UpdateTexture(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,System.Int32) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_RenderTargetSupported(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_GetRenderTarget(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_AllocFormat(System.UInt32) +M: System.IntPtr SDL2.SDL::SDL_AllocPalette(System.Int32) +M: System.Void SDL2.SDL::SDL_CalculateGammaRamp(System.Single,System.UInt16[]) +M: System.Void SDL2.SDL::SDL_FreeFormat(System.IntPtr) +M: System.Void SDL2.SDL::SDL_FreePalette(System.IntPtr) +M: System.String SDL2.SDL::SDL_GetPixelFormatName(System.UInt32) +M: System.Void SDL2.SDL::SDL_GetRGB(System.UInt32,System.IntPtr,System.Byte&,System.Byte&,System.Byte&) +M: System.Void SDL2.SDL::SDL_GetRGBA(System.UInt32,System.IntPtr,System.Byte&,System.Byte&,System.Byte&,System.Byte&) +M: System.UInt32 SDL2.SDL::SDL_MapRGB(System.IntPtr,System.Byte,System.Byte,System.Byte) +M: System.UInt32 SDL2.SDL::SDL_MapRGBA(System.IntPtr,System.Byte,System.Byte,System.Byte,System.Byte) +M: System.UInt32 SDL2.SDL::SDL_MasksToPixelFormatEnum(System.Int32,System.UInt32,System.UInt32,System.UInt32,System.UInt32) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_PixelFormatEnumToMasks(System.UInt32,System.Int32&,System.UInt32&,System.UInt32&,System.UInt32&,System.UInt32&) +M: System.Int32 SDL2.SDL::SDL_SetPaletteColors(System.IntPtr,SDL2.SDL/SDL_Color[],System.Int32,System.Int32) +M: System.Int32 SDL2.SDL::SDL_SetPixelFormatPalette(System.IntPtr,System.IntPtr) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_EnclosePoints(SDL2.SDL/SDL_Point[],System.Int32,SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_HasIntersection(SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_IntersectRect(SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_IntersectRectAndLine(SDL2.SDL/SDL_Rect&,System.Int32&,System.Int32&,System.Int32&,System.Int32&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_RectEmpty(SDL2.SDL/SDL_Rect&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_RectEquals(SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&) +M: System.Void SDL2.SDL::SDL_UnionRect(SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_BlitSurface(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_BlitSurface(System.IntPtr,System.IntPtr,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_BlitSurface(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_BlitSurface(System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_BlitScaled(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_BlitScaled(System.IntPtr,System.IntPtr,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_BlitScaled(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_BlitScaled(System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_ConvertPixels(System.Int32,System.Int32,System.UInt32,System.IntPtr,System.Int32,System.UInt32,System.IntPtr,System.Int32) +M: System.IntPtr SDL2.SDL::SDL_ConvertSurface(System.IntPtr,System.IntPtr,System.UInt32) +M: System.IntPtr SDL2.SDL::SDL_ConvertSurfaceFormat(System.IntPtr,System.UInt32,System.UInt32) +M: System.IntPtr SDL2.SDL::SDL_CreateRGBSurface(System.UInt32,System.Int32,System.Int32,System.Int32,System.UInt32,System.UInt32,System.UInt32,System.UInt32) +M: System.IntPtr SDL2.SDL::SDL_CreateRGBSurfaceFrom(System.IntPtr,System.Int32,System.Int32,System.Int32,System.Int32,System.UInt32,System.UInt32,System.UInt32,System.UInt32) +M: System.Int32 SDL2.SDL::SDL_FillRect(System.IntPtr,SDL2.SDL/SDL_Rect&,System.UInt32) +M: System.Int32 SDL2.SDL::SDL_FillRects(System.IntPtr,SDL2.SDL/SDL_Rect[],System.Int32,System.UInt32) +M: System.Void SDL2.SDL::SDL_FreeSurface(System.IntPtr) +M: System.Void SDL2.SDL::SDL_GetClipRect(System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_GetColorKey(System.IntPtr,System.UInt32&) +M: System.Int32 SDL2.SDL::SDL_GetSurfaceAlphaMod(System.IntPtr,System.Byte&) +M: System.Int32 SDL2.SDL::SDL_GetSurfaceBlendMode(System.IntPtr,SDL2.SDL/SDL_BlendMode&) +M: System.Int32 SDL2.SDL::SDL_GetSurfaceColorMod(System.IntPtr,System.Byte&,System.Byte&,System.Byte&) +M: System.IntPtr SDL2.SDL::INTERNAL_SDL_LoadBMP_RW(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_LockSurface(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_LowerBlit(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_LowerBlitScaled(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::INTERNAL_SDL_SaveBMP_RW(System.IntPtr,System.IntPtr,System.Int32) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_SetClipRect(System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_SetColorKey(System.IntPtr,System.Int32,System.UInt32) +M: System.Int32 SDL2.SDL::SDL_SetSurfaceAlphaMod(System.IntPtr,System.Byte) +M: System.Int32 SDL2.SDL::SDL_SetSurfaceBlendMode(System.IntPtr,SDL2.SDL/SDL_BlendMode) +M: System.Int32 SDL2.SDL::SDL_SetSurfaceColorMod(System.IntPtr,System.Byte,System.Byte,System.Byte) +M: System.Int32 SDL2.SDL::SDL_SetSurfacePalette(System.IntPtr,System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_SetSurfaceRLE(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_SoftStretch(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Void SDL2.SDL::SDL_UnlockSurface(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_UpperBlit(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: System.Int32 SDL2.SDL::SDL_UpperBlitScaled(System.IntPtr,SDL2.SDL/SDL_Rect&,System.IntPtr,SDL2.SDL/SDL_Rect&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_HasClipboardText() +M: System.String SDL2.SDL::SDL_GetClipboardText() +M: System.Int32 SDL2.SDL::SDL_SetClipboardText(System.String) +M: System.Void SDL2.SDL::SDL_PumpEvents() +M: System.Int32 SDL2.SDL::SDL_PeepEvents(SDL2.SDL/SDL_Event[],System.Int32,SDL2.SDL/SDL_eventaction,SDL2.SDL/SDL_EventType,SDL2.SDL/SDL_EventType) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_HasEvent(SDL2.SDL/SDL_EventType) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_HasEvents(SDL2.SDL/SDL_EventType,SDL2.SDL/SDL_EventType) +M: System.Void SDL2.SDL::SDL_FlushEvent(SDL2.SDL/SDL_EventType) +M: System.Void SDL2.SDL::SDL_FlushEvents(SDL2.SDL/SDL_EventType,SDL2.SDL/SDL_EventType) +M: System.Int32 SDL2.SDL::SDL_PollEvent(SDL2.SDL/SDL_Event&) +M: System.Int32 SDL2.SDL::SDL_WaitEvent(SDL2.SDL/SDL_Event&) +M: System.Int32 SDL2.SDL::SDL_WaitEventTimeout(SDL2.SDL/SDL_Event&,System.Int32) +M: System.Int32 SDL2.SDL::SDL_PushEvent(SDL2.SDL/SDL_Event&) +M: System.Void SDL2.SDL::SDL_SetEventFilter(SDL2.SDL/SDL_EventFilter,System.IntPtr) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_GetEventFilter(SDL2.SDL/SDL_EventFilter&,System.IntPtr&) +M: System.Void SDL2.SDL::SDL_AddEventWatch(SDL2.SDL/SDL_EventFilter,System.IntPtr) +M: System.Void SDL2.SDL::SDL_DelEventWatch(SDL2.SDL/SDL_EventFilter,System.IntPtr) +M: System.Void SDL2.SDL::SDL_FilterEvents(SDL2.SDL/SDL_EventFilter,System.IntPtr) +M: System.Byte SDL2.SDL::SDL_EventState(SDL2.SDL/SDL_EventType,System.Int32) +M: System.UInt32 SDL2.SDL::SDL_RegisterEvents(System.Int32) +M: System.IntPtr SDL2.SDL::SDL_GetKeyboardFocus() +M: System.IntPtr SDL2.SDL::SDL_GetKeyboardState(System.Int32&) +M: SDL2.SDL/SDL_Keymod SDL2.SDL::SDL_GetModState() +M: System.Void SDL2.SDL::SDL_SetModState(SDL2.SDL/SDL_Keymod) +M: SDL2.SDL/SDL_Keycode SDL2.SDL::SDL_GetKeyFromScancode(SDL2.SDL/SDL_Scancode) +M: SDL2.SDL/SDL_Scancode SDL2.SDL::SDL_GetScancodeFromKey(SDL2.SDL/SDL_Keycode) +M: System.String SDL2.SDL::SDL_GetScancodeName(SDL2.SDL/SDL_Scancode) +M: SDL2.SDL/SDL_Scancode SDL2.SDL::SDL_GetScancodeFromName(System.String) +M: System.String SDL2.SDL::SDL_GetKeyName(SDL2.SDL/SDL_Keycode) +M: SDL2.SDL/SDL_Keycode SDL2.SDL::SDL_GetKeyFromName(System.String) +M: System.Void SDL2.SDL::SDL_StartTextInput() +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_IsTextInputActive() +M: System.Void SDL2.SDL::SDL_StopTextInput() +M: System.Void SDL2.SDL::SDL_SetTextInputRect(SDL2.SDL/SDL_Rect&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_HasScreenKeyboardSupport() +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_IsScreenKeyboardShown(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_GetMouseFocus() +M: System.UInt32 SDL2.SDL::SDL_GetMouseState(System.Int32&,System.Int32&) +M: System.UInt32 SDL2.SDL::SDL_GetMouseState(System.IntPtr,System.Int32&) +M: System.UInt32 SDL2.SDL::SDL_GetMouseState(System.Int32&,System.IntPtr) +M: System.UInt32 SDL2.SDL::SDL_GetMouseState(System.IntPtr,System.IntPtr) +M: System.UInt32 SDL2.SDL::SDL_GetRelativeMouseState(System.Int32&,System.Int32&) +M: System.Void SDL2.SDL::SDL_WarpMouseInWindow(System.IntPtr,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL::SDL_SetRelativeMouseMode(SDL2.SDL/SDL_bool) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_GetRelativeMouseMode() +M: System.IntPtr SDL2.SDL::SDL_CreateCursor(System.IntPtr,System.IntPtr,System.Int32,System.Int32,System.Int32,System.Int32) +M: System.IntPtr SDL2.SDL::SDL_CreateColorCursor(System.IntPtr,System.Int32,System.Int32) +M: System.IntPtr SDL2.SDL::SDL_CreateSystemCursor(SDL2.SDL/SDL_SystemCursor) +M: System.Void SDL2.SDL::SDL_SetCursor(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_GetCursor() +M: System.Void SDL2.SDL::SDL_FreeCursor(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_ShowCursor(System.Int32) +M: System.Int32 SDL2.SDL::SDL_GetNumTouchDevices() +M: System.Int64 SDL2.SDL::SDL_GetTouchDevice(System.Int32) +M: System.Int32 SDL2.SDL::SDL_GetNumTouchFingers(System.Int64) +M: System.IntPtr SDL2.SDL::SDL_GetTouchFinger(System.Int64,System.Int32) +M: System.Void SDL2.SDL::SDL_JoystickClose(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_JoystickEventState(System.Int32) +M: System.Int16 SDL2.SDL::SDL_JoystickGetAxis(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_JoystickGetBall(System.IntPtr,System.Int32,System.Int32&,System.Int32&) +M: System.Byte SDL2.SDL::SDL_JoystickGetButton(System.IntPtr,System.Int32) +M: System.Byte SDL2.SDL::SDL_JoystickGetHat(System.IntPtr,System.Int32) +M: System.String SDL2.SDL::SDL_JoystickName(System.IntPtr) +M: System.String SDL2.SDL::SDL_JoystickNameForIndex(System.Int32) +M: System.Int32 SDL2.SDL::SDL_JoystickNumAxes(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_JoystickNumBalls(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_JoystickNumButtons(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_JoystickNumHats(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_JoystickOpen(System.Int32) +M: System.Int32 SDL2.SDL::SDL_JoystickOpened(System.Int32) +M: System.Void SDL2.SDL::SDL_JoystickUpdate() +M: System.Int32 SDL2.SDL::SDL_NumJoysticks() +M: System.Guid SDL2.SDL::SDL_JoystickGetDeviceGUID(System.Int32) +M: System.Guid SDL2.SDL::SDL_JoystickGetGUID(System.IntPtr) +M: System.Void SDL2.SDL::SDL_JoystickGetGUIDString(System.Guid,System.Byte[],System.Int32) +M: System.Guid SDL2.SDL::SDL_JoystickGetGUIDFromString(System.String) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_JoystickGetAttached(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_JoystickInstanceID(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_GameControllerAddMapping(System.String) +M: System.Int32 SDL2.SDL::INTERNAL_SDL_GameControllerAddMappingsFromRW(System.IntPtr,System.Int32) +M: System.String SDL2.SDL::SDL_GameControllerMappingForGUID(System.Guid) +M: System.String SDL2.SDL::SDL_GameControllerMapping(System.IntPtr) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_IsGameController(System.Int32) +M: System.String SDL2.SDL::SDL_GameControllerNameForIndex(System.Int32) +M: System.IntPtr SDL2.SDL::SDL_GameControllerOpen(System.Int32) +M: System.String SDL2.SDL::SDL_GameControllerName(System.IntPtr) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_GameControllerGetAttached(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_GameControllerGetJoystick(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_GameControllerEventState(System.Int32) +M: System.Void SDL2.SDL::SDL_GameControllerUpdate() +M: SDL2.SDL/SDL_GameControllerAxis SDL2.SDL::SDL_GameControllerGetAxisFromString(System.String) +M: System.String SDL2.SDL::SDL_GameControllerGetStringForAxis(SDL2.SDL/SDL_GameControllerAxis) +M: SDL2.SDL/SDL_GameControllerButtonBind SDL2.SDL::SDL_GameControllerGetBindForAxis(System.IntPtr,SDL2.SDL/SDL_GameControllerAxis) +M: System.Int16 SDL2.SDL::SDL_GameControllerGetAxis(System.IntPtr,SDL2.SDL/SDL_GameControllerAxis) +M: SDL2.SDL/SDL_GameControllerButton SDL2.SDL::SDL_GameControllerGetButtonFromString(System.String) +M: System.String SDL2.SDL::SDL_GameControllerGetStringForButton(SDL2.SDL/SDL_GameControllerButton) +M: SDL2.SDL/SDL_GameControllerButtonBind SDL2.SDL::SDL_GameControllerGetBindForButton(System.IntPtr,SDL2.SDL/SDL_GameControllerButton) +M: System.Byte SDL2.SDL::SDL_GameControllerGetButton(System.IntPtr,SDL2.SDL/SDL_GameControllerButton) +M: System.Void SDL2.SDL::SDL_GameControllerClose(System.IntPtr) +M: System.Void SDL2.SDL::SDL_HapticClose(System.IntPtr) +M: System.Void SDL2.SDL::SDL_HapticDestroyEffect(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_HapticEffectSupported(System.IntPtr,SDL2.SDL/SDL_HapticEffect&) +M: System.Int32 SDL2.SDL::SDL_HapticGetEffectStatus(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_HapticIndex(System.IntPtr) +M: System.String SDL2.SDL::SDL_HapticName(System.Int32) +M: System.Int32 SDL2.SDL::SDL_HapticNewEffect(System.IntPtr,SDL2.SDL/SDL_HapticEffect&) +M: System.Int32 SDL2.SDL::SDL_HapticNumAxes(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_HapticNumEffects(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_HapticNumEffectsPlaying(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_HapticOpen(System.Int32) +M: System.Int32 SDL2.SDL::SDL_HapticOpened(System.Int32) +M: System.IntPtr SDL2.SDL::SDL_HapticOpenFromJoystick(System.IntPtr) +M: System.IntPtr SDL2.SDL::SDL_HapticOpenFromMouse() +M: System.Int32 SDL2.SDL::SDL_HapticPause(System.IntPtr) +M: System.UInt32 SDL2.SDL::SDL_HapticQuery(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_HapticRumbleInit(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_HapticRumblePlay(System.IntPtr,System.Single,System.UInt32) +M: System.Int32 SDL2.SDL::SDL_HapticRumbleStop(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_HapticRumbleSupported(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_HapticRunEffect(System.IntPtr,System.Int32,System.UInt32) +M: System.Int32 SDL2.SDL::SDL_HapticSetAutocenter(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_HapticSetGain(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_HapticStopAll(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_HapticStopEffect(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL::SDL_HapticUnpause(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_HapticUpdateEffect(System.IntPtr,System.Int32,SDL2.SDL/SDL_HapticEffect&) +M: System.Int32 SDL2.SDL::SDL_JoystickIsHaptic(System.IntPtr) +M: System.Int32 SDL2.SDL::SDL_MouseIsHaptic() +M: System.Int32 SDL2.SDL::SDL_NumHaptics() +M: System.Int32 SDL2.SDL::SDL_AudioDeviceConnected(System.UInt32) +M: System.Int32 SDL2.SDL::SDL_AudioInit(System.String) +M: System.Void SDL2.SDL::SDL_AudioQuit() +M: System.Void SDL2.SDL::SDL_CloseAudio() +M: System.Void SDL2.SDL::SDL_CloseAudioDevice(System.UInt32) +M: System.Void SDL2.SDL::SDL_FreeWAV(System.IntPtr) +M: System.String SDL2.SDL::SDL_GetAudioDeviceName(System.Int32,System.Int32) +M: SDL2.SDL/SDL_AudioStatus SDL2.SDL::SDL_GetAudioDeviceStatus(System.UInt32) +M: System.String SDL2.SDL::SDL_GetAudioDriver(System.Int32) +M: SDL2.SDL/SDL_AudioStatus SDL2.SDL::SDL_GetAudioStatus() +M: System.String SDL2.SDL::SDL_GetCurrentAudioDriver() +M: System.Int32 SDL2.SDL::SDL_GetNumAudioDevices(System.Int32) +M: System.Int32 SDL2.SDL::SDL_GetNumAudioDrivers() +M: System.IntPtr SDL2.SDL::INTERNAL_SDL_LoadWAV_RW(System.IntPtr,System.Int32,SDL2.SDL/SDL_AudioSpec&,System.IntPtr&,System.UInt32&) +M: System.Void SDL2.SDL::SDL_LockAudio() +M: System.Void SDL2.SDL::SDL_LockAudioDevice(System.UInt32) +M: System.Void SDL2.SDL::SDL_MixAudio(System.Byte[],System.Byte[],System.UInt32,System.Int32) +M: System.Void SDL2.SDL::SDL_MixAudioFormat(System.Byte[],System.Byte[],System.UInt16,System.UInt32,System.Int32) +M: System.Int32 SDL2.SDL::SDL_OpenAudio(SDL2.SDL/SDL_AudioSpec&,SDL2.SDL/SDL_AudioSpec&) +M: System.UInt32 SDL2.SDL::SDL_OpenAudioDevice(System.String,System.Int32,SDL2.SDL/SDL_AudioSpec&,SDL2.SDL/SDL_AudioSpec&,System.Int32) +M: System.Void SDL2.SDL::SDL_PauseAudio(System.Int32) +M: System.Void SDL2.SDL::SDL_PauseAudioDevice(System.UInt32,System.Int32) +M: System.Void SDL2.SDL::SDL_UnlockAudio() +M: System.Void SDL2.SDL::SDL_UnlockAudioDevice(System.UInt32) +M: System.Void SDL2.SDL::SDL_Delay(System.UInt32) +M: System.UInt32 SDL2.SDL::SDL_GetTicks() +M: System.UInt64 SDL2.SDL::SDL_GetPerformanceCounter() +M: System.UInt64 SDL2.SDL::SDL_GetPerformanceFrequency() +M: System.Int32 SDL2.SDL::SDL_AddTimer(System.UInt32,SDL2.SDL/SDL_TimerCallback,System.IntPtr) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_RemoveTimer(System.Int32) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_GetWindowWMInfo(System.IntPtr,SDL2.SDL/SDL_SysWMinfo&) +M: System.String SDL2.SDL::SDL_GetBasePath() +M: System.String SDL2.SDL::SDL_GetPrefPath(System.String,System.String) +M: System.Int32 SDL2.SDL::SDL_GetCPUCount() +M: System.Int32 SDL2.SDL::SDL_GetSystemRAM() +M: System.IntPtr SDL2.SDL_image::INTERNAL_IMG_LinkedVersion() +M: System.Int32 SDL2.SDL_image::IMG_Init(SDL2.SDL_image/IMG_InitFlags) +M: System.Void SDL2.SDL_image::IMG_Quit() +M: System.IntPtr SDL2.SDL_image::IMG_Load(System.String) +M: System.IntPtr SDL2.SDL_image::IMG_Load_RW(System.IntPtr,System.Int32) +M: System.IntPtr SDL2.SDL_image::IMG_LoadTyped_RW(System.IntPtr,System.Int32,System.String) +M: System.IntPtr SDL2.SDL_image::IMG_LoadTexture(System.IntPtr,System.String) +M: System.IntPtr SDL2.SDL_image::IMG_LoadTexture_RW(System.IntPtr,System.IntPtr,System.Int32) +M: System.IntPtr SDL2.SDL_image::IMG_LoadTextureTyped_RW(System.IntPtr,System.IntPtr,System.Int32,System.String) +M: System.Int32 SDL2.SDL_image::IMG_InvertAlpha(System.Int32) +M: System.IntPtr SDL2.SDL_image::IMG_ReadXPMFromArray(System.String[]) +M: System.Int32 SDL2.SDL_image::IMG_SavePNG(System.IntPtr,System.String) +M: System.Int32 SDL2.SDL_image::IMG_SavePNG_RW(System.IntPtr,System.IntPtr,System.Int32) +M: System.IntPtr SDL2.SDL_mixer::INTERNAL_MIX_Linked_Version() +M: System.Int32 SDL2.SDL_mixer::Mix_Init(SDL2.SDL_mixer/MIX_InitFlags) +M: System.Void SDL2.SDL_mixer::Mix_Quit() +M: System.Int32 SDL2.SDL_mixer::Mix_OpenAudio(System.Int32,System.UInt16,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_AllocateChannels(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_QuerySpec(System.Int32&,System.UInt16&,System.Int32&) +M: System.IntPtr SDL2.SDL_mixer::Mix_LoadWAV_RW(System.IntPtr,System.Int32) +M: System.IntPtr SDL2.SDL_mixer::Mix_LoadMUS(System.String) +M: System.IntPtr SDL2.SDL_mixer::Mix_QuickLoad_WAV(System.Byte[]) +M: System.IntPtr SDL2.SDL_mixer::Mix_QuickLoad_RAW(System.Byte[],System.UInt32) +M: System.Void SDL2.SDL_mixer::Mix_FreeChunk(System.IntPtr) +M: System.Void SDL2.SDL_mixer::Mix_FreeMusic(System.IntPtr) +M: System.Int32 SDL2.SDL_mixer::Mix_GetNumChunkDecoders() +M: System.String SDL2.SDL_mixer::Mix_GetChunkDecoder(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_GetNumMusicDecoders() +M: System.String SDL2.SDL_mixer::Mix_GetMusicDecoder(System.Int32) +M: SDL2.SDL_mixer/Mix_MusicType SDL2.SDL_mixer::Mix_GetMusicType(System.IntPtr) +M: System.Void SDL2.SDL_mixer::Mix_SetPostMix(SDL2.SDL_mixer/MixFuncDelegate,System.IntPtr) +M: System.Void SDL2.SDL_mixer::Mix_HookMusic(SDL2.SDL_mixer/MixFuncDelegate,System.IntPtr) +M: System.Void SDL2.SDL_mixer::Mix_HookMusicFinished(SDL2.SDL_mixer/MusicFinishedDelegate) +M: System.IntPtr SDL2.SDL_mixer::Mix_GetMusicHookData() +M: System.Void SDL2.SDL_mixer::Mix_ChannelFinished(SDL2.SDL_mixer/ChannelFinishedDelegate) +M: System.Int32 SDL2.SDL_mixer::Mix_RegisterEffect(System.Int32,SDL2.SDL_mixer/Mix_EffectFunc_t,SDL2.SDL_mixer/Mix_EffectDone_t,System.IntPtr) +M: System.Int32 SDL2.SDL_mixer::Mix_UnregisterEffect(System.Int32,SDL2.SDL_mixer/Mix_EffectFunc_t) +M: System.Int32 SDL2.SDL_mixer::Mix_UnregisterAllEffects(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_SetPanning(System.Int32,System.Byte,System.Byte) +M: System.Int32 SDL2.SDL_mixer::Mix_SetPosition(System.Int32,System.Int16,System.Byte) +M: System.Int32 SDL2.SDL_mixer::Mix_SetDistance(System.Int32,System.Byte) +M: System.Int32 SDL2.SDL_mixer::Mix_SetReverseStereo(System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_ReserveChannels(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_GroupChannel(System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_GroupChannels(System.Int32,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_GroupAvailable(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_GroupCount(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_GroupOldest(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_GroupNewer(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_PlayChannelTimed(System.Int32,System.IntPtr,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_PlayMusic(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_FadeInMusic(System.IntPtr,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_FadeInMusicPos(System.IntPtr,System.Int32,System.Int32,System.Double) +M: System.Int32 SDL2.SDL_mixer::Mix_FadeInChannelTimed(System.Int32,System.IntPtr,System.Int32,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_Volume(System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_VolumeChunk(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_VolumeMusic(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_HaltChannel(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_HaltGroup(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_HaltMusic() +M: System.Int32 SDL2.SDL_mixer::Mix_ExpireChannel(System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_FadeOutChannel(System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_FadeOutGroup(System.Int32,System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_FadeOutMusic(System.Int32) +M: SDL2.SDL_mixer/Mix_Fading SDL2.SDL_mixer::Mix_FadingMusic() +M: SDL2.SDL_mixer/Mix_Fading SDL2.SDL_mixer::Mix_FadingChannel(System.Int32) +M: System.Void SDL2.SDL_mixer::Mix_Pause(System.Int32) +M: System.Void SDL2.SDL_mixer::Mix_Resume(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_Paused(System.Int32) +M: System.Void SDL2.SDL_mixer::Mix_PauseMusic() +M: System.Void SDL2.SDL_mixer::Mix_ResumeMusic() +M: System.Void SDL2.SDL_mixer::Mix_RewindMusic() +M: System.Int32 SDL2.SDL_mixer::Mix_PausedMusic() +M: System.Int32 SDL2.SDL_mixer::Mix_SetMusicPosition(System.Double) +M: System.Int32 SDL2.SDL_mixer::Mix_Playing(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_PlayingMusic() +M: System.Int32 SDL2.SDL_mixer::Mix_SetMusicCMD(System.String) +M: System.Int32 SDL2.SDL_mixer::Mix_SetSynchroValue(System.Int32) +M: System.Int32 SDL2.SDL_mixer::Mix_GetSynchroValue() +M: System.Int32 SDL2.SDL_mixer::Mix_SetSoundFonts(System.String) +M: System.String SDL2.SDL_mixer::Mix_GetSoundFonts() +M: System.Int32 SDL2.SDL_mixer::Mix_EachSoundFont(SDL2.SDL_mixer/SoundFontDelegate,System.IntPtr) +M: System.IntPtr SDL2.SDL_mixer::Mix_GetChunk(System.Int32) +M: System.Void SDL2.SDL_mixer::Mix_CloseAudio() +M: System.IntPtr SDL2.SDL_ttf::INTERNAL_TTF_LinkedVersion() +M: System.Void SDL2.SDL_ttf::TTF_ByteSwappedUNICODE(System.Int32) +M: System.Int32 SDL2.SDL_ttf::TTF_Init() +M: System.IntPtr SDL2.SDL_ttf::TTF_OpenFont(System.String,System.Int32) +M: System.IntPtr SDL2.SDL_ttf::TTF_OpenFontRW(System.IntPtr,System.Int32,System.Int32) +M: System.IntPtr SDL2.SDL_ttf::TTF_OpenFontIndex(System.String,System.Int32,System.Int64) +M: System.IntPtr SDL2.SDL_ttf::TTF_OpenFontIndexRW(System.IntPtr,System.Int32,System.Int32,System.Int64) +M: System.Int32 SDL2.SDL_ttf::TTF_GetFontStyle(System.IntPtr) +M: System.Void SDL2.SDL_ttf::TTF_SetFontStyle(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL_ttf::TTF_GetFontOutline(System.IntPtr) +M: System.Void SDL2.SDL_ttf::TTF_SetFontOutline(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL_ttf::TTF_GetFontHinting(System.IntPtr) +M: System.Void SDL2.SDL_ttf::TTF_SetFontHinting(System.IntPtr,System.Int32) +M: System.Int32 SDL2.SDL_ttf::TTF_FontHeight(System.IntPtr) +M: System.Int32 SDL2.SDL_ttf::TTF_FontAscent(System.IntPtr) +M: System.Int32 SDL2.SDL_ttf::TTF_FontDescent(System.IntPtr) +M: System.Int32 SDL2.SDL_ttf::TTF_FontLineSkip(System.IntPtr) +M: System.Int32 SDL2.SDL_ttf::TTF_GetFontKerning(System.IntPtr) +M: System.Void SDL2.SDL_ttf::TTF_SetFontKerning(System.IntPtr,System.Int32) +M: System.Int64 SDL2.SDL_ttf::TTF_FontFaces(System.IntPtr) +M: System.Int32 SDL2.SDL_ttf::TTF_FontFaceIsFixedWidth(System.IntPtr) +M: System.String SDL2.SDL_ttf::TTF_FontFaceFamilyName(System.IntPtr) +M: System.String SDL2.SDL_ttf::TTF_FontFaceStyleName(System.IntPtr) +M: System.Int32 SDL2.SDL_ttf::TTF_GlyphIsProvided(System.IntPtr,System.UInt16) +M: System.Int32 SDL2.SDL_ttf::TTF_GlyphMetrics(System.IntPtr,System.UInt16,System.Int32&,System.Int32&,System.Int32&,System.Int32&,System.Int32&) +M: System.Int32 SDL2.SDL_ttf::TTF_SizeText(System.IntPtr,System.String,System.Int32&,System.Int32&) +M: System.Int32 SDL2.SDL_ttf::TTF_SizeUTF8(System.IntPtr,System.String,System.Int32&,System.Int32&) +M: System.Int32 SDL2.SDL_ttf::TTF_SizeUNICODE(System.IntPtr,System.String,System.Int32&,System.Int32&) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderText_Solid(System.IntPtr,System.String,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderUTF8_Solid(System.IntPtr,System.String,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderUNICODE_Solid(System.IntPtr,System.String,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderGlyph_Solid(System.IntPtr,System.UInt16,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderText_Shaded(System.IntPtr,System.String,SDL2.SDL/SDL_Color,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderUTF8_Shaded(System.IntPtr,System.String,SDL2.SDL/SDL_Color,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderUNICODE_Shaded(System.IntPtr,System.String,SDL2.SDL/SDL_Color,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderGlyph_Shaded(System.IntPtr,System.UInt16,SDL2.SDL/SDL_Color,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderText_Blended(System.IntPtr,System.String,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderUTF8_Blended(System.IntPtr,System.String,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderUNICODE_Blended(System.IntPtr,System.String,SDL2.SDL/SDL_Color) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderText_Blended_Wrapped(System.IntPtr,System.String,SDL2.SDL/SDL_Color,System.UInt32) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderUTF8_Blended_Wrapped(System.IntPtr,System.String,SDL2.SDL/SDL_Color,System.UInt32) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderUNICODE_Blended_Wrapped(System.IntPtr,System.String,SDL2.SDL/SDL_Color,System.UInt32) +M: System.IntPtr SDL2.SDL_ttf::TTF_RenderGlyph_Blended(System.IntPtr,System.UInt16,SDL2.SDL/SDL_Color) +M: System.Void SDL2.SDL_ttf::TTF_CloseFont(System.IntPtr) +M: System.Void SDL2.SDL_ttf::TTF_Quit() +M: System.Int32 SDL2.SDL_ttf::TTF_WasInit() +M: System.Int32 SDL2.SDL_ttf::SDL_GetFontKerningSize(System.IntPtr,System.Int32,System.Int32) + +R: Gendarme.Rules.Naming.DoNotPrefixValuesWithEnumNameRule +T: SDL2.SDL/SDL_BlendMode +T: SDL2.SDL/SDL_TextureAccess +T: SDL2.SDL/SDL_TextureModulate +T: SDL2.SDL/SDL_Scancode +T: SDL2.SDL_mixer/Mix_Fading + +R: Gendarme.Rules.Naming.DoNotUseReservedInEnumValueNamesRule +T: SDL2.SDL/SDL_Keymod + +R: Gendarme.Rules.Design.EnumsShouldUseInt32Rule +T: SDL2.SDL/SDL_MessageBoxFlags +T: SDL2.SDL/SDL_MessageBoxButtonFlags +T: SDL2.SDL/SDL_WindowEventID +T: SDL2.SDL/SDL_WindowFlags +T: SDL2.SDL/SDL_RendererFlags +T: SDL2.SDL/SDL_EventType +T: SDL2.SDL/SDL_Keymod + +R: Gendarme.Rules.Design.FlagsShouldNotDefineAZeroValueRule +T: SDL2.SDL/SDL_BlendMode +T: SDL2.SDL/SDL_RendererFlip +T: SDL2.SDL/SDL_TextureModulate + +R: Gendarme.Rules.Design.MarkAssemblyWithAssemblyVersionRule +A: SDL2-CS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + +R: Gendarme.Rules.Design.MarkAssemblyWithCLSCompliantRule +A: SDL2-CS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + +R: Gendarme.Rules.Design.MarkAssemblyWithComVisibleRule +A: SDL2-CS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + +R: Gendarme.Rules.Security.NativeFieldsShouldNotBeVisibleRule +T: SDL2.SDL/SDL_MessageBoxData +T: SDL2.SDL/SDL_DisplayMode +T: SDL2.SDL/SDL_RendererInfo +T: SDL2.SDL/SDL_Palette +T: SDL2.SDL/SDL_PixelFormat +T: SDL2.SDL/SDL_Surface +T: SDL2.SDL/SDL_DropEvent +T: SDL2.SDL/SDL_UserEvent +T: SDL2.SDL/SDL_SysWMEvent +T: SDL2.SDL/SDL_HapticCustom +T: SDL2.SDL/SDL_AudioSpec +T: SDL2.SDL/INTERNAL_windows_wminfo +T: SDL2.SDL/INTERNAL_x11_wminfo +T: SDL2.SDL/INTERNAL_directfb_wminfo +T: SDL2.SDL/INTERNAL_cocoa_wminfo +T: SDL2.SDL/INTERNAL_uikit_wminfo + +R: Gendarme.Rules.Performance.PreferLiteralOverInitOnlyFieldsRule +T: SDL2.SDL +T: SDL2.SDL_mixer + +R: Gendarme.Rules.Naming.UseCorrectCasingRule +M: System.IntPtr SDL2.LPUtf8StrMarshaler::MarshalManagedToNative(System.Object) +M: System.Void SDL2.LPUtf8StrMarshaler::CleanUpManagedData(System.Object) +M: System.UInt32 SDL2.SDL::SDL_FOURCC(System.Byte,System.Byte,System.Byte,System.Byte) +M: System.Int32 SDL2.SDL::SDL_VERSIONNUM(System.Int32,System.Int32,System.Int32) +M: System.Boolean SDL2.SDL::SDL_VERSION_ATLEAST(System.Int32,System.Int32,System.Int32) +M: System.Int32 SDL2.SDL::SDL_WINDOWPOS_UNDEFINED_DISPLAY(System.Int32) +M: System.Boolean SDL2.SDL::SDL_WINDOWPOS_ISUNDEFINED(System.Int32) +M: System.Int32 SDL2.SDL::SDL_WINDOWPOS_CENTERED_DISPLAY(System.Int32) +M: System.Boolean SDL2.SDL::SDL_WINDOWPOS_ISCENTERED(System.Int32) +M: System.UInt32 SDL2.SDL::SDL_DEFINE_PIXELFOURCC(System.Byte,System.Byte,System.Byte,System.Byte) +M: System.Byte SDL2.SDL::SDL_PIXELFLAG(System.UInt32) +M: System.Byte SDL2.SDL::SDL_PIXELTYPE(System.UInt32) +M: System.Byte SDL2.SDL::SDL_PIXELORDER(System.UInt32) +M: System.Byte SDL2.SDL::SDL_PIXELLAYOUT(System.UInt32) +M: System.Byte SDL2.SDL::SDL_BITSPERPIXEL(System.UInt32) +M: System.Byte SDL2.SDL::SDL_BYTESPERPIXEL(System.UInt32) +M: System.UInt32 SDL2.SDL::SDL_MasksToPixelFormatEnum(System.Int32,System.UInt32,System.UInt32,System.UInt32,System.UInt32) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_PixelFormatEnumToMasks(System.UInt32,System.Int32&,System.UInt32&,System.UInt32&,System.UInt32&,System.UInt32&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_HasIntersection(SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_IntersectRect(SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_IntersectRectAndLine(SDL2.SDL/SDL_Rect&,System.Int32&,System.Int32&,System.Int32&,System.Int32&) +M: SDL2.SDL/SDL_bool SDL2.SDL::SDL_RectEquals(SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&) +M: System.Void SDL2.SDL::SDL_UnionRect(SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&,SDL2.SDL/SDL_Rect&) +M: System.IntPtr SDL2.SDL::SDL_CreateRGBSurface(System.UInt32,System.Int32,System.Int32,System.Int32,System.UInt32,System.UInt32,System.UInt32,System.UInt32) +M: System.IntPtr SDL2.SDL::SDL_CreateRGBSurfaceFrom(System.IntPtr,System.Int32,System.Int32,System.Int32,System.Int32,System.UInt32,System.UInt32,System.UInt32,System.UInt32) +M: System.Int32 SDL2.SDL::SDL_PollEvent(SDL2.SDL/SDL_Event&) +M: System.Int32 SDL2.SDL::SDL_WaitEvent(SDL2.SDL/SDL_Event&) +M: System.Int32 SDL2.SDL::SDL_WaitEventTimeout(SDL2.SDL/SDL_Event&,System.Int32) +M: System.Int32 SDL2.SDL::SDL_PushEvent(SDL2.SDL/SDL_Event&) +M: SDL2.SDL/SDL_Keycode SDL2.SDL::SDL_SCANCODE_TO_KEYCODE(SDL2.SDL/SDL_Scancode) +M: System.UInt32 SDL2.SDL::SDL_BUTTON(System.UInt32) +M: System.Boolean SDL2.SDL::SDL_TICKS_PASSED(System.UInt32,System.UInt32) +M: System.Void SDL2.SDL_image::SDL_IMAGE_VERSION(SDL2.SDL/SDL_version&) +M: System.Void SDL2.SDL_mixer::SDL_MIXER_VERSION(SDL2.SDL/SDL_version&) +M: System.Void SDL2.SDL_ttf::SDL_TTF_VERSION(SDL2.SDL/SDL_version&) + +R: Gendarme.Rules.Naming.UseCorrectSuffixRule +T: SDL2.SDL/SDL_MessageBoxFlags +T: SDL2.SDL/SDL_MessageBoxButtonFlags +T: SDL2.SDL/SDL_WindowFlags +T: SDL2.SDL/SDL_RendererFlags +T: SDL2.SDL/SDL_PIXELTYPE_ENUM +T: SDL2.SDL/SDL_PIXELORDER_ENUM +T: SDL2.SDL/SDL_PACKEDLAYOUT_ENUM +T: SDL2.SDL/SDL_HapticCondition +T: SDL2.SDL_image/IMG_InitFlags +T: SDL2.SDL_mixer/MIX_InitFlags +T: SDL2.SDL_mixer/MixFuncDelegate +T: SDL2.SDL_mixer/MusicFinishedDelegate +T: SDL2.SDL_mixer/ChannelFinishedDelegate +T: SDL2.SDL_mixer/SoundFontDelegate + +R: Gendarme.Rules.Naming.UsePreferredTermsRule +M: System.Void SDL2.SDL::SDL_LogInfo(System.Int32,System.String) +T: SDL2.SDL/SDL_LogOutputFunction + +R: Gendarme.Rules.Naming.UseSingularNameInEnumsUnlessAreFlagsRule +T: SDL2.SDL/SDL_TextureAccess +T: SDL2.SDL/SDL_GameControllerAxis +T: SDL2.SDL/SDL_AudioStatus + diff --git a/gendarme/theoraplay.ignore b/gendarme/theoraplay.ignore new file mode 100644 index 0000000..a77657a --- /dev/null +++ b/gendarme/theoraplay.ignore @@ -0,0 +1,61 @@ +R: Gendarme.Rules.Naming.AvoidNonAlphanumericIdentifierRule +M: System.IntPtr TheoraPlay::THEORAPLAY_startDecodeFile(System.String,System.UInt32,TheoraPlay/THEORAPLAY_VideoFormat) +M: System.Void TheoraPlay::THEORAPLAY_stopDecode(System.IntPtr) +M: System.Int32 TheoraPlay::THEORAPLAY_isDecoding(System.IntPtr) +M: System.Int32 TheoraPlay::THEORAPLAY_decodingError(System.IntPtr) +M: System.Int32 TheoraPlay::THEORAPLAY_isInitialized(System.IntPtr) +M: System.Int32 TheoraPlay::THEORAPLAY_hasVideoStream(System.IntPtr) +M: System.Int32 TheoraPlay::THEORAPLAY_hasAudioStream(System.IntPtr) +M: System.UInt32 TheoraPlay::THEORAPLAY_availableVideo(System.IntPtr) +M: System.UInt32 TheoraPlay::THEORAPLAY_availableAudio(System.IntPtr) +M: System.IntPtr TheoraPlay::THEORAPLAY_getAudio(System.IntPtr) +M: System.Void TheoraPlay::THEORAPLAY_freeAudio(System.IntPtr) +M: System.IntPtr TheoraPlay::THEORAPLAY_getVideo(System.IntPtr) +M: System.Void TheoraPlay::THEORAPLAY_freeVideo(System.IntPtr) +T: TheoraPlay/THEORAPLAY_VideoFormat +T: TheoraPlay/THEORAPLAY_VideoFrame +T: TheoraPlay/THEORAPLAY_AudioPacket + +R: Gendarme.Rules.Design.AvoidVisibleFieldsRule +T: TheoraPlay/THEORAPLAY_VideoFrame +T: TheoraPlay/THEORAPLAY_AudioPacket + +R: Gendarme.Rules.Design.AvoidVisibleNestedTypesRule +T: TheoraPlay/THEORAPLAY_VideoFormat +T: TheoraPlay/THEORAPLAY_VideoFrame +T: TheoraPlay/THEORAPLAY_AudioPacket + +R: Gendarme.Rules.Interoperability.CentralizePInvokesIntoNativeMethodsTypeRule +M: System.IntPtr TheoraPlay::THEORAPLAY_startDecodeFile(System.String,System.UInt32,TheoraPlay/THEORAPLAY_VideoFormat) +M: System.Void TheoraPlay::THEORAPLAY_stopDecode(System.IntPtr) +M: System.Int32 TheoraPlay::THEORAPLAY_isDecoding(System.IntPtr) +M: System.Int32 TheoraPlay::THEORAPLAY_decodingError(System.IntPtr) +M: System.Int32 TheoraPlay::THEORAPLAY_isInitialized(System.IntPtr) +M: System.Int32 TheoraPlay::THEORAPLAY_hasVideoStream(System.IntPtr) +M: System.Int32 TheoraPlay::THEORAPLAY_hasAudioStream(System.IntPtr) +M: System.UInt32 TheoraPlay::THEORAPLAY_availableVideo(System.IntPtr) +M: System.UInt32 TheoraPlay::THEORAPLAY_availableAudio(System.IntPtr) +M: System.IntPtr TheoraPlay::THEORAPLAY_getAudio(System.IntPtr) +M: System.Void TheoraPlay::THEORAPLAY_freeAudio(System.IntPtr) +M: System.IntPtr TheoraPlay::THEORAPLAY_getVideo(System.IntPtr) +M: System.Void TheoraPlay::THEORAPLAY_freeVideo(System.IntPtr) + +R: Gendarme.Rules.Design.MarkAssemblyWithAssemblyVersionRule +A: TheoraPlay-CS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + +R: Gendarme.Rules.Design.MarkAssemblyWithCLSCompliantRule +A: TheoraPlay-CS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + +R: Gendarme.Rules.Design.MarkAssemblyWithComVisibleRule +A: TheoraPlay-CS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + +R: Gendarme.Rules.Security.NativeFieldsShouldNotBeVisibleRule +T: TheoraPlay/THEORAPLAY_VideoFrame +T: TheoraPlay/THEORAPLAY_AudioPacket + +R: Gendarme.Rules.Naming.UseCorrectCasingRule +M: TheoraPlay/THEORAPLAY_VideoFrame TheoraPlay::getVideoFrame(System.IntPtr) +M: TheoraPlay/THEORAPLAY_AudioPacket TheoraPlay::getAudioPacket(System.IntPtr) +M: System.Single[] TheoraPlay::getSamples(System.IntPtr,System.Int32) +M: System.Byte[] TheoraPlay::getPixels(System.IntPtr,System.Int32) + diff --git a/gendarme/vorbisfile.ignore b/gendarme/vorbisfile.ignore new file mode 100644 index 0000000..e02df67 --- /dev/null +++ b/gendarme/vorbisfile.ignore @@ -0,0 +1,94 @@ +R: Gendarme.Rules.Design.Generic.AvoidDeclaringCustomDelegatesRule +T: Vorbisfile/read_func +T: Vorbisfile/seek_func +T: Vorbisfile/close_func +T: Vorbisfile/tell_func + +R: Gendarme.Rules.Performance.AvoidLargeStructureRule +T: Vorbisfile/vorbis_info + +R: Gendarme.Rules.Naming.AvoidNonAlphanumericIdentifierRule +M: System.Int32 Vorbisfile::ov_fopen(System.String,System.IntPtr&) +M: System.Int32 Vorbisfile::ov_open_callbacks(System.IntPtr,System.IntPtr&,System.IntPtr,System.IntPtr,Vorbisfile/ov_callbacks) +M: Vorbisfile/vorbis_info Vorbisfile::ov_info(System.IntPtr,System.Int32) +M: Vorbisfile/vorbis_comment Vorbisfile::ov_comment(System.IntPtr,System.Int32) +M: System.Double Vorbisfile::ov_time_total(System.IntPtr,System.Int32) +M: System.Int64 Vorbisfile::ov_read(System.IntPtr,System.Byte[],System.Int32,System.Int32,System.Int32,System.Int32,System.Int32&) +M: System.Int64 Vorbisfile::ov_read(System.IntPtr,System.IntPtr,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32&) +M: System.Int32 Vorbisfile::ov_time_seek(System.IntPtr,System.Double) +M: System.Int32 Vorbisfile::ov_clear(System.IntPtr&) +T: Vorbisfile/SeekWhence +T: Vorbisfile/read_func +T: Vorbisfile/seek_func +T: Vorbisfile/close_func +T: Vorbisfile/tell_func +T: Vorbisfile/vorbis_info +T: Vorbisfile/vorbis_comment +T: Vorbisfile/ov_callbacks + +R: Gendarme.Rules.Design.AvoidRefAndOutParametersRule +M: System.Int32 Vorbisfile::ov_fopen(System.String,System.IntPtr&) +M: System.Int32 Vorbisfile::ov_open_callbacks(System.IntPtr,System.IntPtr&,System.IntPtr,System.IntPtr,Vorbisfile/ov_callbacks) +M: System.Int32 Vorbisfile::ov_clear(System.IntPtr&) + +R: Gendarme.Rules.Design.AvoidVisibleFieldsRule +T: Vorbisfile/vorbis_info +T: Vorbisfile/vorbis_comment +T: Vorbisfile/ov_callbacks + +R: Gendarme.Rules.Design.AvoidVisibleNestedTypesRule +T: Vorbisfile/SeekWhence +T: Vorbisfile/read_func +T: Vorbisfile/seek_func +T: Vorbisfile/close_func +T: Vorbisfile/tell_func +T: Vorbisfile/vorbis_info +T: Vorbisfile/vorbis_comment +T: Vorbisfile/ov_callbacks + +R: Gendarme.Rules.Interoperability.CentralizePInvokesIntoNativeMethodsTypeRule +M: System.IntPtr Vorbisfile::malloc(System.IntPtr) +M: System.Void Vorbisfile::free(System.IntPtr) +M: System.Int32 Vorbisfile::INTERNAL_ov_fopen(System.String,System.IntPtr) +M: System.Int32 Vorbisfile::INTERNAL_ov_open_callbacks(System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr,Vorbisfile/ov_callbacks) +M: System.IntPtr Vorbisfile::INTERNAL_ov_info(System.IntPtr,System.Int32) +M: System.IntPtr Vorbisfile::INTERNAL_ov_comment(System.IntPtr,System.Int32) +M: System.Double Vorbisfile::ov_time_total(System.IntPtr,System.Int32) +M: System.Int64 Vorbisfile::ov_read(System.IntPtr,System.Byte[],System.Int32,System.Int32,System.Int32,System.Int32,System.Int32&) +M: System.Int64 Vorbisfile::ov_read(System.IntPtr,System.IntPtr,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32&) +M: System.Int32 Vorbisfile::ov_time_seek(System.IntPtr,System.Double) +M: System.Int32 Vorbisfile::INTERNAL_ov_clear(System.IntPtr) + +R: Gendarme.Rules.Design.MarkAssemblyWithAssemblyVersionRule +A: Vorbisfile-CS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + +R: Gendarme.Rules.Design.MarkAssemblyWithCLSCompliantRule +A: Vorbisfile-CS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + +R: Gendarme.Rules.Design.MarkAssemblyWithComVisibleRule +A: Vorbisfile-CS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + +R: Gendarme.Rules.Security.NativeFieldsShouldNotBeVisibleRule +T: Vorbisfile/vorbis_info +T: Vorbisfile/vorbis_comment + +R: Gendarme.Rules.Naming.UseCorrectCasingRule +M: System.IntPtr Vorbisfile::malloc(System.IntPtr) +M: System.Void Vorbisfile::free(System.IntPtr) +M: System.Int32 Vorbisfile::ov_fopen(System.String,System.IntPtr&) +M: System.Int32 Vorbisfile::ov_open_callbacks(System.IntPtr,System.IntPtr&,System.IntPtr,System.IntPtr,Vorbisfile/ov_callbacks) +M: Vorbisfile/vorbis_info Vorbisfile::ov_info(System.IntPtr,System.Int32) +M: Vorbisfile/vorbis_comment Vorbisfile::ov_comment(System.IntPtr,System.Int32) +M: System.Double Vorbisfile::ov_time_total(System.IntPtr,System.Int32) +M: System.Int64 Vorbisfile::ov_read(System.IntPtr,System.Byte[],System.Int32,System.Int32,System.Int32,System.Int32,System.Int32&) +M: System.Int64 Vorbisfile::ov_read(System.IntPtr,System.IntPtr,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32&) +M: System.Int32 Vorbisfile::ov_time_seek(System.IntPtr,System.Double) +M: System.Int32 Vorbisfile::ov_clear(System.IntPtr&) +T: Vorbisfile/read_func +T: Vorbisfile/seek_func +T: Vorbisfile/close_func +T: Vorbisfile/tell_func +T: Vorbisfile/vorbis_info +T: Vorbisfile/vorbis_comment +T: Vorbisfile/ov_callbacks + diff --git a/lib/MojoShader-CS b/lib/MojoShader-CS new file mode 160000 index 0000000..5421230 --- /dev/null +++ b/lib/MojoShader-CS @@ -0,0 +1 @@ +Subproject commit 54212309dedb163a05092fc0ed6ef5bf8bba35da diff --git a/lib/OpenAL-CS b/lib/OpenAL-CS new file mode 160000 index 0000000..1babf1e --- /dev/null +++ b/lib/OpenAL-CS @@ -0,0 +1 @@ +Subproject commit 1babf1e4baf88d843b98bf1ff7d651a2a1e7e36d diff --git a/lib/SDL2-CS b/lib/SDL2-CS new file mode 160000 index 0000000..5d5f415 --- /dev/null +++ b/lib/SDL2-CS @@ -0,0 +1 @@ +Subproject commit 5d5f4154bb9b9db5b0922ade470507210de06331 diff --git a/lib/TheoraPlay-CS b/lib/TheoraPlay-CS new file mode 160000 index 0000000..d5bae69 --- /dev/null +++ b/lib/TheoraPlay-CS @@ -0,0 +1 @@ +Subproject commit d5bae691e56d0a4b7334206d6b92b4ff3cb2cd04 diff --git a/lib/Vorbisfile-CS b/lib/Vorbisfile-CS new file mode 160000 index 0000000..844fbd1 --- /dev/null +++ b/lib/Vorbisfile-CS @@ -0,0 +1 @@ +Subproject commit 844fbd1ab7342a95d761f5e177678de954ec2a21 diff --git a/licenses/LICENSE b/licenses/LICENSE new file mode 100644 index 0000000..2e7a0ba --- /dev/null +++ b/licenses/LICENSE @@ -0,0 +1,63 @@ +Microsoft Public License (Ms-PL) +FNA - Copyright 2009-2015 Ethan Lee and the MonoGame Team + +All rights reserved. + +This license governs use of the accompanying software. If you use the software, +you accept this license. If you do not accept the license, do not use the +software. + +1. Definitions + +The terms "reproduce," "reproduction," "derivative works," and "distribution" +have the same meaning here as under U.S. copyright law. + +A "contribution" is the original software, or any additions or changes to the +software. + +A "contributor" is any person that distributes its contribution under this +license. + +"Licensed patents" are a contributor's patent claims that read directly on its +contribution. + +2. Grant of Rights + +(A) Copyright Grant- Subject to the terms of this license, including the +license conditions and limitations in section 3, each contributor grants you a +non-exclusive, worldwide, royalty-free copyright license to reproduce its +contribution, prepare derivative works of its contribution, and distribute its +contribution or any derivative works that you create. + +(B) Patent Grant- Subject to the terms of this license, including the license +conditions and limitations in section 3, each contributor grants you a +non-exclusive, worldwide, royalty-free license under its licensed patents to +make, have made, use, sell, offer for sale, import, and/or otherwise dispose of +its contribution in the software or derivative works of the contribution in the +software. + +3. Conditions and Limitations + +(A) No Trademark License- This license does not grant you rights to use any +contributors' name, logo, or trademarks. + +(B) If you bring a patent claim against any contributor over patents that you +claim are infringed by the software, your patent license from such contributor +to the software ends automatically. + +(C) If you distribute any portion of the software, you must retain all +copyright, patent, trademark, and attribution notices that are present in the +software. + +(D) If you distribute any portion of the software in source code form, you may +do so only under this license by including a complete copy of this license with +your distribution. If you distribute any portion of the software in compiled or +object code form, you may only do so under a license that complies with this +license. + +(E) The software is licensed "as-is." You bear the risk of using it. The +contributors give no express warranties, guarantees or conditions. You may have +additional consumer rights under your local laws which this license cannot +change. To the extent permitted under your local laws, the contributors exclude +the implied warranties of merchantability, fitness for a particular purpose and +non-infringement. diff --git a/licenses/lzxdecoder.LICENSE b/licenses/lzxdecoder.LICENSE new file mode 100644 index 0000000..c570d11 --- /dev/null +++ b/licenses/lzxdecoder.LICENSE @@ -0,0 +1,29 @@ +LzxDecoder.cs was derived from libmspack +Copyright 2003-2004 Stuart Caie +Copyright 2011 Ali Scissons + +The LZX method was created by Jonathan Forbes and Tomi Poutanen, adapted +by Microsoft Corporation. + +This source file is Dual licensed; meaning the end-user of this source file +may redistribute/modify it under the LGPL 2.1 or MS-PL licenses. + +About +----- +This derived work is recognized by Stuart Caie and is authorized to adapt +any changes made to lzxd.c in his libmspack library and will still retain +this dual licensing scheme. Big thanks to Stuart Caie! + +This file is a pure C# port of the lzxd.c file from libmspack, with minor +changes towards the decompression of XNB files. The original decompression +software of LZX encoded data was written by Suart Caie in his +libmspack/cabextract projects, which can be located at +http://http://www.cabextract.org.uk/ + +GNU Lesser General Public License, Version 2.1 +---------------------------------------------- +https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html + +Microsoft Public License +------------------------ +http://www.opensource.org/licenses/ms-pl.html diff --git a/licenses/monoxna.LICENSE b/licenses/monoxna.LICENSE new file mode 100644 index 0000000..185aa38 --- /dev/null +++ b/licenses/monoxna.LICENSE @@ -0,0 +1,22 @@ +MIT License +Copyright 2006 The Mono.Xna Team + +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. diff --git a/licenses/unxwb.LICENSE b/licenses/unxwb.LICENSE new file mode 100644 index 0000000..db65e36 --- /dev/null +++ b/licenses/unxwb.LICENSE @@ -0,0 +1,12 @@ +The unxwb project, written by Luigi Auriemma, was released in 2006 under the +GNU General Public License, version 2.0: + +http://www.gnu.org/licenses/gpl-2.0.html + +While the unxwb project was released under the GPL, Luigi has given express +permission to the MonoGame project to use code from unxwb under the MonoGame +project license. See LICENSE for details. + +The unxwb website can be found here: + +http://aluigi.altervista.org/papers.htm#xbox diff --git a/src/Audio/AudioCategory.cs b/src/Audio/AudioCategory.cs new file mode 100644 index 0000000..dccbe4a --- /dev/null +++ b/src/Audio/AudioCategory.cs @@ -0,0 +1,337 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +using System.Diagnostics; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + // http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.audiocategory.aspx + public struct AudioCategory : IEquatable + { + #region Internal Primitive Type Container Class + + internal class PrimitiveInstance + { + public T Value; + public PrimitiveInstance(T initial) + { + Value = initial; + } + } + + #endregion + + #region Public Properties + + private string INTERNAL_name; + public string Name + { + get + { + return INTERNAL_name; + } + } + + #endregion + + #region Internal Variables + + // Grumble, struct returns... + internal PrimitiveInstance INTERNAL_volume; + + internal CrossfadeType crossfadeType; + + #endregion + + #region Private Variables + + private List activeCues; + + private Dictionary cueInstanceCounts; + + private byte maxCueInstances; + private MaxInstanceBehavior maxCueBehavior; + private ushort maxFadeInMS; + private ushort maxFadeOutMS; + + #endregion + + #region Internal Constructor + + internal AudioCategory( + string name, + float volume, + byte maxInstances, + int maxBehavior, + ushort fadeInMS, + ushort fadeOutMS, + int fadeType + ) { + INTERNAL_name = name; + INTERNAL_volume = new PrimitiveInstance(volume); + activeCues = new List(); + cueInstanceCounts = new Dictionary(); + + maxCueInstances = maxInstances; + maxCueBehavior = (MaxInstanceBehavior) maxBehavior; + maxFadeInMS = fadeInMS; + maxFadeOutMS = fadeOutMS; + crossfadeType = (CrossfadeType) fadeType; + } + + #endregion + + #region Public Methods + + public void Pause() + { + lock (activeCues) + { + foreach (Cue curCue in activeCues) + { + curCue.Pause(); + } + } + } + + public void Resume() + { + lock (activeCues) + { + foreach (Cue curCue in activeCues) + { + curCue.Resume(); + } + } + } + + public void SetVolume(float volume) + { + lock (activeCues) + { + INTERNAL_volume.Value = volume; + } + } + + public void Stop(AudioStopOptions options) + { + lock (activeCues) + { + while (activeCues.Count > 0) + { + Cue curCue = activeCues[0]; + curCue.Stop(options); + curCue.SetVariable("NumCueInstances", 0); + cueInstanceCounts[curCue.Name] -= 1; + } + activeCues.Clear(); + } + } + + public override int GetHashCode() + { + return Name.GetHashCode(); + } + + public bool Equals(AudioCategory other) + { + return (GetHashCode() == other.GetHashCode()); + } + + public override bool Equals(Object obj) + { + if (obj is AudioCategory) + { + return Equals((AudioCategory) obj); + } + return false; + } + + public static bool operator ==( + AudioCategory value1, + AudioCategory value2 + ) { + return value1.Equals(value2); + } + + public static bool operator !=( + AudioCategory value1, + AudioCategory value2 + ) { + return !(value1.Equals(value2)); + } + + #endregion + + #region Internal Methods + + internal void INTERNAL_update() + { + /* Believe it or not, someone might run the update on a thread. + * So, we're going to give a lock to this method. + * -flibit + */ + lock (activeCues) + { + for (int i = 0; i < activeCues.Count; i += 1) + { + if (!activeCues[i].INTERNAL_update()) + { + i -= 1; + } + } + foreach (Cue curCue in activeCues) + { + curCue.SetVariable( + "NumCueInstances", + cueInstanceCounts[curCue.Name] + ); + } + } + } + + internal void INTERNAL_initCue(Cue newCue) + { + lock (activeCues) + { + if (!cueInstanceCounts.ContainsKey(newCue.Name)) + { + cueInstanceCounts.Add(newCue.Name, 0); + } + newCue.SetVariable("NumCueInstances", cueInstanceCounts[newCue.Name]); + } + } + + internal bool INTERNAL_addCue(Cue newCue) + { + lock (activeCues) + { + if (activeCues.Count >= maxCueInstances) + { + if (maxCueBehavior == MaxInstanceBehavior.Fail) + { + return false; // Just ignore us... + } + else if (maxCueBehavior == MaxInstanceBehavior.Queue) + { + newCue.INTERNAL_startFadeIn(maxFadeInMS); + activeCues[0].INTERNAL_startFadeOut(maxFadeOutMS); + } + else if (maxCueBehavior == MaxInstanceBehavior.ReplaceOldest) + { + INTERNAL_removeOldestCue(activeCues[0].Name); + } + else if (maxCueBehavior == MaxInstanceBehavior.ReplaceQuietest) + { + float lowestVolume = float.MaxValue; + int lowestIndex = -1; + for (int i = 0; i < activeCues.Count; i += 1) + { + float vol = activeCues[i].INTERNAL_calculateVolume(); + if (vol < lowestVolume) + { + lowestVolume = vol; + lowestIndex = i; + } + } + if (lowestIndex > -1) + { + cueInstanceCounts[activeCues[lowestIndex].Name] -= 1; + activeCues[lowestIndex].Stop(AudioStopOptions.AsAuthored); + } + } + else if (maxCueBehavior == MaxInstanceBehavior.ReplaceLowestPriority) + { + // FIXME: Priority? + INTERNAL_removeOldestCue(activeCues[0].Name); + } + } + cueInstanceCounts[newCue.Name] += 1; + newCue.SetVariable("NumCueInstances", cueInstanceCounts[newCue.Name]); + activeCues.Add(newCue); + } + return true; + } + + internal void INTERNAL_removeLatestCue() + { + lock (activeCues) + { + Cue toDie = activeCues[activeCues.Count - 1]; + cueInstanceCounts[toDie.Name] -= 1; + activeCues.RemoveAt(activeCues.Count - 1); + } + } + + internal void INTERNAL_removeOldestCue(string name) + { + lock (activeCues) + { + for (int i = 0; i < activeCues.Count; i += 1) + { + if (activeCues[i].Name.Equals(name)) + { + activeCues[i].Stop(AudioStopOptions.AsAuthored); + return; + } + } + } + } + + internal void INTERNAL_removeQuietestCue(string name) + { + float lowestVolume = float.MaxValue; + int lowestIndex = -1; + + lock (activeCues) + { + for (int i = 0; i < activeCues.Count; i += 1) + { + if (activeCues[i].Name.Equals(name)) + { + float vol = activeCues[i].INTERNAL_calculateVolume(); + if (vol < lowestVolume) + { + lowestVolume = vol; + lowestIndex = i; + } + } + } + + if (lowestIndex > -1) + { + cueInstanceCounts[name] -= 1; + activeCues[lowestIndex].Stop(AudioStopOptions.AsAuthored); + } + } + } + + internal void INTERNAL_removeActiveCue(Cue cue) + { + // FIXME: Avoid calling this when a Cue is GC'd! -flibit + if (activeCues != null) + { + lock (activeCues) + { + if (activeCues.Contains(cue)) + { + activeCues.Remove(cue); + cueInstanceCounts[cue.Name] -= 1; + } + } + } + } + + #endregion + } +} diff --git a/src/Audio/AudioChannels.cs b/src/Audio/AudioChannels.cs new file mode 100644 index 0000000..f36c02a --- /dev/null +++ b/src/Audio/AudioChannels.cs @@ -0,0 +1,18 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + // http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.audiochannels.aspx + public enum AudioChannels + { + Mono = 1, + Stereo = 2 + } +} diff --git a/src/Audio/AudioDevice.cs b/src/Audio/AudioDevice.cs new file mode 100644 index 0000000..4806f2d --- /dev/null +++ b/src/Audio/AudioDevice.cs @@ -0,0 +1,207 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + internal static class AudioDevice + { + #region RendererDetail List + + public static ReadOnlyCollection Renderers; + + #endregion + + #region Internal AL Device + + // FIXME: readonly? -flibit + public static IALDevice ALDevice; + + #endregion + + #region SoundEffect Management Variables + + // FIXME: readonly? -flibit + + // Used to store SoundEffectInstances generated internally. + public static List InstancePool; + + // Used to store all DynamicSoundEffectInstances, to check buffer counts. + public static List DynamicInstancePool; + + #endregion + + #region Microphone Management Variables + + // FIXME: readonly? -flibit + + // Used to store Microphones that are currently recording + public static List ActiveMics; + + #endregion + + #region Public Static Initialize Method + + public static void Initialize() + { + // We should only have one of these! + if (ALDevice != null) + { + System.Console.WriteLine("ALDevice already exists, overwriting!"); + } + + bool disableSound = Environment.GetEnvironmentVariable( + "FNA_AUDIO_DISABLE_SOUND" + ) == "1"; + + if (disableSound) + { + ALDevice = new NullDevice(); + } + else + { + try + { + ALDevice = new OpenALDevice(); + } + catch(DllNotFoundException e) + { + System.Console.WriteLine("OpenAL not found! Need FNA.dll.config?"); + throw e; + } + catch(Exception) + { + /* We ignore and device creation exceptions, + * as they are handled down the line with Instance != null + */ + } + } + + // Populate device list + if (ALDevice != null) + { + Renderers = ALDevice.GetDevices(); + Microphone.All = ALDevice.GetCaptureDevices(); + + InstancePool = new List(); + DynamicInstancePool = new List(); + ActiveMics = new List(); + } + else + { + Renderers = new ReadOnlyCollection(new List()); + Microphone.All = new ReadOnlyCollection(new List()); + } + } + + #endregion + + #region Public Static Dispose Method + + public static void Dispose() + { + if (ALDevice != null) + { + InstancePool.Clear(); + DynamicInstancePool.Clear(); + ALDevice.Dispose(); + // ALDevice = null; <- May cause Exceptions! + } + } + + #endregion + + #region Public Static Update Methods + + public static void Update() + { + if (ALDevice != null) + { + ALDevice.Update(); + + for (int i = 0; i < InstancePool.Count; i += 1) + { + if (InstancePool[i].State == SoundState.Stopped) + { + InstancePool[i].Dispose(); + InstancePool.RemoveAt(i); + i -= 1; + } + } + + foreach (DynamicSoundEffectInstance sfi in DynamicInstancePool) + { + sfi.Update(); + } + + foreach (Microphone mic in ActiveMics) + { + mic.CheckBuffer(); + } + } + } + + #endregion + + #region Public Static Buffer Methods + + public static IALBuffer GenBuffer() + { + if (ALDevice == null) + { + throw new NoAudioHardwareException(); + } + return ALDevice.GenBuffer(); + } + + public static IALBuffer GenBuffer( + byte[] data, + uint sampleRate, + uint channels, + uint loopStart, + uint loopEnd, + bool isADPCM, + uint formatParameter + ) { + if (ALDevice == null) + { + throw new NoAudioHardwareException(); + } + return ALDevice.GenBuffer( + data, + sampleRate, + channels, + loopStart, + loopEnd, + isADPCM, + formatParameter + ); + } + + #endregion + + #region Public Static Reverb Methods + + public static IALReverb GenReverb(DSPParameter[] parameters) + { + if (ALDevice == null) + { + throw new NoAudioHardwareException(); + } + return ALDevice.GenReverb(parameters); + } + + #endregion + } +} diff --git a/src/Audio/AudioEmitter.cs b/src/Audio/AudioEmitter.cs new file mode 100644 index 0000000..f8e7199 --- /dev/null +++ b/src/Audio/AudioEmitter.cs @@ -0,0 +1,78 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + // http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.audioemitter.aspx + public class AudioEmitter + { + #region Public Properties + + private float INTERNAL_dopplerScale; + public float DopplerScale + { + get + { + return INTERNAL_dopplerScale; + } + set + { + if (value < 0.0f) + { + throw new ArgumentOutOfRangeException("AudioEmitter.DopplerScale must be greater than or equal to 0.0f"); + } + INTERNAL_dopplerScale = value; + } + } + + public Vector3 Forward + { + get; + set; + } + + public Vector3 Position + { + get; + set; + } + + + public Vector3 Up + { + get; + set; + } + + public Vector3 Velocity + { + get; + set; + } + + #endregion + + #region Public Constructor + + public AudioEmitter() + { + DopplerScale = 1.0f; + Forward = Vector3.Forward; + Position = Vector3.Zero; + Up = Vector3.Up; + Velocity = Vector3.Zero; + } + + #endregion + } +} diff --git a/src/Audio/AudioEngine.cs b/src/Audio/AudioEngine.cs new file mode 100644 index 0000000..c7d5e50 --- /dev/null +++ b/src/Audio/AudioEngine.cs @@ -0,0 +1,617 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + // http://msdn.microsoft.com/en-us/library/dd940262.aspx + public class AudioEngine : IDisposable + { + #region Public Constants + + public const int ContentVersion = 46; + + #endregion + + #region Public Properties + + public ReadOnlyCollection RendererDetails + { + get + { + return AudioDevice.Renderers; + } + } + + public bool IsDisposed + { + get; + private set; + } + + #endregion + + #region Private Variables + + private Dictionary INTERNAL_waveBanks; + + private List INTERNAL_categories; + private List INTERNAL_variables; + private Dictionary INTERNAL_RPCs; + private List INTERNAL_dspParameters; + private Dictionary INTERNAL_dspPresets; + + #endregion + + #region Disposing Event + + public event EventHandler Disposing; + + #endregion + + #region Public Constructors + + public AudioEngine(string settingsFile) + { + if (String.IsNullOrEmpty(settingsFile)) + { + throw new ArgumentNullException("settingsFile"); + } + + using (Stream stream = TitleContainer.OpenStream(settingsFile)) + using (BinaryReader reader = new BinaryReader(stream)) + { + // Check the file header. Should be 'XGSF' + if (reader.ReadUInt32() != 0x46534758) + { + throw new ArgumentException("XGSF format not recognized!"); + } + + // Check the Content and Tool versions + if (reader.ReadUInt16() != ContentVersion) + { + throw new ArgumentException("XGSF Content version!"); + } + if (reader.ReadUInt16() != 42) + { + throw new ArgumentException("XGSF Tool version!"); + } + + // Unknown value + reader.ReadUInt16(); + + // Last Modified, Unused + reader.ReadUInt64(); + + // XACT Version, Unused + reader.ReadByte(); + + // Number of AudioCategories + ushort numCategories = reader.ReadUInt16(); + + // Number of XACT Variables + ushort numVariables = reader.ReadUInt16(); + + // KEY#1 Length + /*ushort numKeyOne =*/ reader.ReadUInt16(); + + // KEY#2 Length + /*ushort numKeyTwo =*/ reader.ReadUInt16(); + + // Number of RPC Variables + ushort numRPCs = reader.ReadUInt16(); + + // Number of DSP Presets/Parameters + ushort numDSPPresets = reader.ReadUInt16(); + ushort numDSPParameters = reader.ReadUInt16(); + + // Category Offset in XGS File + uint categoryOffset = reader.ReadUInt32(); + + // Variable Offset in XGS File + uint variableOffset = reader.ReadUInt32(); + + // KEY#1 Offset + /*uint keyOneOffset =*/ reader.ReadUInt32(); + + // Category Name Index Offset, unused + reader.ReadUInt32(); + + // KEY#2 Offset + /*uint keyTwoOffset =*/ reader.ReadUInt32(); + + // Variable Name Index Offset, unused + reader.ReadUInt32(); + + // Category Name Offset in XGS File + uint categoryNameOffset = reader.ReadUInt32(); + + // Variable Name Offset in XGS File + uint variableNameOffset = reader.ReadUInt32(); + + // RPC Variable Offset in XGS File + uint rpcOffset = reader.ReadUInt32(); + + // DSP Preset/Parameter Offsets in XGS File + uint dspPresetOffset = reader.ReadUInt32(); + uint dspParameterOffset = reader.ReadUInt32(); + + /* Unknown table #1 + reader.BaseStream.Seek(keyOneOffset, SeekOrigin.Begin); + for (int i = 0; i < numKeyOne; i += 1) + { + // Appears to consistently be 16 shorts? + System.Console.WriteLine(reader.ReadInt16()); + } + /* OhGodNo + * 1, -1, 4, -1, + * 3, -1, -1, 7, + * -1, 2, 5, -1, + * 6, 0, -1, -1 + * + * Naddachance + * 1, -1, 4, -1, + * 5, -1, -1, -1, + * -1, 2, -1, -1, + * 3, 0, -1, -1 + * + * TFA + * 1, -1, -1, -1, + * -1, -1, -1, -1, + * -1, 2, -1, -1, + * -1, -0, -1, -1 + */ + + /* Unknown table #2 + reader.BaseStream.Seek(keyTwoOffset, SeekOrigin.Begin); + for (int i = 0; i < numKeyTwo; i += 1) + { + // Appears to be between 16-20 shorts? + System.Console.WriteLine(reader.ReadInt16()); + } + /* OhGodNo + * 2, 7, 1, -1, + * -1, 10, 19, -1, + * 11, 3, -1, -1, + * 8, -1, 14, 5, + * 12, 0, 4, 6 + * + * Naddachance + * 2, 3, -1, -1, + * 9, -1, 7, -1, + * 10, 0, 1, 5, + * -1, -1, -1, -1 + * + * TFA + * 2, 3, -1, -1, + * -1, -1, -1, -1, + * -1, 0, 1, 5, + * -1, -1, -1, -1 + */ + + // Obtain the Audio Category Names + reader.BaseStream.Seek(categoryNameOffset, SeekOrigin.Begin); + string[] categoryNames = new string[numCategories]; + for (int i = 0; i < numCategories; i += 1) + { + List builtString = new List(); + while (reader.PeekChar() != 0) + { + builtString.Add(reader.ReadChar()); + } + reader.ReadChar(); // Null terminator + categoryNames[i] = new string(builtString.ToArray()); + } + + // Obtain the Audio Categories + reader.BaseStream.Seek(categoryOffset, SeekOrigin.Begin); + INTERNAL_categories = new List(); + for (int i = 0; i < numCategories; i += 1) + { + // Maximum instances + byte maxInstances = reader.ReadByte(); + + // Fade In/Out + ushort fadeInMS = reader.ReadUInt16(); + ushort fadeOutMS = reader.ReadUInt16(); + + // Instance Behavior Flags + byte instanceFlags = reader.ReadByte(); + int fadeType = instanceFlags & 0x07; + int maxBehavior = instanceFlags >> 3; + + // Unknown value + reader.ReadUInt16(); + + // Volume + float volume = XACTCalculator.CalculateVolume(reader.ReadByte()); + + // Visibility Flags, unused + reader.ReadByte(); + + // Add to the engine list + INTERNAL_categories.Add( + new AudioCategory( + categoryNames[i], + volume, + maxInstances, + maxBehavior, + fadeInMS, + fadeOutMS, + fadeType + ) + ); + } + + // Obtain the Variable Names + reader.BaseStream.Seek(variableNameOffset, SeekOrigin.Begin); + string[] variableNames = new string[numVariables]; + for (int i = 0; i < numVariables; i += 1) + { + List builtString = new List(); + while (reader.PeekChar() != 0) + { + builtString.Add(reader.ReadChar()); + } + reader.ReadChar(); // Null terminator + variableNames[i] = new string(builtString.ToArray()); + } + + // Obtain the Variables + reader.BaseStream.Seek(variableOffset, SeekOrigin.Begin); + INTERNAL_variables = new List(); + for (int i = 0; i < numVariables; i += 1) + { + // Variable Accessibility (See Variable constructor) + byte varFlags = reader.ReadByte(); + + // Variable Value, Boundaries + float initialValue = reader.ReadSingle(); + float minValue = reader.ReadSingle(); + float maxValue = reader.ReadSingle(); + + // Add to the engine list + INTERNAL_variables.Add( + new Variable( + variableNames[i], + (varFlags & 0x01) != 0, + (varFlags & 0x02) != 0, + (varFlags & 0x04) == 0, + (varFlags & 0x08) != 0, + initialValue, + minValue, + maxValue + ) + ); + } + + // Obtain the RPC Curves + reader.BaseStream.Seek(rpcOffset, SeekOrigin.Begin); + INTERNAL_RPCs = new Dictionary(); + for (int i = 0; i < numRPCs; i += 1) + { + // RPC "Code", used by the SoundBanks + long rpcCode = reader.BaseStream.Position; + + // RPC Variable + ushort rpcVariable = reader.ReadUInt16(); + + // Number of RPC Curve Points + byte numPoints = reader.ReadByte(); + + // RPC Parameter + ushort rpcParameter = reader.ReadUInt16(); + + // RPC Curve Points + RPCPoint[] rpcPoints = new RPCPoint[numPoints]; + for (byte j = 0; j < numPoints; j += 1) + { + float x = reader.ReadSingle(); + float y = reader.ReadSingle(); + byte type = reader.ReadByte(); + rpcPoints[j] = new RPCPoint( + x, y, + (RPCPointType) type + ); + } + + // Add to the engine list + INTERNAL_RPCs.Add( + rpcCode, + new RPC( + INTERNAL_variables[rpcVariable].Name, + rpcParameter, + rpcPoints + ) + ); + } + + // Obtain the DSP Parameters + reader.BaseStream.Seek(dspParameterOffset, SeekOrigin.Begin); + INTERNAL_dspParameters = new List(); + for (int i = 0; i < numDSPParameters; i += 1) + { + // Effect Parameter Type + byte type = reader.ReadByte(); + + // Effect value, boundaries + float value = reader.ReadSingle(); + float minVal = reader.ReadSingle(); + float maxVal = reader.ReadSingle(); + + // Unknown value + reader.ReadUInt16(); + + // Add to Parameter list + INTERNAL_dspParameters.Add( + new DSPParameter( + type, + value, + minVal, + maxVal + ) + ); + } + + // Obtain the DSP Presets + reader.BaseStream.Seek(dspPresetOffset, SeekOrigin.Begin); + INTERNAL_dspPresets = new Dictionary(); + int total = 0; + for (int i = 0; i < numDSPPresets; i += 1) + { + // DSP "Code", used by the SoundBanks + long dspCode = reader.BaseStream.Position; + + // Preset Accessibility + bool global = (reader.ReadByte() == 1); + + // Number of preset parameters + uint numParams = reader.ReadUInt32(); + + // Obtain DSP Parameters + DSPParameter[] parameters = new DSPParameter[numParams]; + for (uint j = 0; j < numParams; j += 1) + { + parameters[j] = INTERNAL_dspParameters[total]; + total += 1; + } + + // Add to DSP Preset list + INTERNAL_dspPresets.Add( + dspCode, + new DSPPreset( + global, + parameters + ) + ); + } + } + + // Create the WaveBank Dictionary + INTERNAL_waveBanks = new Dictionary(); + + // Finally. + IsDisposed = false; + } + + public AudioEngine( + string settingsFile, + TimeSpan lookAheadTime, + string rendererId + ) { + /* TODO: May require either resetting the ALDevice, + * or adding a second AL device/context for this engine. + * -flibit + */ + throw new NotSupportedException(); + } + + #endregion + + #region Destructor + + ~AudioEngine() + { + Dispose(); + } + + #endregion + + #region Public Dispose Methods + + public void Dispose() + { + if (!IsDisposed) + { + if (Disposing != null) + { + Disposing.Invoke(this, null); + } + foreach (AudioCategory curCategory in INTERNAL_categories) + { + curCategory.Stop(AudioStopOptions.Immediate); + } + INTERNAL_categories.Clear(); + foreach (KeyValuePair curDSP in INTERNAL_dspPresets) + { + curDSP.Value.Dispose(); + } + INTERNAL_dspPresets.Clear(); + INTERNAL_dspParameters.Clear(); + INTERNAL_variables.Clear(); + INTERNAL_RPCs.Clear(); + IsDisposed = true; + } + } + + #endregion + + #region Public Methods + + public AudioCategory GetCategory(string name) + { + if (String.IsNullOrEmpty(name)) + { + throw new ArgumentNullException("name"); + } + for (int i = 0; i < INTERNAL_categories.Count; i += 1) + { + if (INTERNAL_categories[i].Name.Equals(name)) + { + return INTERNAL_categories[i]; + } + } + throw new InvalidOperationException("Category not found!"); + } + + public float GetGlobalVariable(string name) + { + if (String.IsNullOrEmpty(name)) + { + throw new ArgumentNullException("name"); + } + for (int i = 0; i < INTERNAL_variables.Count; i += 1) + { + if (name.Equals(INTERNAL_variables[i].Name)) + { + if (!INTERNAL_variables[i].IsGlobal) + { + throw new InvalidOperationException("Variable not global!"); + } + return INTERNAL_variables[i].GetValue(); + } + } + throw new InvalidOperationException("Variable not found!"); + } + + public void SetGlobalVariable(string name, float value) + { + if (String.IsNullOrEmpty(name)) + { + throw new ArgumentNullException("name"); + } + for (int i = 0; i < INTERNAL_variables.Count; i += 1) + { + if (name.Equals(INTERNAL_variables[i].Name)) + { + if (!INTERNAL_variables[i].IsGlobal) + { + throw new InvalidOperationException("Variable not global!"); + } + INTERNAL_variables[i].SetValue(value); + return; // We made it! + } + } + throw new InvalidOperationException("Variable not found!"); + } + + public void Update() + { + // Update Global RPCs + foreach (RPC curRPC in INTERNAL_RPCs.Values) + if (curRPC.Parameter >= RPCParameter.NUM_PARAMETERS) + foreach (Variable curVar in INTERNAL_variables) + if (curVar.Name.Equals(curRPC.Variable) && curVar.IsGlobal) + foreach (DSPPreset curDSP in INTERNAL_dspPresets.Values) + { + /* FIXME: This affects all DSP presets! + * What if there's more than one? + * -flibit + */ + curDSP.SetParameter( + (int) curRPC.Parameter - (int) RPCParameter.NUM_PARAMETERS, + curRPC.CalculateRPC(GetGlobalVariable(curVar.Name)) + ); + } + + // Apply all DSP changes once they have been made + foreach (DSPPreset curDSP in INTERNAL_dspPresets.Values) + { + AudioDevice.ALDevice.CommitReverbChanges(curDSP.Effect); + } + + // Update Cues + foreach (AudioCategory curCategory in INTERNAL_categories) + { + curCategory.INTERNAL_update(); + } + } + + #endregion + + #region Internal Methods + + internal void INTERNAL_addWaveBank(string name, WaveBank waveBank) + { + INTERNAL_waveBanks.Add(name, waveBank); + } + + internal void INTERNAL_removeWaveBank(string name) + { + INTERNAL_waveBanks.Remove(name); + } + + internal SoundEffect INTERNAL_getWaveBankTrack(string name, ushort track) + { + return INTERNAL_waveBanks[name].INTERNAL_getTrack(track); + } + + internal string INTERNAL_getVariableName(ushort index) + { + return INTERNAL_variables[index].Name; + } + + internal RPC INTERNAL_getRPC(uint code) + { + return INTERNAL_RPCs[code]; + } + + internal IALReverb INTERNAL_getDSP(uint code) + { + return INTERNAL_dspPresets[code].Effect; + } + + internal AudioCategory INTERNAL_initCue(Cue newCue, ushort category) + { + List cueVariables = new List(); + foreach (Variable curVar in INTERNAL_variables) + { + if (!curVar.IsGlobal) + { + cueVariables.Add(curVar.Clone()); + } + } + newCue.INTERNAL_genVariables(cueVariables); + return INTERNAL_categories[category]; + } + + internal bool INTERNAL_isGlobalVariable(string name) + { + // FIXME: Any way to speed this up? -flibit + foreach (Variable curVar in INTERNAL_variables) + { + if (name.Equals(curVar.Name)) + { + return curVar.IsGlobal; + } + } + + // Variable doesn't even exist here...! + return false; + } + + #endregion + } +} diff --git a/src/Audio/AudioListener.cs b/src/Audio/AudioListener.cs new file mode 100644 index 0000000..f590d4f --- /dev/null +++ b/src/Audio/AudioListener.cs @@ -0,0 +1,56 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + // http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.audiolistener.aspx + public class AudioListener + { + #region Public Properties + + public Vector3 Forward + { + get; + set; + } + + public Vector3 Position + { + get; + set; + } + + + public Vector3 Up + { + get; + set; + } + + public Vector3 Velocity + { + get; + set; + } + + #endregion + + #region Public Constructor + + public AudioListener() + { + Forward = Vector3.Forward; + Position = Vector3.Zero; + Up = Vector3.Up; + Velocity = Vector3.Zero; + } + + #endregion + } +} diff --git a/src/Audio/AudioStopOptions.cs b/src/Audio/AudioStopOptions.cs new file mode 100644 index 0000000..9284429 --- /dev/null +++ b/src/Audio/AudioStopOptions.cs @@ -0,0 +1,18 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + // http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.audiostopoptions.aspx + public enum AudioStopOptions + { + AsAuthored, + Immediate + } +} diff --git a/src/Audio/Cue.cs b/src/Audio/Cue.cs new file mode 100644 index 0000000..b07fdae --- /dev/null +++ b/src/Audio/Cue.cs @@ -0,0 +1,898 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +using System.Diagnostics; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + // http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.cue.aspx + public sealed class Cue : IDisposable + { + #region Public Properties + + public bool IsCreated + { + get; + private set; + } + + public bool IsDisposed + { + get; + private set; + } + + public bool IsPaused + { + get + { + return ( !INTERNAL_timer.IsRunning && + INTERNAL_timer.ElapsedTicks > 0 ); + } + } + + public bool IsPlaying + { + get + { + return ( INTERNAL_timer.IsRunning || + INTERNAL_timer.ElapsedTicks > 0 ); + } + } + + public bool IsPrepared + { + get; + private set; + } + + public bool IsPreparing + { + get; + private set; + } + + public bool IsStopped + { + get + { + return !IsPlaying; + } + } + + public bool IsStopping + { + get + { + return INTERNAL_fadeMode == FadeMode.FadeOut; + } + } + + public string Name + { + get; + private set; + } + + #endregion + + #region Private Variables + + private AudioEngine INTERNAL_baseEngine; + + // Cue information parsed from the SoundBank + private CueData INTERNAL_data; + + // Current sound and its events + private XACTSound INTERNAL_activeSound; + private List INTERNAL_eventList; + private List INTERNAL_eventPlayed; + private Dictionary INTERNAL_eventLoops; + private Dictionary INTERNAL_waveEventSounds; + + // Used for event timestamps + private Stopwatch INTERNAL_timer; + + // Sound list + private List INTERNAL_instancePool; + private List INTERNAL_instanceVolumes; + private List INTERNAL_instancePitches; + + // RPC data list + private List INTERNAL_rpcTrackVolumes; + private List INTERNAL_rpcTrackPitches; + + // Events can control volume/pitch as well! + private float eventVolume; + private float eventPitch; + + // User-controlled sounds require a bit more trickery. + private bool INTERNAL_userControlledPlaying; + private float INTERNAL_controlledValue; + + // 3D audio variables + private bool INTERNAL_isPositional; + private AudioListener INTERNAL_listener; + private AudioEmitter INTERNAL_emitter; + + // XACT instance variables + private List INTERNAL_variables; + + // Category managing this Cue, and whether or not it's user-managed + private AudioCategory INTERNAL_category; + private bool INTERNAL_isManaged; + + // Fading + private enum FadeMode + { + None, + FadeOut, + FadeIn + } + private long INTERNAL_fadeStart; + private long INTERNAL_fadeEnd; + private FadeMode INTERNAL_fadeMode = FadeMode.None; + + #endregion + + #region Private Static Random Number Generator + + private static Random random = new Random(); + + #endregion + + #region Disposing Event + + public event EventHandler Disposing; + + #endregion + + #region Internal Constructor + + internal Cue( + AudioEngine audioEngine, + List waveBankNames, + string name, + CueData data, + bool managed + ) { + INTERNAL_baseEngine = audioEngine; + + Name = name; + + INTERNAL_data = data; + foreach (XACTSound curSound in data.Sounds) + { + if (!curSound.HasLoadedTracks) + { + curSound.LoadTracks( + INTERNAL_baseEngine, + waveBankNames + ); + } + } + + INTERNAL_isManaged = managed; + + INTERNAL_category = INTERNAL_baseEngine.INTERNAL_initCue( + this, + data.Category + ); + + eventVolume = 1.0f; + eventPitch = 0.0f; + + INTERNAL_userControlledPlaying = false; + INTERNAL_isPositional = false; + + INTERNAL_eventList = new List(); + INTERNAL_eventPlayed = new List(); + INTERNAL_eventLoops = new Dictionary(); + INTERNAL_waveEventSounds = new Dictionary(); + + INTERNAL_timer = new Stopwatch(); + + INTERNAL_instancePool = new List(); + INTERNAL_instanceVolumes = new List(); + INTERNAL_instancePitches = new List(); + + INTERNAL_rpcTrackVolumes = new List(); + INTERNAL_rpcTrackPitches = new List(); + } + + #endregion + + #region Destructor + + ~Cue() + { + Dispose(); + } + + #endregion + + #region Public Dispose Method + + public void Dispose() + { + if (!IsDisposed) + { + if (Disposing != null) + { + Disposing.Invoke(this, null); + } + if (INTERNAL_instancePool != null) + { + foreach (SoundEffectInstance sfi in INTERNAL_instancePool) + { + sfi.Dispose(); + } + INTERNAL_instancePool.Clear(); + INTERNAL_instanceVolumes.Clear(); + INTERNAL_instancePitches.Clear(); + INTERNAL_rpcTrackVolumes.Clear(); + INTERNAL_rpcTrackPitches.Clear(); + INTERNAL_timer.Stop(); + } + INTERNAL_category.INTERNAL_removeActiveCue(this); + IsDisposed = true; + } + } + + #endregion + + #region Public Methods + + public void Apply3D(AudioListener listener, AudioEmitter emitter) + { + if (IsPlaying && !INTERNAL_isPositional) + { + throw new InvalidOperationException("Apply3D call after Play!"); + } + if (listener == null) + { + throw new ArgumentNullException("listener"); + } + if (emitter == null) + { + throw new ArgumentNullException("emitter"); + } + INTERNAL_listener = listener; + INTERNAL_emitter = emitter; + SetVariable( + "Distance", + Vector3.Distance( + INTERNAL_emitter.Position, + INTERNAL_listener.Position + ) + ); + // TODO: DopplerPitchScaler, OrientationAngle + INTERNAL_isPositional = true; + } + + public float GetVariable(string name) + { + if (String.IsNullOrEmpty(name)) + { + throw new ArgumentNullException("name"); + } + foreach (Variable curVar in INTERNAL_variables) + { + if (name.Equals(curVar.Name)) + { + return curVar.GetValue(); + } + } + throw new Exception("Instance variable not found!"); + } + + public void Pause() + { + if (IsPlaying) + { + INTERNAL_timer.Stop(); + foreach (SoundEffectInstance sfi in INTERNAL_instancePool) + { + sfi.Pause(); + } + } + } + + public void Play() + { + if (IsPlaying) + { + throw new InvalidOperationException("Cue already playing!"); + } + + INTERNAL_category.INTERNAL_initCue(this); + + if (GetVariable("NumCueInstances") >= INTERNAL_data.InstanceLimit) + { + if (INTERNAL_data.MaxCueBehavior == MaxInstanceBehavior.Fail) + { + return; // Just ignore us... + } + else if (INTERNAL_data.MaxCueBehavior == MaxInstanceBehavior.Queue) + { + throw new Exception("Cue Queueing not handled!"); + } + else if (INTERNAL_data.MaxCueBehavior == MaxInstanceBehavior.ReplaceOldest) + { + INTERNAL_category.INTERNAL_removeOldestCue(Name); + } + else if (INTERNAL_data.MaxCueBehavior == MaxInstanceBehavior.ReplaceQuietest) + { + INTERNAL_category.INTERNAL_removeQuietestCue(Name); + } + else if (INTERNAL_data.MaxCueBehavior == MaxInstanceBehavior.ReplaceLowestPriority) + { + // FIXME: Priority? + INTERNAL_category.INTERNAL_removeOldestCue(Name); + } + } + + if (!INTERNAL_category.INTERNAL_addCue(this)) + { + return; + } + + INTERNAL_timer.Start(); + if (INTERNAL_data.FadeInMS > 0) + { + INTERNAL_startFadeIn(INTERNAL_data.FadeInMS); + } + + if (!INTERNAL_calculateNextSound()) + { + return; + } + + INTERNAL_activeSound.GatherEvents(INTERNAL_eventList); + foreach (XACTEvent evt in INTERNAL_eventList) + { + INTERNAL_eventPlayed.Add(false); + INTERNAL_eventLoops.Add(evt, 0); + } + } + + public void Resume() + { + if (IsPaused) + { + INTERNAL_timer.Start(); + foreach (SoundEffectInstance sfi in INTERNAL_instancePool) + { + sfi.Resume(); + } + } + } + + public void SetVariable(string name, float value) + { + if (String.IsNullOrEmpty(name)) + { + throw new ArgumentNullException("name"); + } + foreach (Variable curVar in INTERNAL_variables) + { + if (name.Equals(curVar.Name)) + { + curVar.SetValue(value); + return; + } + } + throw new Exception("Instance variable not found!"); + } + + public void Stop(AudioStopOptions options) + { + if (IsPlaying) + { + if ( options == AudioStopOptions.AsAuthored && + INTERNAL_data.FadeOutMS > 0 ) + { + INTERNAL_startFadeOut(INTERNAL_data.FadeOutMS); + return; + } + INTERNAL_timer.Stop(); + INTERNAL_timer.Reset(); + foreach (SoundEffectInstance sfi in INTERNAL_instancePool) + { + sfi.Stop(); + sfi.Dispose(); + } + INTERNAL_instancePool.Clear(); + INTERNAL_instanceVolumes.Clear(); + INTERNAL_instancePitches.Clear(); + INTERNAL_rpcTrackVolumes.Clear(); + INTERNAL_rpcTrackPitches.Clear(); + INTERNAL_userControlledPlaying = false; + INTERNAL_category.INTERNAL_removeActiveCue(this); + + // If this is a managed Cue, we're done here. + if (INTERNAL_isManaged) + { + Dispose(); + } + } + } + + #endregion + + #region Internal Methods + + internal bool INTERNAL_update() + { + // If we're not running, save some instructions... + if (!INTERNAL_timer.IsRunning) + { + return true; + } + + // Play events when the timestamp has been hit. + for (int i = 0; i < INTERNAL_eventList.Count; i += 1) + { + if ( !INTERNAL_eventPlayed[i] && + INTERNAL_timer.ElapsedMilliseconds > INTERNAL_eventList[i].Timestamp ) + { + uint type = INTERNAL_eventList[i].Type; + if (type == 1) + { + PlayWave((PlayWaveEvent) INTERNAL_eventList[i]); + } + else if (type == 2) + { + eventVolume = ((SetVolumeEvent) INTERNAL_eventList[i]).GetVolume(); + } + else if (type == 3) + { + eventPitch = ((SetPitchEvent) INTERNAL_eventList[i]).GetPitch(); + } + else + { + throw new Exception("Unhandled XACTEvent type!"); + } + INTERNAL_eventPlayed[i] = true; + } + } + + // Clear out sound effect instances as they finish + for (int i = 0; i < INTERNAL_instancePool.Count; i += 1) + { + if (INTERNAL_instancePool[i].State == SoundState.Stopped) + { + // Get the event that spawned this instance... + PlayWaveEvent evt = (PlayWaveEvent) INTERNAL_waveEventSounds[INTERNAL_instancePool[i]]; + + // Then delete all the guff + INTERNAL_waveEventSounds.Remove(INTERNAL_instancePool[i]); + INTERNAL_instancePool[i].Dispose(); + INTERNAL_instancePool.RemoveAt(i); + INTERNAL_instanceVolumes.RemoveAt(i); + INTERNAL_instancePitches.RemoveAt(i); + INTERNAL_rpcTrackVolumes.RemoveAt(i); + INTERNAL_rpcTrackPitches.RemoveAt(i); + + // Increment the loop counter, try to get another loop + INTERNAL_eventLoops[evt] += 1; + PlayWave(evt); + + // Removed a wave, have to step back... + i -= 1; + } + } + + // Fade in/out + float fadePerc = 1.0f; + if (INTERNAL_fadeMode != FadeMode.None) + { + if (INTERNAL_fadeMode == FadeMode.FadeOut) + { + if (INTERNAL_category.crossfadeType == CrossfadeType.Linear) + { + fadePerc = (INTERNAL_fadeEnd - (INTERNAL_timer.ElapsedMilliseconds - INTERNAL_fadeStart)) / (float) INTERNAL_fadeEnd; + } + else + { + throw new NotImplementedException("Unhandled CrossfadeType!"); + } + if (fadePerc <= 0.0f) + { + Stop(AudioStopOptions.Immediate); + INTERNAL_fadeMode = FadeMode.None; + return false; + } + } + else + { + if (INTERNAL_category.crossfadeType == CrossfadeType.Linear) + { + fadePerc = INTERNAL_timer.ElapsedMilliseconds / (float) INTERNAL_fadeEnd; + } + else + { + throw new NotImplementedException("Unhandled CrossfadeType!"); + } + if (fadePerc > 1.0f) + { + fadePerc = 1.0f; + INTERNAL_fadeMode = FadeMode.None; + } + } + } + + // User control updates + if (INTERNAL_data.IsUserControlled) + { + string varName = INTERNAL_data.UserControlVariable; + if ( INTERNAL_userControlledPlaying && + (INTERNAL_baseEngine.INTERNAL_isGlobalVariable(varName) ? + !MathHelper.WithinEpsilon(INTERNAL_controlledValue, INTERNAL_baseEngine.GetGlobalVariable(varName)) : + !MathHelper.WithinEpsilon(INTERNAL_controlledValue, GetVariable(INTERNAL_data.UserControlVariable))) ) + { + // TODO: Crossfading + foreach (SoundEffectInstance sfi in INTERNAL_instancePool) + { + sfi.Stop(); + sfi.Dispose(); + } + INTERNAL_instancePool.Clear(); + INTERNAL_instanceVolumes.Clear(); + INTERNAL_instancePitches.Clear(); + INTERNAL_rpcTrackVolumes.Clear(); + INTERNAL_rpcTrackPitches.Clear(); + if (!INTERNAL_calculateNextSound()) + { + // Nothing to play, bail. + return true; + } + INTERNAL_activeSound.GatherEvents(INTERNAL_eventList); + foreach (XACTEvent evt in INTERNAL_eventList) + { + INTERNAL_eventPlayed.Add(false); + INTERNAL_eventLoops.Add(evt, 0); + } + INTERNAL_timer.Stop(); + INTERNAL_timer.Reset(); + INTERNAL_timer.Start(); + } + + if (INTERNAL_activeSound == null) + { + return INTERNAL_userControlledPlaying; + } + } + + // If everything has been played and finished, we're done here. + if (INTERNAL_instancePool.Count == 0) + { + bool allPlayed = true; + foreach (bool played in INTERNAL_eventPlayed) + { + if (!played) + { + allPlayed = false; + break; + } + } + if (allPlayed) + { + // If this is managed, we're done completely. + if (INTERNAL_isManaged) + { + Dispose(); + } + else + { + INTERNAL_timer.Stop(); + INTERNAL_timer.Reset(); + INTERNAL_category.INTERNAL_removeActiveCue(this); + } + return INTERNAL_userControlledPlaying; + } + } + + // RPC updates + float rpcVolume = 1.0f; + float rpcPitch = 0.0f; + float hfGain = 1.0f; + float lfGain = 1.0f; + for (int i = 0; i < INTERNAL_activeSound.RPCCodes.Count; i += 1) + { + if (i > INTERNAL_instancePool.Count) + { + break; + } + if (i > 0) + { + INTERNAL_rpcTrackVolumes[i - 1] = 1.0f; + INTERNAL_rpcTrackPitches[i - 1] = 0.0f; + } + foreach (uint curCode in INTERNAL_activeSound.RPCCodes[i]) + { + RPC curRPC = INTERNAL_baseEngine.INTERNAL_getRPC(curCode); + float result; + if (!INTERNAL_baseEngine.INTERNAL_isGlobalVariable(curRPC.Variable)) + { + result = curRPC.CalculateRPC(GetVariable(curRPC.Variable)); + } + else + { + // It's a global variable we're looking for! + result = curRPC.CalculateRPC( + INTERNAL_baseEngine.GetGlobalVariable( + curRPC.Variable + ) + ); + } + if (curRPC.Parameter == RPCParameter.Volume) + { + float vol = XACTCalculator.CalculateAmplitudeRatio(result / 100.0); + if (i == 0) + { + rpcVolume *= vol; + } + else + { + INTERNAL_rpcTrackVolumes[i - 1] *= vol; + } + } + else if (curRPC.Parameter == RPCParameter.Pitch) + { + float pitch = result / 1000.0f; + if (i == 0) + { + rpcPitch += pitch; + } + else + { + INTERNAL_rpcTrackPitches[i - 1] += pitch; + } + } + else if (curRPC.Parameter == RPCParameter.FilterFrequency) + { + // FIXME: Just listening to the last RPC! + float hf = result / 20000.0f; + float lf = 1.0f - hf; + if (i == 0) + { + hfGain = hf; + lfGain = lf; + } + else + { + throw new NotImplementedException("Per-track filter RPCs!"); + } + } + else + { + throw new Exception("RPC Parameter Type: " + curRPC.Parameter.ToString()); + } + } + } + + // Sound effect instance updates + for (int i = 0; i < INTERNAL_instancePool.Count; i += 1) + { + /* The final volume should be the combination of the + * authored volume, category volume, RPC/Event volumes, and fade. + */ + INTERNAL_instancePool[i].Volume = ( + INTERNAL_instanceVolumes[i] * + INTERNAL_category.INTERNAL_volume.Value * + rpcVolume * + INTERNAL_rpcTrackVolumes[i] * + eventVolume * + fadePerc + ); + + /* The final pitch should be the combination of the + * authored pitch and RPC/Event pitch results. + */ + INTERNAL_instancePool[i].Pitch = ( + INTERNAL_instancePitches[i] + + rpcPitch + + eventPitch + + INTERNAL_rpcTrackPitches[i] + ); + + /* The final filter is determined by the instance's filter type, + * in addition to our calculation of the HF/LF gain values. + */ + byte fType = INTERNAL_instancePool[i].FilterType; + if (fType == 0xFF) + { + // No-op, no filter! + } + else if (fType == 0) + { + INTERNAL_instancePool[i].INTERNAL_applyLowPassFilter(hfGain); + } + else if (fType == 1) + { + INTERNAL_instancePool[i].INTERNAL_applyHighPassFilter(lfGain); + } + else if (fType == 2) + { + INTERNAL_instancePool[i].INTERNAL_applyBandPassFilter(hfGain, lfGain); + } + else + { + throw new InvalidOperationException("Unhandled filter type!"); + } + + // Update 3D position, if applicable + if (INTERNAL_isPositional) + { + INTERNAL_instancePool[i].Apply3D( + INTERNAL_listener, + INTERNAL_emitter + ); + } + } + + return true; + } + + internal void INTERNAL_genVariables(List cueVariables) + { + INTERNAL_variables = cueVariables; + } + + internal float INTERNAL_calculateVolume() + { + float retval = 1.0f; + for (int i = 0; i < INTERNAL_activeSound.RPCCodes.Count; i += 1) + foreach (uint curCode in INTERNAL_activeSound.RPCCodes[i]) + { + RPC curRPC = INTERNAL_baseEngine.INTERNAL_getRPC(curCode); + if (curRPC.Parameter != RPCParameter.Volume) + { + continue; + } + float result; + if (!INTERNAL_baseEngine.INTERNAL_isGlobalVariable(curRPC.Variable)) + { + result = curRPC.CalculateRPC(GetVariable(curRPC.Variable)); + } + else + { + // It's a global variable we're looking for! + result = curRPC.CalculateRPC( + INTERNAL_baseEngine.GetGlobalVariable( + curRPC.Variable + ) + ); + } + retval *= XACTCalculator.CalculateAmplitudeRatio(result / 100.0); + } + return retval; + } + + internal void INTERNAL_startFadeIn(ushort ms) + { + // start is not used, since it's always 0 anyway -flibit + INTERNAL_fadeEnd = ms; + INTERNAL_fadeMode = FadeMode.FadeIn; + } + + internal void INTERNAL_startFadeOut(ushort ms) + { + INTERNAL_fadeStart = INTERNAL_timer.ElapsedMilliseconds; + INTERNAL_fadeEnd = ms; + INTERNAL_fadeMode = FadeMode.FadeOut; + } + + #endregion + + #region Private Methods + + private bool INTERNAL_calculateNextSound() + { + INTERNAL_activeSound = null; + INTERNAL_eventList.Clear(); + INTERNAL_eventPlayed.Clear(); + INTERNAL_eventLoops.Clear(); + INTERNAL_waveEventSounds.Clear(); + + // Pick a sound based on a Cue instance variable + if (INTERNAL_data.IsUserControlled) + { + INTERNAL_userControlledPlaying = true; + if (INTERNAL_baseEngine.INTERNAL_isGlobalVariable(INTERNAL_data.UserControlVariable)) + { + INTERNAL_controlledValue = INTERNAL_baseEngine.GetGlobalVariable( + INTERNAL_data.UserControlVariable + ); + } + else + { + INTERNAL_controlledValue = GetVariable( + INTERNAL_data.UserControlVariable + ); + } + for (int i = 0; i < INTERNAL_data.Probabilities.Length / 2; i += 1) + { + if ( INTERNAL_controlledValue <= INTERNAL_data.Probabilities[i, 0] && + INTERNAL_controlledValue >= INTERNAL_data.Probabilities[i, 1] ) + { + INTERNAL_activeSound = INTERNAL_data.Sounds[i]; + return true; + } + } + + /* This should only happen when the + * UserControlVariable is none of the sound + * probabilities, in which case we are just + * silent. But, we are still claiming to be + * "playing" in the meantime. + * -flibit + */ + return false; + } + + // Randomly pick a sound + double max = 0.0; + for (int i = 0; i < INTERNAL_data.Probabilities.GetLength(0); i += 1) + { + max += INTERNAL_data.Probabilities[i, 0] - INTERNAL_data.Probabilities[i, 1]; + } + double next = random.NextDouble() * max; + + for (int i = INTERNAL_data.Probabilities.GetLength(0) - 1; i >= 0; i -= 1) + { + if (next > max - (INTERNAL_data.Probabilities[i, 0] - INTERNAL_data.Probabilities[i, 1])) + { + INTERNAL_activeSound = INTERNAL_data.Sounds[i]; + break; + } + max -= INTERNAL_data.Probabilities[i, 0] - INTERNAL_data.Probabilities[i, 1]; + } + + return true; + } + + private void PlayWave(PlayWaveEvent evt) + { + SoundEffectInstance sfi = evt.GenerateInstance( + INTERNAL_activeSound.Volume, + INTERNAL_activeSound.Pitch, + INTERNAL_eventLoops[evt] + ); + if (sfi != null) + { + if (INTERNAL_isPositional) + { + sfi.Apply3D(INTERNAL_listener, INTERNAL_emitter); + } + foreach (uint curDSP in INTERNAL_activeSound.DSPCodes) + { + // FIXME: This only applies the last DSP! + sfi.INTERNAL_applyReverb( + INTERNAL_baseEngine.INTERNAL_getDSP(curDSP) + ); + } + INTERNAL_instancePool.Add(sfi); + INTERNAL_instanceVolumes.Add(sfi.Volume); + INTERNAL_instancePitches.Add(sfi.Pitch); + INTERNAL_waveEventSounds.Add(sfi, evt); + INTERNAL_rpcTrackVolumes.Add(1.0f); + INTERNAL_rpcTrackPitches.Add(0.0f); + sfi.Play(); + } + } + + #endregion + } +} diff --git a/src/Audio/CueData.cs b/src/Audio/CueData.cs new file mode 100644 index 0000000..1e01da4 --- /dev/null +++ b/src/Audio/CueData.cs @@ -0,0 +1,985 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +using System.IO; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + internal class CueData + { + public XACTSound[] Sounds + { + get; + private set; + } + + public ushort Category + { + get; + private set; + } + + public float[,] Probabilities + { + get; + private set; + } + + public bool IsUserControlled + { + get; + private set; + } + + public string UserControlVariable + { + get; + private set; + } + + public byte InstanceLimit + { + get; + private set; + } + + public MaxInstanceBehavior MaxCueBehavior + { + get; + private set; + } + + public ushort FadeInMS + { + get; + private set; + } + + public ushort FadeOutMS + { + get; + private set; + } + + public CueData(XACTSound sound) + { + Sounds = new XACTSound[1]; + Probabilities = new float[1, 2]; + + Sounds[0] = sound; + Category = sound.Category; + Probabilities[0, 0] = 1.0f; + Probabilities[0, 1] = 0.0f; + IsUserControlled = false; + + // Assume we can have max instances, for now. + InstanceLimit = 255; + MaxCueBehavior = MaxInstanceBehavior.ReplaceOldest; + FadeInMS = 0; + FadeOutMS = 0; + } + + public CueData( + XACTSound[] sounds, + float[,] probabilities, + string controlVariable + ) { + Sounds = sounds; + Category = Sounds[0].Category; // FIXME: Assumption! + Probabilities = probabilities; + IsUserControlled = !String.IsNullOrEmpty(controlVariable); + UserControlVariable = controlVariable; + + // Assume we can have max instances, for now. + InstanceLimit = 255; + MaxCueBehavior = MaxInstanceBehavior.ReplaceOldest; + FadeInMS = 0; + FadeOutMS = 0; + } + + public void SetLimit( + byte instanceLimit, + byte behavior, + ushort fadeIn, + ushort fadeOut + ) { + InstanceLimit = instanceLimit; + MaxCueBehavior = (MaxInstanceBehavior) (behavior >> 3); + FadeInMS = fadeIn; + FadeOutMS = fadeOut; + } + } + + internal class XACTSound + { + private XACTClip[] INTERNAL_clips; + + public double Volume + { + get; + private set; + } + + public float Pitch + { + get; + private set; + } + + public ushort Category + { + get; + private set; + } + + public bool HasLoadedTracks + { + get; + private set; + } + + public List RPCCodes + { + get; + private set; + } + + public uint[] DSPCodes + { + get; + private set; + } + + public XACTSound(ushort track, byte waveBank) + { + INTERNAL_clips = new XACTClip[1]; + INTERNAL_clips[0] = new XACTClip(track, waveBank); + Category = 0; + Volume = 0.0; + HasLoadedTracks = false; + } + + public XACTSound(BinaryReader reader) + { + // Sound Effect Flags + byte soundFlags = reader.ReadByte(); + bool complex = (soundFlags & 0x01) != 0; + + // AudioCategory Index + Category = reader.ReadUInt16(); + + // Sound Volume + Volume = XACTCalculator.ParseDecibel(reader.ReadByte()); + + // Sound Pitch + Pitch = (reader.ReadInt16() / 1000.0f); + + // Unknown value + reader.ReadByte(); + + // Length of Sound Entry, unused + reader.ReadUInt16(); + + // Number of Sound Clips + if (complex) + { + INTERNAL_clips = new XACTClip[reader.ReadByte()]; + } + else + { + // Simple Sounds always have 1 PlayWaveEvent. + INTERNAL_clips = new XACTClip[1]; + ushort track = reader.ReadUInt16(); + byte waveBank = reader.ReadByte(); + INTERNAL_clips[0] = new XACTClip(track, waveBank); + } + + // Parse RPC Properties + RPCCodes = new List(); + if ((soundFlags & 0x0E) != 0) + { + // RPC data length + ushort rpcDataLength = reader.ReadUInt16(); + ushort totalDataRead = 2; + + while (totalDataRead < rpcDataLength) + { + // Number of RPC Presets (for this track) + uint[] codeList = new uint[reader.ReadByte()]; + + // Obtain RPC curve codes (in this block) + for (int i = 0; i < codeList.Length; i += 1) + { + codeList[i] = reader.ReadUInt32(); + } + + // Add this track's code list to the master list + RPCCodes.Add(codeList); + + totalDataRead += (ushort) (1 + (4 * codeList.Length)); + } + } + + // Parse DSP Presets + DSPCodes = new uint[0]; // Eww... -flibit + if ((soundFlags & 0x10) != 0) + { + // DSP Presets Length, unused + reader.ReadUInt16(); + + // Number of DSP Presets + DSPCodes = new uint[reader.ReadByte()]; + + // Obtain DSP Preset codes + for (byte j = 0; j < DSPCodes.Length; j += 1) + { + DSPCodes[j] = reader.ReadUInt32(); + } + } + + // Parse Sound Events + if (complex) + { + for (int i = 0; i < INTERNAL_clips.Length; i += 1) + { + // XACT Clip volume + double clipVolume = XACTCalculator.ParseDecibel(reader.ReadByte()); + + // XACT Clip Offset in Bank + uint offset = reader.ReadUInt32(); + + // XACT Clip filter + byte filterFlags = reader.ReadByte(); + byte filterType; + if ((filterFlags & 0x01) == 0x01) + { + filterType = (byte) ((filterFlags >> 1) & 0x02); + } + else + { + filterType = 0xFF; + } + reader.ReadByte(); // QFactor? + reader.ReadUInt16(); // Frequency + + // Store this for when we're done reading the clip. + long curPos = reader.BaseStream.Position; + + // Go to the Clip in the Bank. + reader.BaseStream.Seek(offset, SeekOrigin.Begin); + + // Parse the Clip. + INTERNAL_clips[i] = new XACTClip(reader, clipVolume, filterType); + + // Back to where we were... + reader.BaseStream.Seek(curPos, SeekOrigin.Begin); + } + } + + HasLoadedTracks = false; + } + + public void LoadTracks(AudioEngine audioEngine, List waveBankNames) + { + foreach (XACTClip curClip in INTERNAL_clips) + { + curClip.LoadTracks(audioEngine, waveBankNames); + } + HasLoadedTracks = true; + } + + public void GatherEvents(List eventList) + { + foreach (XACTClip curClip in INTERNAL_clips) + { + eventList.AddRange(curClip.Events); + } + } + } + + internal class XACTClip + { + public XACTEvent[] Events + { + get; + private set; + } + + public XACTClip(ushort track, byte waveBank) + { + Events = new XACTEvent[1]; + Events[0] = new PlayWaveEvent( + 0, + new ushort[] { track }, + new byte[] { waveBank }, + 0, + 0, + 1.0, + 1.0, + 0xFF, + 0, + 0, + false, + new byte[] { 0xFF } + ); + } + + public XACTClip(BinaryReader reader, double clipVolume, byte filterType) + { + // Number of XACT Events + Events = new XACTEvent[reader.ReadByte()]; + + for (int i = 0; i < Events.Length; i += 1) + { + // Full Event information + uint eventInfo = reader.ReadUInt32(); + + // XACT Event Type, Timestamp + uint eventType = eventInfo & 0x0000001F; + uint eventTimestamp = (eventInfo >> 5) & 0x0000FFFF; + // uint eventUnknown = eventInfo >> 21; + + // Random offset, unused + reader.ReadUInt16(); + + // Load the Event + if (eventType == 0) + { + // TODO: Codename OhGodNo + // Stop Event + } + else if (eventType == 1) + { + // Unknown value + reader.ReadByte(); + + /* Event Flags + * 0x01 = Break Loop + * 0x02 = Use Speaker Position + * 0x04 = Use Center Speaker + * 0x08 = New Speaker Position On Loop + */ + reader.ReadByte(); + + // WaveBank Track Index + ushort track = reader.ReadUInt16(); + + // WaveBank Index + byte waveBank = reader.ReadByte(); + + // Number of times to loop wave (255 is infinite) + byte loopCount = reader.ReadByte(); + + // Speaker position angle/arc, unused + reader.ReadUInt16(); + reader.ReadUInt16(); + + // Finally. + Events[i] = new PlayWaveEvent( + eventTimestamp, + new ushort[] { track }, + new byte[] { waveBank }, + 0, + 0, + clipVolume, + clipVolume, + filterType, + loopCount, + 0, + false, + new byte[] { 0xFF } + ); + } + else if (eventType == 3) + { + // Unknown value + reader.ReadByte(); + + /* Event Flags + * 0x01 = Break Loop + * 0x02 = Use Speaker Position + * 0x04 = Use Center Speaker + * 0x08 = New Speaker Position On Loop + */ + reader.ReadByte(); + + // Number of times to loop wave (255 is infinite) + byte loopCount = reader.ReadByte(); + + // Speaker position angle/arc, unused + reader.ReadUInt16(); + reader.ReadUInt16(); + + // Number of WaveBank tracks + ushort numTracks = reader.ReadUInt16(); + + /* Variation Playlist Type. + * First 4 bytes indicates Variation Type. + * Next 4 bytes appear to indicate New Variation On Loop. + * The rest is currently unknown. + * -flibit + */ + ushort variationValues = reader.ReadUInt16(); + ushort variationType = (ushort)(variationValues & 0x000F); + bool variationOnLoop = (variationValues & 0x00F0) > 0; + + // Unknown values + reader.ReadBytes(4); + + // Obtain WaveBank track information + ushort[] tracks = new ushort[numTracks]; + byte[] waveBanks = new byte[numTracks]; + byte[] weights = new byte[numTracks]; + for (ushort j = 0; j < numTracks; j += 1) + { + tracks[j] = reader.ReadUInt16(); + waveBanks[j] = reader.ReadByte(); + byte minWeight = reader.ReadByte(); + byte maxWeight = reader.ReadByte(); + weights[j] = (byte) (maxWeight - minWeight); + } + + // Finally. + Events[i] = new PlayWaveEvent( + eventTimestamp, + tracks, + waveBanks, + 0, + 0, + clipVolume, + clipVolume, + filterType, + loopCount, + variationType, + variationOnLoop, + weights + ); + } + else if (eventType == 4) + { + // Unknown value + reader.ReadByte(); + + /* Event Flags + * 0x01 = Break Loop + * 0x02 = Use Speaker Position + * 0x04 = Use Center Speaker + * 0x08 = New Speaker Position On Loop + */ + reader.ReadByte(); + + // WaveBank track + ushort track = reader.ReadUInt16(); + + // WaveBank index, unconfirmed + byte waveBank = reader.ReadByte(); + + // Loop Count, unconfirmed + byte loopCount = reader.ReadByte(); + + // Speaker position angle/arc, unused + reader.ReadUInt16(); + reader.ReadUInt16(); + + // Pitch Variation + short minPitch = reader.ReadInt16(); + short maxPitch = reader.ReadInt16(); + + // Volume Variation + double minVolume = XACTCalculator.ParseDecibel(reader.ReadByte()); + double maxVolume = XACTCalculator.ParseDecibel(reader.ReadByte()); + + // Frequency Variation, unusued + reader.ReadSingle(); + reader.ReadSingle(); + + // Q Factor Variation, unused + reader.ReadSingle(); + reader.ReadSingle(); + + // Unknown value + reader.ReadUInt16(); + + // Finally. + Events[i] = new PlayWaveEvent( + eventTimestamp, + new ushort[] { track }, + new byte[] { waveBank }, + minPitch, + maxPitch, + minVolume, + maxVolume, + filterType, + loopCount, + 0, + false, + new byte[] { 0xFF } + ); + } + else if (eventType == 6) + { + // Unknown value + reader.ReadByte(); + + /* Event Flags + * 0x01 = Break Loop + * 0x02 = Use Speaker Position + * 0x04 = Use Center Speaker + * 0x08 = New Speaker Position On Loop + */ + reader.ReadByte(); + + // Number of times to loop wave (255 is infinite) + byte loopCount = reader.ReadByte(); + + // Speaker position angle/arc, unused + reader.ReadUInt16(); + reader.ReadUInt16(); + + // Pitch variation + short minPitch = reader.ReadInt16(); + short maxPitch = reader.ReadInt16(); + + // Volume variation + double minVolume = XACTCalculator.ParseDecibel(reader.ReadByte()); + double maxVolume = XACTCalculator.ParseDecibel(reader.ReadByte()); + + // Frequency Variation, unusued + reader.ReadSingle(); + reader.ReadSingle(); + + // Q Factor Variation, unused + reader.ReadSingle(); + reader.ReadSingle(); + + // Unknown value + reader.ReadByte(); + + // Variation flags + // FIXME: There's probably more to these flags... + byte varFlags = reader.ReadByte(); + if ((varFlags & 0x20) != 0x20) + { + // Throw out the volume variation. + minVolume = clipVolume; + maxVolume = clipVolume; + } + if ((varFlags & 0x10) != 0x10) + { + // Throw out the pitch variation + minPitch = 0; + maxPitch = 0; + } + + // Number of WaveBank tracks + ushort numTracks = reader.ReadUInt16(); + + /* Variation Playlist Type. + * First 4 bytes indicates Variation Type. + * Next 4 bytes appear to indicate New Variation On Loop. + * The rest is currently unknown. + * -flibit + */ + ushort variationValues = reader.ReadUInt16(); + ushort variationType = (ushort)(variationValues & 0x000F); + bool variationOnLoop = (variationValues & 0x00F0) > 0; + + // Unknown values + reader.ReadBytes(4); + + // Obtain WaveBank track information + ushort[] tracks = new ushort[numTracks]; + byte[] waveBanks = new byte[numTracks]; + byte[] weights = new byte[numTracks]; + for (ushort j = 0; j < numTracks; j += 1) + { + tracks[j] = reader.ReadUInt16(); + waveBanks[j] = reader.ReadByte(); + byte minWeight = reader.ReadByte(); + byte maxWeight = reader.ReadByte(); + weights[j] = (byte) (maxWeight - minWeight); + } + + // Finally. + Events[i] = new PlayWaveEvent( + eventTimestamp, + tracks, + waveBanks, + minPitch, + maxPitch, + minVolume, + maxVolume, + filterType, + loopCount, + variationType, + variationOnLoop, + weights + ); + } + else if (eventType == 7) + { + // Unknown values + reader.ReadBytes(2); + + /* Event Flags + * 0x08 = Min/Max Values + * Rest is unknown + */ + bool minMax = (reader.ReadByte() & 0x08) == 0x08; + + // Min/Max Random + float min = reader.ReadSingle() / 1000.0f; + float max; + if (minMax) + { + max = reader.ReadSingle() / 1000.0f; + } + else + { + max = min; + } + + // FIXME: Any more...? -flibit + + Events[i] = new SetPitchEvent( + eventTimestamp, + min, + max + ); + } + else if (eventType == 8) + { + // Unknown values + reader.ReadBytes(2); + + /* Event Flags + * 0x08 = Min/Max Values + * 0x01 = Add, rather than replace + * Rest is unknown + */ + byte flags = reader.ReadByte(); + bool addVolume = (flags & 0x01) == 0x01; + bool minMax = (flags & 0x08) == 0x08; + + // Operand Constant + float min = reader.ReadSingle() / 100.0f; + float max; + if (minMax) + { + max = reader.ReadSingle() / 100.0f; + + // Unknown bytes + reader.ReadBytes(5); + } + else + { + max = min; + + // Unknown values + reader.ReadBytes(8); + } + if (addVolume) + { + min += (float) clipVolume; + max += (float) clipVolume; + } + + Events[i] = new SetVolumeEvent( + eventTimestamp, + XACTCalculator.CalculateAmplitudeRatio(min), + XACTCalculator.CalculateAmplitudeRatio(max) + ); + } + else if (eventType == 15) + { + // TODO: Codename OhGodNo -flibit + // Unknown Event! + } + else if (eventType == 17) + { + // TODO: Codename OhGodNo -flibit + // Volume Repeat Event + } + else + { + /* TODO: All XACT Events. + * The following type information is based on + * third-party contributions: + * Type 9 - Marker Event + * -flibit + */ + throw new Exception( + "EVENT TYPE " + eventType.ToString() + " NOT IMPLEMENTED!" + ); + } + } + } + + public void LoadTracks(AudioEngine audioEngine, List waveBankNames) + { + foreach (XACTEvent curEvent in Events) + { + if (curEvent.Type == 1) + { + ((PlayWaveEvent) curEvent).LoadTracks( + audioEngine, + waveBankNames + ); + } + } + } + } + + internal abstract class XACTEvent + { + public uint Type + { + get; + private set; + } + + public uint Timestamp + { + get; + private set; + } + + protected static Random random = new Random(); + + public XACTEvent(uint type, uint timestamp) + { + Type = type; + Timestamp = timestamp; + } + } + + internal class PlayWaveEvent : XACTEvent + { + private enum VariationPlaylistType : ushort + { + Ordered, + OrderedFromRandom, + Random, + RandomNoImmediateRepeats, + Shuffle + } + + private ushort[] INTERNAL_tracks; + private byte[] INTERNAL_waveBanks; + + private short INTERNAL_minPitch; + private short INTERNAL_maxPitch; + + private double INTERNAL_minVolume; + private double INTERNAL_maxVolume; + + private byte INTERNAL_filterType; + + private byte INTERNAL_loopCount; + + private VariationPlaylistType INTERNAL_variationType; + private bool INTERNAL_variationOnLoop; + private byte[] INTERNAL_weights; + private int INTERNAL_curWave; + + private SoundEffect[] INTERNAL_waves; + + public PlayWaveEvent( + uint timestamp, + ushort[] tracks, + byte[] waveBanks, + short minPitch, + short maxPitch, + double minVolume, + double maxVolume, + byte filterType, + byte loopCount, + ushort variationType, + bool variationOnLoop, + byte[] weights + ) : base(1, timestamp) { + INTERNAL_tracks = tracks; + INTERNAL_waveBanks = waveBanks; + INTERNAL_minPitch = minPitch; + INTERNAL_maxPitch = maxPitch; + INTERNAL_minVolume = minVolume; + INTERNAL_maxVolume = maxVolume; + INTERNAL_filterType = filterType; + INTERNAL_loopCount = loopCount; + INTERNAL_variationType = (VariationPlaylistType) variationType; + INTERNAL_variationOnLoop = variationOnLoop; + INTERNAL_weights = weights; + INTERNAL_waves = new SoundEffect[tracks.Length]; + INTERNAL_curWave = -1; + } + + public void LoadTracks(AudioEngine audioEngine, List waveBankNames) + { + for (int i = 0; i < INTERNAL_waves.Length; i += 1) + { + INTERNAL_waves[i] = audioEngine.INTERNAL_getWaveBankTrack( + waveBankNames[INTERNAL_waveBanks[i]], + INTERNAL_tracks[i] + ); + } + } + + public SoundEffectInstance GenerateInstance( + double soundVolume, + float soundPitch, + int currentLoop + ) { + if (currentLoop > INTERNAL_loopCount && INTERNAL_loopCount != 255) + { + // We've finished all the loops! + return null; + } + INTERNAL_getNextSound(); + SoundEffectInstance result = INTERNAL_waves[INTERNAL_curWave].CreateInstance(); + result.INTERNAL_isXACTSource = true; + result.Volume = XACTCalculator.CalculateAmplitudeRatio( + soundVolume + ( + random.NextDouble() * + (INTERNAL_maxVolume - INTERNAL_minVolume) + ) + INTERNAL_minVolume + ); + result.Pitch = ( + random.Next( + INTERNAL_minPitch, + INTERNAL_maxPitch + ) / 1000.0f + ) + soundPitch; + result.FilterType = INTERNAL_filterType; + result.IsLooped = !INTERNAL_variationOnLoop && (INTERNAL_loopCount == 255); + return result; + } + + private void INTERNAL_getNextSound() + { + if (INTERNAL_variationType == VariationPlaylistType.Ordered) + { + INTERNAL_curWave += 1; + if (INTERNAL_curWave >= INTERNAL_waves.Length) + { + INTERNAL_curWave = 0; + } + } + else if (INTERNAL_variationType == VariationPlaylistType.OrderedFromRandom) + { + // FIXME: It seems like XACT organizes this for us? + INTERNAL_curWave += 1; + if (INTERNAL_curWave >= INTERNAL_waves.Length) + { + INTERNAL_curWave = 0; + } + } + else if (INTERNAL_variationType == VariationPlaylistType.Random) + { + double max = 0.0; + for (int i = 0; i < INTERNAL_weights.Length; i += 1) + { + max += INTERNAL_weights[i]; + } + double next = random.NextDouble() * max; + for (int i = INTERNAL_weights.Length - 1; i >= 0; i -= 1) + { + if (next > max - INTERNAL_weights[i]) + { + INTERNAL_curWave = i; + return; + } + max -= INTERNAL_weights[i]; + } + } + else if ( INTERNAL_variationType == VariationPlaylistType.RandomNoImmediateRepeats || + INTERNAL_variationType == VariationPlaylistType.Shuffle ) + { + // FIXME: Is Shuffle really any different from this? + double max = 0.0; + for (int i = 0; i < INTERNAL_weights.Length; i += 1) + { + if (i == INTERNAL_curWave) + { + continue; + } + max += INTERNAL_weights[i]; + } + double next = random.NextDouble() * max; + for (int i = INTERNAL_weights.Length - 1; i >= 0; i -= 1) + { + if (i == INTERNAL_curWave) + { + continue; + } + if (next > max - INTERNAL_weights[i]) + { + INTERNAL_curWave = i; + return; + } + max -= INTERNAL_weights[i]; + } + } + else + { + throw new Exception( + "Variation Playlist Type unhandled: " + + INTERNAL_variationType.ToString() + ); + } + } + } + + internal class SetVolumeEvent : XACTEvent + { + private float INTERNAL_min; + private float INTERNAL_max; + + public SetVolumeEvent( + uint timestamp, + float min, + float max + ) : base(2, timestamp) { + INTERNAL_min = min; + INTERNAL_max = max; + } + + public float GetVolume() + { + return INTERNAL_min + (float) ( + random.NextDouble() * (INTERNAL_max - INTERNAL_min) + ); + } + } + + internal class SetPitchEvent : XACTEvent + { + private float INTERNAL_min; + private float INTERNAL_max; + + public SetPitchEvent( + uint timestamp, + float min, + float max + ) : base(3, timestamp) { + INTERNAL_min = min; + INTERNAL_max = max; + } + + public float GetPitch() + { + return INTERNAL_min + (float) ( + random.NextDouble() * (INTERNAL_max - INTERNAL_min) + ); + } + } +} diff --git a/src/Audio/DynamicSoundEffectInstance.cs b/src/Audio/DynamicSoundEffectInstance.cs new file mode 100644 index 0000000..ed3ccc3 --- /dev/null +++ b/src/Audio/DynamicSoundEffectInstance.cs @@ -0,0 +1,395 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + // http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.dynamicsoundeffectinstance.aspx + public sealed class DynamicSoundEffectInstance : SoundEffectInstance + { + #region Public Properties + + public int PendingBufferCount + { + get; + private set; + } + + public override bool IsLooped + { + get + { + return false; + } + set + { + // No-op, DynamicSoundEffectInstance cannot be looped! + } + } + + #endregion + + #region Private XNA Variables + + private int sampleRate; + private AudioChannels channels; + + private const int MINIMUM_BUFFER_CHECK = 3; + + #endregion + + #region Private AL Variables + + private Queue queuedBuffers; + private Queue buffersToQueue; + private Queue availableBuffers; + + #endregion + + #region BufferNeeded Event + + public event EventHandler BufferNeeded; + + #endregion + + #region Public Constructor + + public DynamicSoundEffectInstance(int sampleRate, AudioChannels channels) : base(null) + { + this.sampleRate = sampleRate; + this.channels = channels; + + PendingBufferCount = 0; + + isDynamic = true; + queuedBuffers = new Queue(); + buffersToQueue = new Queue(); + availableBuffers = new Queue(); + } + + #endregion + + #region Destructor + + ~DynamicSoundEffectInstance() + { + Dispose(); + } + + #endregion + + #region Public Dispose Method + + public override void Dispose() + { + if (!IsDisposed) + { + base.Dispose(); // Will call Stop(true); + + // Delete all known buffer objects + while (queuedBuffers.Count > 0) + { + AudioDevice.ALDevice.DeleteBuffer(queuedBuffers.Dequeue()); + } + queuedBuffers = null; + while (availableBuffers.Count > 0) + { + AudioDevice.ALDevice.DeleteBuffer(availableBuffers.Dequeue()); + } + availableBuffers = null; + while (buffersToQueue.Count > 0) + { + AudioDevice.ALDevice.DeleteBuffer(buffersToQueue.Dequeue()); + } + buffersToQueue = null; + + IsDisposed = true; + } + } + + #endregion + + #region Public Time/Sample Information Methods + + public TimeSpan GetSampleDuration(int sizeInBytes) + { + return SoundEffect.GetSampleDuration( + sizeInBytes, + sampleRate, + channels + ); + } + + public int GetSampleSizeInBytes(TimeSpan duration) + { + return SoundEffect.GetSampleSizeInBytes( + duration, + sampleRate, + channels + ); + } + + #endregion + + #region Public SubmitBuffer Methods + + public void SubmitBuffer(byte[] buffer) + { + this.SubmitBuffer(buffer, 0, buffer.Length); + } + + public void SubmitBuffer(byte[] buffer, int offset, int count) + { + // Generate a buffer if we don't have any to use. + if (availableBuffers.Count == 0) + { + availableBuffers.Enqueue( + AudioDevice.ALDevice.GenBuffer() + ); + } + + // Push the data to OpenAL. + IALBuffer newBuf = availableBuffers.Dequeue(); + AudioDevice.ALDevice.SetBufferData( + newBuf, + channels, + buffer, // TODO: offset -flibit + count, + sampleRate + ); + + // If we're already playing, queue immediately. + if (INTERNAL_alSource != null) + { + AudioDevice.ALDevice.QueueSourceBuffer( + INTERNAL_alSource, + newBuf + ); + queuedBuffers.Enqueue(newBuf); + + // If the source stopped, reboot it now. + if (AudioDevice.ALDevice.GetSourceState(INTERNAL_alSource) == SoundState.Stopped) + { + AudioDevice.ALDevice.PlaySource(INTERNAL_alSource); + } + } + else + { + buffersToQueue.Enqueue(newBuf); + } + + PendingBufferCount += 1; + } + + #endregion + + #region Public Play Method + + public override void Play() + { + Play(true); + } + + #endregion + + #region Internal Play Method + + internal void Play(bool isManaged) + { + if (State != SoundState.Stopped) + { + return; // No-op if we're already playing. + } + + if (INTERNAL_alSource != null) + { + // The sound has stopped, but hasn't cleaned up yet... + AudioDevice.ALDevice.StopAndDisposeSource(INTERNAL_alSource); + INTERNAL_alSource = null; + } + while (queuedBuffers.Count > 0) + { + availableBuffers.Enqueue(queuedBuffers.Dequeue()); + PendingBufferCount -= 1; + } + + INTERNAL_alSource = AudioDevice.ALDevice.GenSource(); + if (INTERNAL_alSource == null) + { + System.Console.WriteLine("WARNING: AL SOURCE WAS NOT AVAILABLE. SKIPPING."); + return; + } + + // Queue the buffers to this source + while (buffersToQueue.Count > 0) + { + IALBuffer nextBuf = buffersToQueue.Dequeue(); + queuedBuffers.Enqueue(nextBuf); + AudioDevice.ALDevice.QueueSourceBuffer(INTERNAL_alSource, nextBuf); + } + + // Apply Pan/Position + if (INTERNAL_positionalAudio) + { + INTERNAL_positionalAudio = false; + AudioDevice.ALDevice.SetSourcePosition( + INTERNAL_alSource, + position + ); + } + else + { + Pan = Pan; + } + + // Reassign Properties, in case the AL properties need to be applied. + Volume = Volume; + Pitch = Pitch; + + // ... but wait! What if we need moar buffers? + for ( + int i = MINIMUM_BUFFER_CHECK - PendingBufferCount; + (i > 0) && BufferNeeded != null; + i -= 1 + ) { + BufferNeeded(this, null); + } + + // Finally. + AudioDevice.ALDevice.PlaySource(INTERNAL_alSource); + if (isManaged) + { + AudioDevice.DynamicInstancePool.Add(this); + } + } + + #endregion + + #region Internal Update Method + + internal void Update() + { + // Get the number of processed buffers. + int finishedBuffers = AudioDevice.ALDevice.CheckProcessedBuffers( + INTERNAL_alSource + ); + if (finishedBuffers == 0) + { + // Nothing to do... yet. + return; + } + + // Dequeue the processed buffers, error checking as needed. + AudioDevice.ALDevice.DequeueSourceBuffers( + INTERNAL_alSource, + finishedBuffers, + queuedBuffers + ); + + // The processed buffers are now available. + for (int i = 0; i < finishedBuffers; i += 1) + { + availableBuffers.Enqueue(queuedBuffers.Dequeue()); + } + + // PendingBufferCount changed during playback, trigger now! + PendingBufferCount -= finishedBuffers; + if (BufferNeeded != null) + { + BufferNeeded(this, null); + } + + // Do we need even moar buffers? + for ( + int i = MINIMUM_BUFFER_CHECK - PendingBufferCount; + (i > 0) && BufferNeeded != null; + i -= 1 + ) { + BufferNeeded(this, null); + } + } + + #endregion + + #region Internal Sample Data Retrieval Method + + internal void GetSamples(float[] samples) + { + if (INTERNAL_alSource != null && queuedBuffers.Count > 0) + { + AudioDevice.ALDevice.GetBufferData( + INTERNAL_alSource, + queuedBuffers.ToArray(), // FIXME: Blech -flibit + samples, + channels + ); + } + else + { + Array.Clear(samples, 0, samples.Length); + } + } + + #endregion + + #region Public FNA Extension Methods + + /* THIS IS AN EXTENSION OF THE XNA4 API! */ + public void SubmitFloatBufferEXT(float[] buffer) + { + /* Float samples are the typical format received from decoders. + * We currently use this for the VideoPlayer. + * -flibit + */ + + // Generate a buffer if we don't have any to use. + if (availableBuffers.Count == 0) + { + availableBuffers.Enqueue(AudioDevice.ALDevice.GenBuffer()); + } + + // Push buffer to the AL. + IALBuffer newBuf = availableBuffers.Dequeue(); + AudioDevice.ALDevice.SetBufferData( + newBuf, + channels, + buffer, + sampleRate + ); + + // If we're already playing, queue immediately. + if (INTERNAL_alSource != null) + { + AudioDevice.ALDevice.QueueSourceBuffer( + INTERNAL_alSource, + newBuf + ); + queuedBuffers.Enqueue(newBuf); + + // If the source stopped, reboot it now. + if (AudioDevice.ALDevice.GetSourceState(INTERNAL_alSource) == SoundState.Stopped) + { + AudioDevice.ALDevice.PlaySource(INTERNAL_alSource); + } + } + else + { + buffersToQueue.Enqueue(newBuf); + } + + PendingBufferCount += 1; + } + + #endregion + } +} diff --git a/src/Audio/IALDevice.cs b/src/Audio/IALDevice.cs new file mode 100644 index 0000000..b666460 --- /dev/null +++ b/src/Audio/IALDevice.cs @@ -0,0 +1,127 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + internal interface IALDevice + { + void Update(); + void Dispose(); + ReadOnlyCollection GetDevices(); + ReadOnlyCollection GetCaptureDevices(); + + IALBuffer GenBuffer(); + IALBuffer GenBuffer( + byte[] data, + uint sampleRate, + uint channels, + uint loopStart, + uint loopEnd, + bool isADPCM, + uint formatParameter + ); + void DeleteBuffer(IALBuffer buffer); + void SetBufferData( + IALBuffer buffer, + AudioChannels channels, + byte[] data, + int count, + int sampleRate + ); + void SetBufferData( + IALBuffer buffer, + AudioChannels channels, + float[] data, + int sampleRate + ); + + IALSource GenSource(); + IALSource GenSource(IALBuffer buffer); + void StopAndDisposeSource(IALSource source); + void PlaySource(IALSource source); + void PauseSource(IALSource source); + void ResumeSource(IALSource source); + SoundState GetSourceState(IALSource source); + void SetSourceVolume(IALSource source, float volume); + void SetSourceLooped(IALSource source, bool looped); + void SetSourcePan(IALSource source, float pan); + void SetSourcePosition(IALSource source, Vector3 pos); + void SetSourcePitch(IALSource source, float pitch, bool clamp); + void SetSourceReverb(IALSource source, IALReverb reverb); + void SetSourceLowPassFilter(IALSource source, float hfGain); + void SetSourceHighPassFilter(IALSource source, float lfGain); + void SetSourceBandPassFilter(IALSource source, float hfGain, float lfGain); + void QueueSourceBuffer(IALSource source, IALBuffer buffer); + void DequeueSourceBuffers( + IALSource source, + int buffersToDequeue, + Queue errorCheck + ); + int CheckProcessedBuffers(IALSource source); + void GetBufferData( + IALSource source, + IALBuffer[] buffer, + float[] samples, + AudioChannels channels + ); + + IALReverb GenReverb(DSPParameter[] parameters); + void DeleteReverb(IALReverb reverb); + void CommitReverbChanges(IALReverb reverb); + void SetReverbReflectionsDelay(IALReverb reverb, float value); + void SetReverbDelay(IALReverb reverb, float value); + void SetReverbPositionLeft(IALReverb reverb, float value); + void SetReverbPositionRight(IALReverb reverb, float value); + void SetReverbPositionLeftMatrix(IALReverb reverb, float value); + void SetReverbPositionRightMatrix(IALReverb reverb, float value); + void SetReverbEarlyDiffusion(IALReverb reverb, float value); + void SetReverbLateDiffusion(IALReverb reverb, float value); + void SetReverbLowEQGain(IALReverb reverb, float value); + void SetReverbLowEQCutoff(IALReverb reverb, float value); + void SetReverbHighEQGain(IALReverb reverb, float value); + void SetReverbHighEQCutoff(IALReverb reverb, float value); + void SetReverbRearDelay(IALReverb reverb, float value); + void SetReverbRoomFilterFrequency(IALReverb reverb, float value); + void SetReverbRoomFilterMain(IALReverb reverb, float value); + void SetReverbRoomFilterHighFrequency(IALReverb reverb, float value); + void SetReverbReflectionsGain(IALReverb reverb, float value); + void SetReverbGain(IALReverb reverb, float value); + void SetReverbDecayTime(IALReverb reverb, float value); + void SetReverbDensity(IALReverb reverb, float value); + void SetReverbRoomSize(IALReverb reverb, float value); + void SetReverbWetDryMix(IALReverb reverb, float value); + + IntPtr StartDeviceCapture(string name, int sampleRate, int bufSize); + void StopDeviceCapture(IntPtr handle); + int CaptureSamples(IntPtr handle, IntPtr buffer, int count); + bool CaptureHasSamples(IntPtr handle); + } + + internal interface IALBuffer + { + TimeSpan Duration + { + get; + } + } + + internal interface IALSource + { + } + + internal interface IALReverb + { + } +} diff --git a/src/Audio/InstancePlayLimitException.cs b/src/Audio/InstancePlayLimitException.cs new file mode 100644 index 0000000..c9537f3 --- /dev/null +++ b/src/Audio/InstancePlayLimitException.cs @@ -0,0 +1,22 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Runtime.InteropServices; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + // http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.instanceplaylimitexception.aspx + [Serializable] + public sealed class InstancePlayLimitException : ExternalException + { + } +} diff --git a/src/Audio/Microphone.cs b/src/Audio/Microphone.cs new file mode 100644 index 0000000..dd3feee --- /dev/null +++ b/src/Audio/Microphone.cs @@ -0,0 +1,221 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.ObjectModel; +using System.Runtime.InteropServices; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + public class Microphone + { + #region Public Static Properties + + public static ReadOnlyCollection All + { + get; + internal set; + } + + public static Microphone Default + { + get + { + if (All.Count == 0) + { + return null; + } + return All[0]; + } + } + + #endregion + + #region Public Properties + + public TimeSpan BufferDuration + { + get + { + return bufferDuration; + } + set + { + if ( value.Milliseconds < 100 || + value.Milliseconds > 1000 || + value.Milliseconds % 10 != 0 ) + { + throw new ArgumentOutOfRangeException(); + } + bufferDuration = value; + } + } + + public bool IsHeadset + { + get + { + // FIXME: I think this is just for Windows Phone? -flibit + return false; + } + } + + public int SampleRate + { + get + { + return SAMPLERATE; + } + } + + public MicrophoneState State + { + get; + private set; + } + + #endregion + + #region Public Variables + + public readonly string Name; + + #endregion + + #region Private Variables + + private TimeSpan bufferDuration; + private IntPtr nativeMic; + + #endregion + + #region Events + + public event EventHandler BufferReady; + + #endregion + + #region Private Constants + + /* FIXME: This is what XNA4 aims for, but it _could_ be lower. + * Something work looking at is falling back to lower sample rates in + * powers of two, i.e. 44100, 22050, 11025, etc. + * -flibit + */ + private const int SAMPLERATE = 44100; + + #endregion + + #region Internal Constructor + + internal Microphone(string name) + { + Name = name; + bufferDuration = TimeSpan.FromSeconds(1.0); + State = MicrophoneState.Stopped; + } + + #endregion + + #region Public Methods + + public int GetData(byte[] buffer) + { + return GetData(buffer, 0, buffer.Length); + } + + public int GetData(byte[] buffer, int offset, int count) + { + if (buffer == null) + { + throw new ArgumentException("buffer is null!"); + } + if (offset < 0 || offset > buffer.Length) + { + throw new ArgumentException("offset"); + } + if (count <= 0 || (offset + count) > buffer.Length) + { + throw new ArgumentException("count"); + } + GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); + int read = AudioDevice.ALDevice.CaptureSamples( + nativeMic, + handle.AddrOfPinnedObject() + offset, + count + ); + handle.Free(); + return read; + } + + public TimeSpan GetSampleDuration(int sizeInBytes) + { + return SoundEffect.GetSampleDuration( + sizeInBytes, + SampleRate, + AudioChannels.Mono + ); + } + + public int GetSampleSizeInBytes(TimeSpan duration) + { + return SoundEffect.GetSampleSizeInBytes( + duration, + SampleRate, + AudioChannels.Mono + ); + } + + public void Start() + { + if (State == MicrophoneState.Stopped) + { + nativeMic = AudioDevice.ALDevice.StartDeviceCapture( + Name, + SampleRate, + GetSampleSizeInBytes(bufferDuration) + ); + if (nativeMic == IntPtr.Zero) + { + throw new NoMicrophoneConnectedException(Name); + } + AudioDevice.ActiveMics.Add(this); + State = MicrophoneState.Started; + } + } + + public void Stop() + { + if (State == MicrophoneState.Started) + { + AudioDevice.ActiveMics.Remove(this); + AudioDevice.ALDevice.StopDeviceCapture(nativeMic); + nativeMic = IntPtr.Zero; + State = MicrophoneState.Stopped; + } + } + + #endregion + + #region Internal Methods + + internal void CheckBuffer() + { + if ( BufferReady != null && + AudioDevice.ALDevice.CaptureHasSamples(nativeMic) ) + { + BufferReady(this, EventArgs.Empty); + } + } + + #endregion + } +} diff --git a/src/Audio/MicrophoneState.cs b/src/Audio/MicrophoneState.cs new file mode 100644 index 0000000..06bd7e0 --- /dev/null +++ b/src/Audio/MicrophoneState.cs @@ -0,0 +1,17 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + public enum MicrophoneState + { + Started, + Stopped + } +} diff --git a/src/Audio/NoAudioHardwareException.cs b/src/Audio/NoAudioHardwareException.cs new file mode 100644 index 0000000..3c8fe95 --- /dev/null +++ b/src/Audio/NoAudioHardwareException.cs @@ -0,0 +1,35 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Runtime.InteropServices; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + // http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.noaudiohardwareexception.aspx + [Serializable] + public sealed class NoAudioHardwareException : ExternalException + { + public NoAudioHardwareException() + { + } + + public NoAudioHardwareException(String message) + : base(message) + { + } + + public NoAudioHardwareException(String message, Exception innerException) + : base(message, innerException) + { + } + } +} diff --git a/src/Audio/NoMicrophoneConnectedException.cs b/src/Audio/NoMicrophoneConnectedException.cs new file mode 100644 index 0000000..6fb815e --- /dev/null +++ b/src/Audio/NoMicrophoneConnectedException.cs @@ -0,0 +1,35 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Runtime.InteropServices; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + // http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.nomicrophoneconnectedexception.aspx + [Serializable] + public sealed class NoMicrophoneConnectedException : Exception + { + public NoMicrophoneConnectedException() + { + } + + public NoMicrophoneConnectedException(String message) + : base(message) + { + } + + public NoMicrophoneConnectedException(String message, Exception innerException) + : base(message, innerException) + { + } + } +} diff --git a/src/Audio/NullDevice.cs b/src/Audio/NullDevice.cs new file mode 100644 index 0000000..ff8d7a0 --- /dev/null +++ b/src/Audio/NullDevice.cs @@ -0,0 +1,370 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + /* This is a device that deliberately does as little as possible, allowing + * for no sound without throwing NoAudioHardwareExceptions. This is not a + * part of the XNA4 spec, however, so behavior here is entirely undefined! + * -flibit + */ + internal class NullDevice : IALDevice + { + private class NullBuffer : IALBuffer + { + public TimeSpan Duration + { + get + { + // FIXME: Maybe read the PCM/ADPCM lengths? -flibit + return TimeSpan.Zero; + } + } + } + + private class NullSource : IALSource + { + } + + private class NullReverb : IALReverb + { + } + + public void Update() + { + // No-op, duh. + } + + public void Dispose() + { + // No-op, duh. + } + + public ReadOnlyCollection GetDevices() + { + return new ReadOnlyCollection( + new List() + ); + } + + public ReadOnlyCollection GetCaptureDevices() + { + return new ReadOnlyCollection( + new List() + ); + } + + public IALBuffer GenBuffer() + { + return new NullBuffer(); + } + + public IALBuffer GenBuffer( + byte[] data, + uint sampleRate, + uint channels, + uint loopStart, + uint loopEnd, + bool isADPCM, + uint formatParameter + ) { + return new NullBuffer(); + } + + public void DeleteBuffer(IALBuffer buffer) + { + // No-op, duh. + } + + public void SetBufferData( + IALBuffer buffer, + AudioChannels channels, + byte[] data, + int count, + int sampleRate + ) { + // No-op, duh. + } + + public void SetBufferData( + IALBuffer buffer, + AudioChannels channels, + float[] data, + int sampleRate + ) { + // No-op, duh. + } + + public IALSource GenSource() + { + return new NullSource(); + } + + public IALSource GenSource(IALBuffer buffer) + { + return new NullSource(); + } + + public void StopAndDisposeSource(IALSource source) + { + // No-op, duh. + } + + public void PlaySource(IALSource source) + { + // No-op, duh. + } + + public void PauseSource(IALSource source) + { + // No-op, duh. + } + + public void ResumeSource(IALSource source) + { + // No-op, duh. + } + + public SoundState GetSourceState(IALSource source) + { + /* FIXME: This return value is highly volatile! + * You can't necessarily do Stopped, because then stuff like Song + * explodes, but SoundState.Playing doesn't make a whole lot of + * sense either. This at least prevents annoyances like Song errors + * from happening and, for the most part, claims to be "playing" + * depending on how you ask for a source's state. + * -flibit + */ + return SoundState.Paused; + } + + public void SetSourceVolume(IALSource source, float volume) + { + // No-op, duh. + } + + public void SetSourceLooped(IALSource source, bool looped) + { + // No-op, duh. + } + + public void SetSourcePan(IALSource source, float pan) + { + // No-op, duh. + } + + public void SetSourcePosition(IALSource source, Vector3 pos) + { + // No-op, duh. + } + + public void SetSourcePitch(IALSource source, float pitch, bool clamp) + { + // No-op, duh. + } + + public void SetSourceReverb(IALSource source, IALReverb reverb) + { + // No-op, duh. + } + + public void SetSourceLowPassFilter(IALSource source, float hfGain) + { + // No-op, duh. + } + + public void SetSourceHighPassFilter(IALSource source, float lfGain) + { + // No-op, duh. + } + + public void SetSourceBandPassFilter(IALSource source, float hfGain, float lfGain) + { + // No-op, duh. + } + + public void QueueSourceBuffer(IALSource source, IALBuffer buffer) + { + // No-op, duh. + } + + public void DequeueSourceBuffers( + IALSource source, + int buffersToDequeue, + Queue errorCheck + ) { + // No-op, duh. + } + + public int CheckProcessedBuffers(IALSource source) + { + return 0; + } + + public void GetBufferData( + IALSource source, + IALBuffer[] buffer, + float[] samples, + AudioChannels channels + ) { + // No-op, duh. + } + + public IALReverb GenReverb(DSPParameter[] parameters) + { + return new NullReverb(); + } + + public void DeleteReverb(IALReverb reverb) + { + // No-op, duh. + } + + public void CommitReverbChanges(IALReverb reverb) + { + // No-op, duh. + } + + public void SetReverbReflectionsDelay(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbDelay(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbPositionLeft(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbPositionRight(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbPositionLeftMatrix(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbPositionRightMatrix(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbEarlyDiffusion(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbLateDiffusion(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbLowEQGain(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbLowEQCutoff(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbHighEQGain(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbHighEQCutoff(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbRearDelay(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbRoomFilterFrequency(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbRoomFilterMain(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbRoomFilterHighFrequency(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbReflectionsGain(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbGain(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbDecayTime(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbDensity(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbRoomSize(IALReverb reverb, float value) + { + // No-op, duh. + } + + public void SetReverbWetDryMix(IALReverb reverb, float value) + { + // No-op, duh. + } + + public IntPtr StartDeviceCapture(string name, int sampleRate, int bufSize) + { + return IntPtr.Zero; + } + + public void StopDeviceCapture(IntPtr handle) + { + // No-op, duh. + } + + public int CaptureSamples(IntPtr handle, IntPtr buffer, int count) + { + return 0; + } + + public bool CaptureHasSamples(IntPtr handle) + { + return false; + } + } +} diff --git a/src/Audio/OpenALDevice.cs b/src/Audio/OpenALDevice.cs new file mode 100644 index 0000000..8a0ba40 --- /dev/null +++ b/src/Audio/OpenALDevice.cs @@ -0,0 +1,1191 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region VERBOSE_AL_DEBUGGING Option +// #define VERBOSE_AL_DEBUGGING +/* OpenAL does not have a function similar to ARB_debug_output. Because of this, + * we only have alGetError to debug. In DEBUG, we call this once per frame. + * + * If you enable this define, we call this after every single AL operation, and + * throw an Exception when any errors show up. This makes finding problems a lot + * easier, but calling alGetError so often can slow things down. + * -flibit + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Runtime.InteropServices; + +using OpenAL; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + internal class OpenALDevice : IALDevice + { + #region OpenAL Buffer Container Class + + private class OpenALBuffer : IALBuffer + { + public uint Handle + { + get; + private set; + } + + public TimeSpan Duration + { + get; + private set; + } + + public OpenALBuffer(uint handle, TimeSpan duration) + { + Handle = handle; + Duration = duration; + } + } + + #endregion + + #region OpenAL Source Container Class + + private class OpenALSource : IALSource + { + public uint Handle + { + get; + private set; + } + + public OpenALSource(uint handle) + { + Handle = handle; + } + } + + #endregion + + #region OpenAL Reverb Effect Container Class + + private class OpenALReverb : IALReverb + { + public uint SlotHandle + { + get; + private set; + } + + public uint EffectHandle + { + get; + private set; + } + + public OpenALReverb(uint slot, uint effect) + { + SlotHandle = slot; + EffectHandle = effect; + } + } + + #endregion + + #region Private ALC Variables + + // OpenAL Device/Context Handles + private IntPtr alDevice; + private IntPtr alContext; + + #endregion + + #region Private EFX Variables + + // OpenAL Filter Handle + private uint INTERNAL_alFilter; + + #endregion + + #region Public Constructor + + public OpenALDevice() + { + string envDevice = Environment.GetEnvironmentVariable("FNA_AUDIO_DEVICE_NAME"); + if (String.IsNullOrEmpty(envDevice)) + { + /* Be sure ALC won't explode if the variable doesn't exist. + * But, fail if the device name is wrong. The user needs to know + * if their environment variable was incorrect. + * -flibit + */ + envDevice = String.Empty; + } + alDevice = ALC10.alcOpenDevice(envDevice); + if (CheckALCError() || alDevice == IntPtr.Zero) + { + throw new Exception("Could not open audio device!"); + } + + int[] attribute = new int[0]; + alContext = ALC10.alcCreateContext(alDevice, attribute); + if (CheckALCError() || alContext == IntPtr.Zero) + { + Dispose(); + throw new Exception("Could not create OpenAL context"); + } + + ALC10.alcMakeContextCurrent(alContext); + if (CheckALCError()) + { + Dispose(); + throw new Exception("Could not make OpenAL context current"); + } + + float[] ori = new float[] + { + 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f + }; + AL10.alListenerfv(AL10.AL_ORIENTATION, ori); + AL10.alListener3f(AL10.AL_POSITION, 0.0f, 0.0f, 0.0f); + AL10.alListener3f(AL10.AL_VELOCITY, 0.0f, 0.0f, 0.0f); + AL10.alListenerf(AL10.AL_GAIN, 1.0f); + + // We do NOT use automatic attenuation! XNA does not do this! + AL10.alDistanceModel(AL10.AL_NONE); + + EFX.alGenFilters((IntPtr) 1, out INTERNAL_alFilter); + } + + #endregion + + #region Public Dispose Method + + public void Dispose() + { + EFX.alDeleteFilters((IntPtr) 1, ref INTERNAL_alFilter); + + ALC10.alcMakeContextCurrent(IntPtr.Zero); + if (alContext != IntPtr.Zero) + { + ALC10.alcDestroyContext(alContext); + alContext = IntPtr.Zero; + } + if (alDevice != IntPtr.Zero) + { + ALC10.alcCloseDevice(alDevice); + alDevice = IntPtr.Zero; + } + } + + #endregion + + #region Public Update Method + + public void Update() + { +#if DEBUG + CheckALError(); +#endif + } + + #endregion + + #region OpenAL Buffer Methods + + public IALBuffer GenBuffer() + { + uint result; + AL10.alGenBuffers((IntPtr) 1, out result); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + return new OpenALBuffer(result, TimeSpan.Zero); + } + + public IALBuffer GenBuffer( + byte[] data, + uint sampleRate, + uint channels, + uint loopStart, + uint loopEnd, + bool isADPCM, + uint formatParameter + ) { + uint result; + + // Generate the buffer now, in case we need to perform alBuffer ops. + AL10.alGenBuffers((IntPtr) 1, out result); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + + int format; + if (isADPCM) + { + format = (channels == 2) ? + ALEXT.AL_FORMAT_STEREO_MSADPCM_SOFT : + ALEXT.AL_FORMAT_MONO_MSADPCM_SOFT; + AL10.alBufferi( + result, + ALEXT.AL_UNPACK_BLOCK_ALIGNMENT_SOFT, + (int) formatParameter + ); + } + else + { + if (formatParameter == 1) + { + format = (channels == 2) ? + AL10.AL_FORMAT_STEREO16: + AL10.AL_FORMAT_MONO16; + } + else + { + format = (channels == 2) ? + AL10.AL_FORMAT_STEREO8: + AL10.AL_FORMAT_MONO8; + } + } + + // Load it! + AL10.alBufferData( + result, + format, + data, + (IntPtr) data.Length, + (IntPtr) sampleRate + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + + // Calculate the duration now, after we've unpacked the buffer + int bufLen, bits; + AL10.alGetBufferi( + result, + AL10.AL_SIZE, + out bufLen + ); + AL10.alGetBufferi( + result, + AL10.AL_BITS, + out bits + ); + if (bufLen == 0 || bits == 0) + { + throw new InvalidOperationException( + "OpenAL buffer allocation failed!" + ); + } + TimeSpan resultDur = TimeSpan.FromSeconds( + bufLen / + (bits / 8) / + channels / + ((double) sampleRate) + ); + + // Set the loop points, if applicable + if (loopStart > 0 || loopEnd > 0) + { + AL10.alBufferiv( + result, + ALEXT.AL_LOOP_POINTS_SOFT, + new int[] + { + (int) loopStart, + (int) loopEnd + } + ); + } +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + + // Finally. + return new OpenALBuffer(result, resultDur); + } + + public void DeleteBuffer(IALBuffer buffer) + { + uint handle = (buffer as OpenALBuffer).Handle; + AL10.alDeleteBuffers((IntPtr) 1, ref handle); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetBufferData( + IALBuffer buffer, + AudioChannels channels, + byte[] data, + int count, + int sampleRate + ) { + AL10.alBufferData( + (buffer as OpenALBuffer).Handle, + XNAToShort[(int) channels], + data, // TODO: offset -flibit + (IntPtr) count, + (IntPtr) sampleRate + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetBufferData( + IALBuffer buffer, + AudioChannels channels, + float[] data, + int sampleRate + ) { + AL10.alBufferData( + (buffer as OpenALBuffer).Handle, + XNAToFloat[(int) channels], + data, + (IntPtr) (data.Length * 4), + (IntPtr) sampleRate + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + #endregion + + #region OpenAL Source Methods + + public IALSource GenSource() + { + uint result; + AL10.alGenSources((IntPtr) 1, out result); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + if (result == 0) + { + return null; + } + return new OpenALSource(result); + } + + public IALSource GenSource(IALBuffer buffer) + { + uint result; + AL10.alGenSources((IntPtr) 1, out result); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + if (result == 0) + { + return null; + } + AL10.alSourcei( + result, + AL10.AL_BUFFER, + (int) (buffer as OpenALBuffer).Handle + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + return new OpenALSource(result); + } + + public void StopAndDisposeSource(IALSource source) + { + uint handle = (source as OpenALSource).Handle; + AL10.alSourceStop(handle); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + AL10.alDeleteSources((IntPtr) 1, ref handle); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void PlaySource(IALSource source) + { + AL10.alSourcePlay((source as OpenALSource).Handle); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void PauseSource(IALSource source) + { + AL10.alSourcePause((source as OpenALSource).Handle); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void ResumeSource(IALSource source) + { + AL10.alSourcePlay((source as OpenALSource).Handle); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public SoundState GetSourceState(IALSource source) + { + int state; + AL10.alGetSourcei( + (source as OpenALSource).Handle, + AL10.AL_SOURCE_STATE, + out state + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + if (state == AL10.AL_PLAYING) + { + return SoundState.Playing; + } + else if (state == AL10.AL_PAUSED) + { + return SoundState.Paused; + } + return SoundState.Stopped; + } + + public void SetSourceVolume(IALSource source, float volume) + { + AL10.alSourcef( + (source as OpenALSource).Handle, + AL10.AL_GAIN, + volume * SoundEffect.MasterVolume + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetSourceLooped(IALSource source, bool looped) + { + AL10.alSourcei( + (source as OpenALSource).Handle, + AL10.AL_LOOPING, + looped ? 1 : 0 + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetSourcePan(IALSource source, float pan) + { + AL10.alSource3f( + (source as OpenALSource).Handle, + AL10.AL_POSITION, + pan, + 0.0f, + (float) Math.Sqrt(1 - Math.Pow(pan, 2)) + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetSourcePosition(IALSource source, Vector3 pos) + { + AL10.alSource3f( + (source as OpenALSource).Handle, + AL10.AL_POSITION, + pos.X, + pos.Y, + pos.Z + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetSourcePitch(IALSource source, float pitch, bool clamp) + { + /* XNA sets pitch bounds to [-1.0f, 1.0f], each end being one octave. + * OpenAL's AL_PITCH boundaries are (0.0f, INF). + * Consider the function f(x) = 2 ^ x + * The domain is (-INF, INF) and the range is (0, INF). + * 0.0f is the original pitch for XNA, 1.0f is the original pitch for OpenAL. + * Note that f(0) = 1, f(1) = 2, f(-1) = 0.5, and so on. + * XNA's pitch values are on the domain, OpenAL's are on the range. + * Remember: the XNA limit is arbitrarily between two octaves on the domain. + * To convert, we just plug XNA pitch into f(x). + * -flibit + */ + if (clamp && (pitch < -1.0f || pitch > 1.0f)) + { + throw new Exception("XNA PITCH MUST BE WITHIN [-1.0f, 1.0f]!"); + } + AL10.alSourcef( + (source as OpenALSource).Handle, + AL10.AL_PITCH, + (float) Math.Pow(2, pitch) + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetSourceReverb(IALSource source, IALReverb reverb) + { + AL10.alSource3i( + (source as OpenALSource).Handle, + EFX.AL_AUXILIARY_SEND_FILTER, + (int) (reverb as OpenALReverb).SlotHandle, + 0, + 0 + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetSourceLowPassFilter(IALSource source, float hfGain) + { + EFX.alFilteri(INTERNAL_alFilter, EFX.AL_FILTER_TYPE, EFX.AL_FILTER_LOWPASS); + EFX.alFilterf(INTERNAL_alFilter, EFX.AL_LOWPASS_GAINHF, hfGain); + AL10.alSourcei( + (source as OpenALSource).Handle, + EFX.AL_DIRECT_FILTER, + (int) INTERNAL_alFilter + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetSourceHighPassFilter(IALSource source, float lfGain) + { + EFX.alFilteri(INTERNAL_alFilter, EFX.AL_FILTER_TYPE, EFX.AL_FILTER_HIGHPASS); + EFX.alFilterf(INTERNAL_alFilter, EFX.AL_HIGHPASS_GAINLF, lfGain); + AL10.alSourcei( + (source as OpenALSource).Handle, + EFX.AL_DIRECT_FILTER, + (int) INTERNAL_alFilter + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetSourceBandPassFilter(IALSource source, float hfGain, float lfGain) + { + EFX.alFilteri(INTERNAL_alFilter, EFX.AL_FILTER_TYPE, EFX.AL_FILTER_BANDPASS); + EFX.alFilterf(INTERNAL_alFilter, EFX.AL_BANDPASS_GAINHF, hfGain); + EFX.alFilterf(INTERNAL_alFilter, EFX.AL_BANDPASS_GAINLF, lfGain); + AL10.alSourcei( + (source as OpenALSource).Handle, + EFX.AL_DIRECT_FILTER, + (int) INTERNAL_alFilter + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void QueueSourceBuffer(IALSource source, IALBuffer buffer) + { + uint buf = (buffer as OpenALBuffer).Handle; + AL10.alSourceQueueBuffers( + (source as OpenALSource).Handle, + (IntPtr) 1, + ref buf + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void DequeueSourceBuffers( + IALSource source, + int buffersToDequeue, + Queue errorCheck + ) { + uint[] bufs = new uint[buffersToDequeue]; + AL10.alSourceUnqueueBuffers( + (source as OpenALSource).Handle, + (IntPtr) buffersToDequeue, + bufs + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif +#if DEBUG + // Error check our queuedBuffers list. + IALBuffer[] sync = errorCheck.ToArray(); + for (int i = 0; i < buffersToDequeue; i += 1) + { + if (bufs[i] != (sync[i] as OpenALBuffer).Handle) + { + throw new Exception("Buffer desync!"); + } + } +#endif + } + + public int CheckProcessedBuffers(IALSource source) + { + int result; + AL10.alGetSourcei( + (source as OpenALSource).Handle, + AL10.AL_BUFFERS_PROCESSED, + out result + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + return result; + } + + public void GetBufferData( + IALSource source, + IALBuffer[] buffer, + float[] samples, + AudioChannels channels + ) { + int copySize1 = samples.Length / (int) channels; + int copySize2 = 0; + + // Where are we now? + int offset; + AL10.alGetSourcei( + (source as OpenALSource).Handle, + AL11.AL_SAMPLE_OFFSET, + out offset + ); + + // Is that longer than what the active buffer has left...? + uint buf = (buffer[0] as OpenALBuffer).Handle; + int len; + AL10.alGetBufferi( + buf, + AL10.AL_SIZE, + out len + ); + len /= 2; // FIXME: Assuming 16-bit! + len /= (int) channels; + if (offset > len) + { + copySize2 = copySize1; + copySize1 = 0; + offset -= len; + } + else if (offset + copySize1 > len) + { + copySize2 = copySize1 - (len - offset); + copySize1 = (len - offset); + } + + // Copy! + GCHandle handle = GCHandle.Alloc(samples, GCHandleType.Pinned); + if (copySize1 > 0) + { + ALEXT.alGetBufferSamplesSOFT( + buf, + offset, + copySize1, + channels == AudioChannels.Stereo ? + ALEXT.AL_STEREO_SOFT : + ALEXT.AL_MONO_SOFT, + ALEXT.AL_FLOAT_SOFT, + handle.AddrOfPinnedObject() + ); + offset = 0; + } + if (buffer.Length > 1 && copySize2 > 0) + { + ALEXT.alGetBufferSamplesSOFT( + (buffer[1] as OpenALBuffer).Handle, + 0, + copySize2, + channels == AudioChannels.Stereo ? + ALEXT.AL_STEREO_SOFT : + ALEXT.AL_MONO_SOFT, + ALEXT.AL_FLOAT_SOFT, + handle.AddrOfPinnedObject() + (copySize1 * (int) channels) + ); + } + handle.Free(); + } + + #endregion + + #region OpenAL Reverb Effect Methods + + public IALReverb GenReverb(DSPParameter[] parameters) + { + uint slot, effect; + EFX.alGenAuxiliaryEffectSlots((IntPtr) 1, out slot); + EFX.alGenEffects((IntPtr) 1, out effect); + // Set up the Reverb Effect + EFX.alEffecti( + effect, + EFX.AL_EFFECT_TYPE, + EFX.AL_EFFECT_EAXREVERB + ); + + IALReverb result = new OpenALReverb(slot, effect); + + // Apply initial values + SetReverbReflectionsDelay(result, parameters[0].Value); + SetReverbDelay(result, parameters[1].Value); + SetReverbPositionLeft(result, parameters[2].Value); + SetReverbPositionRight(result, parameters[3].Value); + SetReverbPositionLeftMatrix(result, parameters[4].Value); + SetReverbPositionRightMatrix(result, parameters[5].Value); + SetReverbEarlyDiffusion(result, parameters[6].Value); + SetReverbLateDiffusion(result, parameters[7].Value); + SetReverbLowEQGain(result, parameters[8].Value); + SetReverbLowEQCutoff(result, parameters[9].Value); + SetReverbHighEQGain(result, parameters[10].Value); + SetReverbHighEQCutoff(result, parameters[11].Value); + SetReverbRearDelay(result, parameters[12].Value); + SetReverbRoomFilterFrequency(result, parameters[13].Value); + SetReverbRoomFilterMain(result, parameters[14].Value); + SetReverbRoomFilterHighFrequency(result, parameters[15].Value); + SetReverbReflectionsGain(result, parameters[16].Value); + SetReverbGain(result, parameters[17].Value); + SetReverbDecayTime(result, parameters[18].Value); + SetReverbDensity(result, parameters[19].Value); + SetReverbRoomSize(result, parameters[20].Value); + SetReverbWetDryMix(result, parameters[21].Value); + + // Bind the Effect to the EffectSlot. XACT will use the EffectSlot. + EFX.alAuxiliaryEffectSloti( + slot, + EFX.AL_EFFECTSLOT_EFFECT, + (int) effect + ); + +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + return result; + } + + public void DeleteReverb(IALReverb reverb) + { + OpenALReverb rv = (reverb as OpenALReverb); + uint slot = rv.SlotHandle; + uint effect = rv.EffectHandle; + EFX.alDeleteAuxiliaryEffectSlots((IntPtr) 1, ref slot); + EFX.alDeleteEffects((IntPtr) 1, ref effect); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void CommitReverbChanges(IALReverb reverb) + { + OpenALReverb rv = (reverb as OpenALReverb); + EFX.alAuxiliaryEffectSloti( + rv.SlotHandle, + EFX.AL_EFFECTSLOT_EFFECT, + (int) rv.EffectHandle + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetReverbReflectionsDelay(IALReverb reverb, float value) + { + EFX.alEffectf( + (reverb as OpenALReverb).EffectHandle, + EFX.AL_EAXREVERB_REFLECTIONS_DELAY, + value / 1000.0f + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetReverbDelay(IALReverb reverb, float value) + { + EFX.alEffectf( + (reverb as OpenALReverb).EffectHandle, + EFX.AL_EAXREVERB_LATE_REVERB_DELAY, + value / 1000.0f + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetReverbPositionLeft(IALReverb reverb, float value) + { + // No known mapping :( + } + + public void SetReverbPositionRight(IALReverb reverb, float value) + { + // No known mapping :( + } + + public void SetReverbPositionLeftMatrix(IALReverb reverb, float value) + { + // No known mapping :( + } + + public void SetReverbPositionRightMatrix(IALReverb reverb, float value) + { + // No known mapping :( + } + + public void SetReverbEarlyDiffusion(IALReverb reverb, float value) + { + // Same as late diffusion, whatever... -flibit + EFX.alEffectf( + (reverb as OpenALReverb).EffectHandle, + EFX.AL_EAXREVERB_DIFFUSION, + value / 15.0f + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetReverbLateDiffusion(IALReverb reverb, float value) + { + // Same as early diffusion, whatever... -flibit + EFX.alEffectf( + (reverb as OpenALReverb).EffectHandle, + EFX.AL_EAXREVERB_DIFFUSION, + value / 15.0f + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetReverbLowEQGain(IALReverb reverb, float value) + { + // Cutting off volumes from 0db to 4db! -flibit + EFX.alEffectf( + (reverb as OpenALReverb).EffectHandle, + EFX.AL_EAXREVERB_GAINLF, + Math.Min( + XACTCalculator.CalculateAmplitudeRatio( + value - 8.0f + ), + 1.0f + ) + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetReverbLowEQCutoff(IALReverb reverb, float value) + { + EFX.alEffectf( + (reverb as OpenALReverb).EffectHandle, + EFX.AL_EAXREVERB_LFREFERENCE, + (value * 50.0f) + 50.0f + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetReverbHighEQGain(IALReverb reverb, float value) + { + EFX.alEffectf( + (reverb as OpenALReverb).EffectHandle, + EFX.AL_EAXREVERB_GAINHF, + XACTCalculator.CalculateAmplitudeRatio( + value - 8.0f + ) + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetReverbHighEQCutoff(IALReverb reverb, float value) + { + EFX.alEffectf( + (reverb as OpenALReverb).EffectHandle, + EFX.AL_EAXREVERB_HFREFERENCE, + (value * 500.0f) + 1000.0f + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetReverbRearDelay(IALReverb reverb, float value) + { + // No known mapping :( + } + + public void SetReverbRoomFilterFrequency(IALReverb reverb, float value) + { + // No known mapping :( + } + + public void SetReverbRoomFilterMain(IALReverb reverb, float value) + { + // No known mapping :( + } + + public void SetReverbRoomFilterHighFrequency(IALReverb reverb, float value) + { + // No known mapping :( + } + + public void SetReverbReflectionsGain(IALReverb reverb, float value) + { + // Cutting off possible float values above 3.16, for EFX -flibit + EFX.alEffectf( + (reverb as OpenALReverb).EffectHandle, + EFX.AL_EAXREVERB_REFLECTIONS_GAIN, + Math.Min( + XACTCalculator.CalculateAmplitudeRatio(value), + 3.16f + ) + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetReverbGain(IALReverb reverb, float value) + { + // Cutting off volumes from 0db to 20db! -flibit + EFX.alEffectf( + (reverb as OpenALReverb).EffectHandle, + EFX.AL_EAXREVERB_GAIN, + Math.Min( + XACTCalculator.CalculateAmplitudeRatio(value), + 1.0f + ) + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetReverbDecayTime(IALReverb reverb, float value) + { + /* FIXME: WTF is with this XACT value? + * XACT: 0-30 equal to 0.1-inf seconds?! + * EFX: 0.1-20 seconds + * -flibit + EFX.alEffectf( + (reverb as OpenALReverb).EffectHandle, + EFX.AL_EAXREVERB_GAIN, + value + ); + */ + } + + public void SetReverbDensity(IALReverb reverb, float value) + { + EFX.alEffectf( + (reverb as OpenALReverb).EffectHandle, + EFX.AL_EAXREVERB_DENSITY, + value / 100.0f + ); +#if VERBOSE_AL_DEBUGGING + CheckALError(); +#endif + } + + public void SetReverbRoomSize(IALReverb reverb, float value) + { + // No known mapping :( + } + + public void SetReverbWetDryMix(IALReverb reverb, float value) + { + /* FIXME: Note that were dividing by 200, not 100. + * For some ridiculous reason the mix is WAY too wet + * when we actually do the correct math, but cutting + * the ratio in half mysteriously makes it sound right. + * + * Or, well, "more" right. I'm sure we're still off. + * -flibit + */ + EFX.alAuxiliaryEffectSlotf( + (reverb as OpenALReverb).SlotHandle, + EFX.AL_EFFECTSLOT_GAIN, + value / 200.0f + ); + } + + #endregion + + #region OpenAL Capture Methods + + public IntPtr StartDeviceCapture(string name, int sampleRate, int bufSize) + { + IntPtr result = ALC11.alcCaptureOpenDevice( + name, + (uint) sampleRate, + AL10.AL_FORMAT_MONO16, + (IntPtr) bufSize + ); + ALC11.alcCaptureStart(result); +#if VERBOSE_AL_DEBUGGING + if (CheckALCError()) + { + throw new InvalidOperationException("AL device error!"); + } +#endif + return result; + } + + public void StopDeviceCapture(IntPtr handle) + { + ALC11.alcCaptureStop(handle); + ALC11.alcCaptureCloseDevice(handle); +#if VERBOSE_AL_DEBUGGING + if (CheckALCError()) + { + throw new InvalidOperationException("AL device error!"); + } +#endif + } + + public int CaptureSamples(IntPtr handle, IntPtr buffer, int count) + { + int[] samples = new int[1] { 0 }; + ALC10.alcGetIntegerv( + handle, + ALC11.ALC_CAPTURE_SAMPLES, + (IntPtr) 1, + samples + ); + samples[0] = Math.Min(samples[0], count / 2); + if (samples[0] > 0) + { + ALC11.alcCaptureSamples(handle, buffer, (IntPtr) samples[0]); + } +#if VERBOSE_AL_DEBUGGING + if (CheckALCError()) + { + throw new InvalidOperationException("AL device error!"); + } +#endif + return samples[0] * 2; + } + + public bool CaptureHasSamples(IntPtr handle) + { + int[] samples = new int[1] { 0 }; + ALC10.alcGetIntegerv( + handle, + ALC11.ALC_CAPTURE_SAMPLES, + (IntPtr) 1, + samples + ); + return samples[0] > 0; + } + + #endregion + + #region Private OpenAL Error Check Methods + + private void CheckALError() + { + int err = AL10.alGetError(); + + if (err == AL10.AL_NO_ERROR) + { + return; + } + + System.Console.WriteLine("OpenAL Error: {0:X}", err); +#if VERBOSE_AL_DEBUGGING + throw new InvalidOperationException("OpenAL Error!"); +#endif + } + + private bool CheckALCError() + { + int err = ALC10.alcGetError(alDevice); + + if (err == ALC10.ALC_NO_ERROR) + { + return false; + } + + System.Console.WriteLine("OpenAL Device Error: {0:X}", err); + return true; + } + + #endregion + + #region Private Static XNA->AL Dictionaries + + private static readonly int[] XNAToShort = new int[] + { + AL10.AL_NONE, // NOPE + AL10.AL_FORMAT_MONO16, // AudioChannels.Mono + AL10.AL_FORMAT_STEREO16, // AudioChannels.Stereo + }; + + private static readonly int[] XNAToFloat = new int[] + { + AL10.AL_NONE, // NOPE + ALEXT.AL_FORMAT_MONO_FLOAT32, // AudioChannels.Mono + ALEXT.AL_FORMAT_STEREO_FLOAT32 // AudioChannels.Stereo + }; + + #endregion + + #region OpenAL Device Enumerators + + public ReadOnlyCollection GetDevices() + { + IntPtr deviceList = ALC10.alcGetString(IntPtr.Zero, ALC11.ALC_ALL_DEVICES_SPECIFIER); + List renderers = new List(); + + int i = 0; + string curString = Marshal.PtrToStringAnsi(deviceList); + while (!String.IsNullOrEmpty(curString)) + { + renderers.Add(new RendererDetail( + curString, + i.ToString() + )); + i += 1; + deviceList += curString.Length + 1; + curString = Marshal.PtrToStringAnsi(deviceList); + } + + return new ReadOnlyCollection(renderers); + } + + public ReadOnlyCollection GetCaptureDevices() + { + IntPtr deviceList = ALC10.alcGetString(IntPtr.Zero, ALC11.ALC_CAPTURE_DEVICE_SPECIFIER); + List microphones = new List(); + + string curString = Marshal.PtrToStringAnsi(deviceList); + while (!String.IsNullOrEmpty(curString)) + { + microphones.Add(new Microphone(curString)); + deviceList += curString.Length + 1; + curString = Marshal.PtrToStringAnsi(deviceList); + } + + return new ReadOnlyCollection(microphones); + } + + #endregion + } +} diff --git a/src/Audio/RendererDetail.cs b/src/Audio/RendererDetail.cs new file mode 100644 index 0000000..f8da3b4 --- /dev/null +++ b/src/Audio/RendererDetail.cs @@ -0,0 +1,79 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + [Serializable] + public struct RendererDetail + { + #region Public Properties + + public string FriendlyName + { + get; + private set; + } + + public string RendererId + { + get; + private set; + } + + #endregion + + #region Internal Constructor + + internal RendererDetail(string name, string id) : this() + { + FriendlyName = name; + RendererId = id; + } + + #endregion + + #region Public Methods + + public override bool Equals(object obj) + { + return ( (obj is RendererDetail) && + RendererId.Equals(((RendererDetail) obj).RendererId) ); + } + + public override int GetHashCode() + { + return RendererId.GetHashCode(); + } + + public override string ToString() + { + return FriendlyName; + } + + #endregion + + #region Public Static Operator Overloads + + public static bool operator==(RendererDetail left, RendererDetail right) + { + return left.RendererId.Equals(right.RendererId); + } + + public static bool operator!=(RendererDetail left, RendererDetail right) + { + return !left.RendererId.Equals(right.RendererId); + } + + #endregion + } +} diff --git a/src/Audio/SoundBank.cs b/src/Audio/SoundBank.cs new file mode 100644 index 0000000..0c5ca35 --- /dev/null +++ b/src/Audio/SoundBank.cs @@ -0,0 +1,487 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +using System.IO; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + // http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.soundbank.aspx + public class SoundBank : IDisposable + { + #region Public Properties + + public bool IsDisposed + { + get; + private set; + } + + public bool IsInUse + { + get + { + throw new NotImplementedException("Bank Cue instance count tracking!"); + } + } + + #endregion + + #region Private Variables + + private AudioEngine INTERNAL_baseEngine; + + private List INTERNAL_waveBankNames; + private Dictionary INTERNAL_cueData; + + #endregion + + #region Disposing Event + + public event EventHandler Disposing; + + #endregion + + #region Public Constructor + + public SoundBank(AudioEngine audioEngine, string filename) + { + if (audioEngine == null) + { + throw new ArgumentNullException("audioEngine"); + } + if (String.IsNullOrEmpty(filename)) + { + throw new ArgumentNullException("filename"); + } + + INTERNAL_baseEngine = audioEngine; + + using (Stream soundBankStream = TitleContainer.OpenStream(filename)) + using (BinaryReader reader = new BinaryReader(soundBankStream)) + { + // Check the file header. Should be 'SDBK' + if (reader.ReadUInt32() != 0x4B424453) + { + throw new ArgumentException("SDBK format not recognized!"); + } + + // Check the content version. Assuming XNA4 Refresh. + if (reader.ReadUInt16() != AudioEngine.ContentVersion) + { + throw new ArgumentException("SDBK Content version!"); + } + + // Check the tool version. Assuming XNA4 Refresh. + if (reader.ReadUInt16() != 43) + { + throw new ArgumentException("SDBK Tool version!"); + } + + // CRC, unused + reader.ReadUInt16(); + + // Last modified, unused + reader.ReadUInt64(); + + // Unknown value, Internet suggests platform + reader.ReadByte(); + + // Cue Counts + ushort numCueSimple = reader.ReadUInt16(); + ushort numCueComplex = reader.ReadUInt16(); + + // Unknown value + reader.ReadUInt16(); + + // Total Cues, unused + reader.ReadUInt16(); + + // Number of associated WaveBanks + byte numWaveBanks = reader.ReadByte(); + + // Unknown, Internet suggest number of "sounds" + reader.ReadUInt16(); + + // Cue Name Table Length + ushort cueNameTableLength = reader.ReadUInt16(); + + // Unknown value + reader.ReadUInt16(); + + // Cue Offsets + uint cueSimpleOffset = reader.ReadUInt32(); + uint cueComplexOffset = reader.ReadUInt32(); + + // Cue Name Table Offset + uint cueNameTableOffset = reader.ReadUInt32(); + + // Unknown value + reader.ReadUInt32(); + + // Variable Tables Offset, unused + reader.ReadUInt32(); + + // Unknown value + reader.ReadUInt32(); + + // WaveBank Name Table Offset + uint waveBankNameTableOffset = reader.ReadUInt32(); + + // Cue Name Hash Offsets, unused + reader.ReadUInt32(); + reader.ReadUInt32(); + + // Unknown value, Internet suggest "sounds" offset + reader.ReadUInt32(); + + // SoundBank Name, unused + reader.ReadBytes(64); + + // Parse WaveBank names + soundBankStream.Seek(waveBankNameTableOffset, SeekOrigin.Begin); + INTERNAL_waveBankNames = new List(); + for (byte i = 0; i < numWaveBanks; i += 1) + { + INTERNAL_waveBankNames.Add( + System.Text.Encoding.UTF8.GetString( + reader.ReadBytes(64), 0, 64 + ).Replace("\0", "") + ); + } + + // Parse Cue name list + soundBankStream.Seek(cueNameTableOffset, SeekOrigin.Begin); + string[] cueNames = System.Text.Encoding.UTF8.GetString( + reader.ReadBytes(cueNameTableLength), + 0, + cueNameTableLength + ).Split('\0'); + + // Create our CueData Dictionary + INTERNAL_cueData = new Dictionary(); + + // Parse Simple Cues + soundBankStream.Seek(cueSimpleOffset, SeekOrigin.Begin); + for (ushort i = 0; i < numCueSimple; i += 1) + { + // Cue flags, unused + reader.ReadByte(); + + // Cue Sound Offset + uint offset = reader.ReadUInt32(); + + // Store this for when we're done reading the sound. + long curPos = reader.BaseStream.Position; + + // Go to the sound in the Bank. + reader.BaseStream.Seek(offset, SeekOrigin.Begin); + + // Parse the Sound + INTERNAL_cueData.Add( + cueNames[i], + new CueData(new XACTSound(reader)) + ); + + // Back to where we were... + reader.BaseStream.Seek(curPos, SeekOrigin.Begin); + } + + // Parse Complex Cues + soundBankStream.Seek(cueComplexOffset, SeekOrigin.Begin); + for (ushort i = 0; i < numCueComplex; i += 1) + { + // Cue flags + byte cueFlags = reader.ReadByte(); + + if ((cueFlags & 0x04) != 0) // FIXME: ??? + { + // Cue Sound Offset + uint offset = reader.ReadUInt32(); + + // Unknown value + reader.ReadUInt32(); + + // Store this for when we're done reading the sound. + long curPos = reader.BaseStream.Position; + + // Go to the sound in the bank + reader.BaseStream.Seek(offset, SeekOrigin.Begin); + + // Parse the Sound + INTERNAL_cueData.Add( + cueNames[numCueSimple + i], + new CueData(new XACTSound(reader)) + ); + + // Back to where we were... + reader.BaseStream.Seek(curPos, SeekOrigin.Begin); + } + else + { + // Variation Table Offset for this Cue + uint offset = reader.ReadUInt32(); + + // Transition Table Offset for this Cue, unused + reader.ReadUInt32(); + + // Store this for when we're done reading the Variation Table + long curPos = reader.BaseStream.Position; + + // Seek to the Variation Table in the file + reader.BaseStream.Seek(offset, SeekOrigin.Begin); + + // Number of Variations in the Table + ushort numVariations = reader.ReadUInt16(); + + // Variation Table Flags + ushort varTableFlags = reader.ReadUInt16(); + + // Unknown value + reader.ReadUInt16(); + + // Probability Control Variable, if applicable + ushort variable = reader.ReadUInt16(); + + // Create data for the CueData + XACTSound[] cueSounds = new XACTSound[numVariations]; + float[,] cueProbs = new float[numVariations, 2]; + + // Used to determine Variation storage format + int varTableType = (varTableFlags >> 3) & 0x0007; + + for (ushort j = 0; j < numVariations; j += 1) + { + if (varTableType == 0) + { + // Wave with byte min/max + ushort track = reader.ReadUInt16(); + byte waveBank = reader.ReadByte(); + byte wMin = reader.ReadByte(); + byte wMax = reader.ReadByte(); + + // Create the Sound + cueSounds[j] = new XACTSound(track, waveBank); + + // Calculate probability based on weight + cueProbs[j, 0] = wMax / 255.0f; + cueProbs[j, 1] = wMin / 255.0f; + } + else if (varTableType == 1) + { + // Complex with byte min/max + uint varOffset = reader.ReadUInt32(); + byte wMin = reader.ReadByte(); + byte wMax = reader.ReadByte(); + + // Store for sound read + long varPos = reader.BaseStream.Position; + + // Seek to the sound in the Bank + reader.BaseStream.Seek(varOffset, SeekOrigin.Begin); + + // Read the sound + cueSounds[j] = new XACTSound(reader); + + // Back to where we were... + reader.BaseStream.Seek(varPos, SeekOrigin.Begin); + + // Calculate probability based on weight + cueProbs[j, 0] = wMax / 255.0f; + cueProbs[j, 1] = wMin / 255.0f; + } + else if (varTableType == 3) + { + // Complex with float min/max + uint varOffset = reader.ReadUInt32(); + float wMin = reader.ReadSingle(); + float wMax = reader.ReadSingle(); + + // Unknown value + reader.ReadUInt32(); + + // Store for sound read + long varPos = reader.BaseStream.Position; + + // Seek to the sound in the Bank + reader.BaseStream.Seek(varOffset, SeekOrigin.Begin); + + // Read the sound + cueSounds[j] = new XACTSound(reader); + + // Back to where we were... + reader.BaseStream.Seek(varPos, SeekOrigin.Begin); + + // Calculate probability based on weight + cueProbs[j, 0] = wMax; + cueProbs[j, 1] = wMin; + } + else if (varTableType == 4) + { + // Compact Wave + ushort track = reader.ReadUInt16(); + byte waveBank = reader.ReadByte(); + + // Create the Sound + cueSounds[j] = new XACTSound(track, waveBank); + + // FIXME: Assume Sound weight is 100% + cueProbs[j, 0] = 1.0f; + cueProbs[j, 1] = 0.0f; + } + else + { + throw new NotSupportedException(); + } + } + + // Back to where we were... + reader.BaseStream.Seek(curPos, SeekOrigin.Begin); + + // Add Built CueData to Dictionary + INTERNAL_cueData.Add( + cueNames[numCueSimple + i], + new CueData( + cueSounds, + cueProbs, + (varTableType == 3) ? INTERNAL_baseEngine.INTERNAL_getVariableName(variable) : String.Empty + ) + ); + } + + // Cue instance limit + byte instanceLimit = reader.ReadByte(); + + // Fade In/Out + ushort fadeIn = reader.ReadUInt16(); + ushort fadeOut = reader.ReadUInt16(); + + // Cue max instance behavior + byte behavior = reader.ReadByte(); + + INTERNAL_cueData[cueNames[numCueSimple + i]].SetLimit( + instanceLimit, + behavior, + fadeIn, + fadeOut + ); + } + } + IsDisposed = false; + } + + #endregion + + #region Destructor + + ~SoundBank() + { + Dispose(true); + } + + #endregion + + #region Public Dispose Method + + public void Dispose() + { + Dispose(false); + } + + #endregion + + #region Protected Dispose Method + + protected void Dispose(bool disposing) + { + if (!IsDisposed) + { + if (Disposing != null) + { + Disposing.Invoke(this, null); + } + INTERNAL_waveBankNames.Clear(); + INTERNAL_cueData.Clear(); + IsDisposed = true; + } + } + + #endregion + + #region Public Methods + + public Cue GetCue(string name) + { + if (String.IsNullOrEmpty(name)) + { + throw new ArgumentNullException("name"); + } + if (!INTERNAL_cueData.ContainsKey(name)) + { + throw new ArgumentException("Cue name not found: " + name); + } + return new Cue( + INTERNAL_baseEngine, + INTERNAL_waveBankNames, + name, + INTERNAL_cueData[name], + false + ); + } + + public void PlayCue(string name) + { + if (String.IsNullOrEmpty(name)) + { + throw new ArgumentNullException("name"); + } + if (!INTERNAL_cueData.ContainsKey(name)) + { + throw new InvalidOperationException("name not found!"); + } + Cue newCue = new Cue( + INTERNAL_baseEngine, + INTERNAL_waveBankNames, + name, + INTERNAL_cueData[name], + true + ); + newCue.Play(); + } + + public void PlayCue( + string name, + AudioListener listener, + AudioEmitter emitter + ) { + if (String.IsNullOrEmpty(name)) + { + throw new ArgumentNullException("name"); + } + if (!INTERNAL_cueData.ContainsKey(name)) + { + throw new InvalidOperationException("name not found!"); + } + Cue newCue = new Cue( + INTERNAL_baseEngine, + INTERNAL_waveBankNames, + name, + INTERNAL_cueData[name], + true + ); + newCue.Apply3D(listener, emitter); + newCue.Play(); + } + + #endregion + } +} diff --git a/src/Audio/SoundEffect.cs b/src/Audio/SoundEffect.cs new file mode 100644 index 0000000..72128f0 --- /dev/null +++ b/src/Audio/SoundEffect.cs @@ -0,0 +1,408 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.IO; +using System.Collections.Generic; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + // http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.soundeffect.aspx + public sealed class SoundEffect : IDisposable + { + #region Public Properties + + public TimeSpan Duration + { + get + { + return INTERNAL_buffer.Duration; + } + } + + public bool IsDisposed + { + get; + private set; + } + + public string Name + { + get; + set; + } + + #endregion + + #region Public Static Properties + + // FIXME: This should affect all sounds! alListener? -flibit + private static float INTERNAL_masterVolume = 1.0f; + public static float MasterVolume + { + get + { + return INTERNAL_masterVolume; + } + set + { + INTERNAL_masterVolume = value; + } + } + + // FIXME: How does this affect OpenAL? -flibit + private static float INTERNAL_distanceScale = 1.0f; + public static float DistanceScale + { + get + { + return INTERNAL_distanceScale; + } + set + { + if (value <= 0.0f) + { + throw new ArgumentOutOfRangeException("value of DistanceScale"); + } + INTERNAL_distanceScale = value; + } + } + + // FIXME: How does this affect OpenAL? -flibit + private static float INTERNAL_dopplerScale = 1.0f; + public static float DopplerScale + { + get + { + return INTERNAL_dopplerScale; + } + set + { + if (value <= 0.0f) + { + throw new ArgumentOutOfRangeException("value of DopplerScale"); + } + INTERNAL_dopplerScale = value; + } + } + + // FIXME: How does this affect OpenAL? -flibit + private static float INTERNAL_speedOfSound = 343.5f; + public static float SpeedOfSound + { + get + { + return INTERNAL_speedOfSound; + } + set + { + INTERNAL_speedOfSound = value; + } + } + + #endregion + + #region Internal Variables + + internal List Instances = new List(); + internal IALBuffer INTERNAL_buffer; + + #endregion + + #region Public Constructors + + public SoundEffect( + byte[] buffer, + int sampleRate, + AudioChannels channels + ) { + INTERNAL_buffer = AudioDevice.GenBuffer( + buffer, + (uint) sampleRate, + (uint) channels, + 0, + 0, + false, + 1 + ); + } + + public SoundEffect( + byte[] buffer, + int offset, + int count, + int sampleRate, + AudioChannels channels, + int loopStart, + int loopLength + ) { + byte[] sendBuf; + if (offset != 0 || count != buffer.Length) + { + // I kind of hate this. -flibit + sendBuf = new byte[count]; + Array.Copy(buffer, offset, sendBuf, 0, count); + } + else + { + sendBuf = buffer; + } + + INTERNAL_buffer = AudioDevice.GenBuffer( + sendBuf, + (uint) sampleRate, + (uint) channels, + (uint) loopStart, + (uint) (loopStart + loopLength), + false, + 1 + ); + } + + #endregion + + #region Internal Constructors + + internal SoundEffect(Stream s) + { + INTERNAL_loadAudioStream(s); + } + + internal SoundEffect( + string name, + byte[] buffer, + uint sampleRate, + uint channels, + uint loopStart, + uint loopLength, + bool isADPCM, + uint formatParameter + ) { + Name = name; + INTERNAL_buffer = AudioDevice.GenBuffer( + buffer, + sampleRate, + channels, + loopStart, + loopStart + loopLength, + isADPCM, + formatParameter + ); + } + + #endregion + + #region Destructor + + ~SoundEffect() + { + Dispose(); + } + + #endregion + + #region Public Dispose Method + + public void Dispose() + { + if (!IsDisposed) + { + /* FIXME: Is it ironic that we're generating + * garbage with ToArray while cleaning up after + * the program's leaks? + * -flibit + */ + foreach (WeakReference instance in Instances.ToArray()) + { + object target = instance.Target; + if (target != null) + { + (target as IDisposable).Dispose(); + } + } + Instances.Clear(); + if (INTERNAL_buffer != null) + { + AudioDevice.ALDevice.DeleteBuffer(INTERNAL_buffer); + } + IsDisposed = true; + } + } + + #endregion + + #region Additional SoundEffect/SoundEffectInstance Creation Methods + + public SoundEffectInstance CreateInstance() + { + return new SoundEffectInstance(this); + } + + public static SoundEffect FromStream(Stream stream) + { + return new SoundEffect(stream); + } + + #endregion + + #region Public Play Methods + + public bool Play() + { + // FIXME: Perhaps MasterVolume should be applied to alListener? -flibit + return Play(MasterVolume, 0.0f, 0.0f); + } + + public bool Play(float volume, float pitch, float pan) + { + SoundEffectInstance instance = CreateInstance(); + instance.Volume = volume; + instance.Pitch = pitch; + instance.Pan = pan; + instance.Play(); + if (instance.State != SoundState.Playing) + { + // Ran out of AL sources, probably. + instance.Dispose(); + return false; + } + AudioDevice.InstancePool.Add(instance); + return true; + } + + #endregion + + #region Private WAV Loading Method + + private void INTERNAL_loadAudioStream(Stream s) + { + byte[] data; + uint sampleRate = 0; + uint numChannels = 0; + bool isADPCM = false; + uint formatParameter = 0; + + using (BinaryReader reader = new BinaryReader(s)) + { + // RIFF Signature + string signature = new string(reader.ReadChars(4)); + if (signature != "RIFF") + { + throw new NotSupportedException("Specified stream is not a wave file."); + } + + reader.ReadUInt32(); // Riff Chunk Size + + string wformat = new string(reader.ReadChars(4)); + if (wformat != "WAVE") + { + throw new NotSupportedException("Specified stream is not a wave file."); + } + + // WAVE Header + string format_signature = new string(reader.ReadChars(4)); + while (format_signature != "fmt ") + { + reader.ReadBytes(reader.ReadInt32()); + format_signature = new string(reader.ReadChars(4)); + } + + int format_chunk_size = reader.ReadInt32(); + + // Header Information + uint audio_format = reader.ReadUInt16(); // 2 + numChannels = reader.ReadUInt16(); // 4 + sampleRate = reader.ReadUInt32(); // 8 + reader.ReadUInt32(); // 12, Byte Rate + ushort blockAlign = reader.ReadUInt16(); // 14, Block Align + ushort bitDepth = reader.ReadUInt16(); // 16, Bits Per Sample + + if (audio_format == 1) + { + System.Diagnostics.Debug.Assert(bitDepth == 8 || bitDepth == 16); + formatParameter = (uint) (bitDepth / 16); // 1 for 16, 0 for 8 + } + else if (audio_format != 2) + { + isADPCM = true; + formatParameter = (((blockAlign / numChannels) - 6) * 2); + } + else + { + throw new NotSupportedException("Wave format is not supported."); + } + + // Reads residual bytes + if (format_chunk_size > 16) + { + reader.ReadBytes(format_chunk_size - 16); + } + + // data Signature + string data_signature = new string(reader.ReadChars(4)); + while (data_signature.ToLowerInvariant() != "data") + { + reader.ReadBytes(reader.ReadInt32()); + data_signature = new string(reader.ReadChars(4)); + } + if (data_signature != "data") + { + throw new NotSupportedException("Specified wave file is not supported."); + } + + int waveDataLength = reader.ReadInt32(); + data = reader.ReadBytes(waveDataLength); + } + + INTERNAL_buffer = AudioDevice.GenBuffer( + data, + sampleRate, + numChannels, + 0, + 0, + isADPCM, + formatParameter + ); + } + + #endregion + + #region Public Static Methods + + public static TimeSpan GetSampleDuration( + int sizeInBytes, + int sampleRate, + AudioChannels channels + ) { + sizeInBytes /= 2; // 16-bit PCM! + int ms = (int) ( + (sizeInBytes / (int) channels) / + (sampleRate / 1000.0f) + ); + return new TimeSpan(0, 0, 0, 0, ms); + } + + public static int GetSampleSizeInBytes( + TimeSpan duration, + int sampleRate, + AudioChannels channels + ) { + return (int) ( + duration.TotalSeconds * + sampleRate * + (int) channels * + 2 // 16-bit PCM! + ); + } + + #endregion + } +} diff --git a/src/Audio/SoundEffectInstance.cs b/src/Audio/SoundEffectInstance.cs new file mode 100644 index 0000000..9dfb26a --- /dev/null +++ b/src/Audio/SoundEffectInstance.cs @@ -0,0 +1,388 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + // http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.soundeffectinstance.aspx + public class SoundEffectInstance : IDisposable + { + #region Public Properties + + public bool IsDisposed + { + get; + protected set; + } + + private bool INTERNAL_looped = false; + public virtual bool IsLooped + { + get + { + return INTERNAL_looped; + } + set + { + INTERNAL_looped = value; + if (INTERNAL_alSource != null) + { + AudioDevice.ALDevice.SetSourceLooped( + INTERNAL_alSource, + value + ); + } + } + } + + private float INTERNAL_pan = 0.0f; + public float Pan + { + get + { + return INTERNAL_pan; + } + set + { + INTERNAL_pan = value; + if (INTERNAL_alSource != null) + { + AudioDevice.ALDevice.SetSourcePan( + INTERNAL_alSource, + value + ); + } + } + } + + private float INTERNAL_pitch = 0f; + public float Pitch + { + get + { + return INTERNAL_pitch; + } + set + { + INTERNAL_pitch = value; + if (INTERNAL_alSource != null) + { + AudioDevice.ALDevice.SetSourcePitch( + INTERNAL_alSource, + value, + !INTERNAL_isXACTSource + ); + } + } + } + + public SoundState State + { + get + { + if (INTERNAL_alSource == null) + { + return SoundState.Stopped; + } + SoundState result = AudioDevice.ALDevice.GetSourceState( + INTERNAL_alSource + ); + if (result == SoundState.Stopped && isDynamic) + { + // Force playing at all times for DSFI! + return SoundState.Playing; + } + return result; + } + } + + private float INTERNAL_volume = 1.0f; + public float Volume + { + get + { + return INTERNAL_volume; + } + set + { + INTERNAL_volume = value; + if (INTERNAL_alSource != null) + { + AudioDevice.ALDevice.SetSourceVolume( + INTERNAL_alSource, + value + ); + } + } + } + + #endregion + + #region Internal Variables: XACT Filters + + internal byte FilterType; + + #endregion + + #region Private Variables: XNA Implementation + + private SoundEffect INTERNAL_parentEffect; + private WeakReference selfReference; + + internal bool isDynamic; + + /* FNA' XACT runtime wraps around SoundEffect for audio output. + * Only problem: XACT pitch has no boundaries, SoundEffect does. + * So, we're going to use this to tell the pitch clamp to STFU. + * -flibit + */ + internal bool INTERNAL_isXACTSource = false; + + #endregion + + #region Private Variables: AL Source, EffectSlot + + internal IALSource INTERNAL_alSource; + private IALReverb INTERNAL_alReverb; + + #endregion + + #region Private Variables: 3D Audio + + protected Vector3 position = new Vector3(0.0f, 0.0f, 0.1f); + + // Used to prevent outdated positional audio data from being used + protected bool INTERNAL_positionalAudio = false; + + #endregion + + #region Internal Constructor + + internal SoundEffectInstance(SoundEffect parent) + { + INTERNAL_parentEffect = parent; + if (INTERNAL_parentEffect != null) + { + selfReference = new WeakReference(this); + INTERNAL_parentEffect.Instances.Add(selfReference); + } + isDynamic = false; + } + + #endregion + + #region Destructor + + ~SoundEffectInstance() + { + Dispose(); + } + + #endregion + + #region Public Dispose Method + + public virtual void Dispose() + { + if (!IsDisposed) + { + Stop(true); + if (INTERNAL_parentEffect != null) + { + INTERNAL_parentEffect.Instances.Remove(selfReference); + selfReference = null; + } + IsDisposed = true; + } + } + + #endregion + + #region Public 3D Audio Methods + + public void Apply3D(AudioListener listener, AudioEmitter emitter) + { + if (INTERNAL_alSource == null) + { + return; + } + + // Set up orientation matrix + Matrix orientation = Matrix.CreateWorld(Vector3.Zero, listener.Forward, listener.Up); + + // Set up our final position according to orientation of listener + position = Vector3.Transform(emitter.Position - listener.Position, orientation); + if (position != Vector3.Zero) + { + position.Normalize(); + } + + // Set the position based on relative positon + AudioDevice.ALDevice.SetSourcePosition( + INTERNAL_alSource, + position + ); + + // We positional now + INTERNAL_positionalAudio = true; + } + + public void Apply3D(AudioListener[] listeners, AudioEmitter emitter) + { + throw new NotSupportedException("OpenAL can only make use of one listener."); + } + + #endregion + + #region Public Playback Methods + + public virtual void Play() + { + if (State != SoundState.Stopped) + { + return; + } + + if (INTERNAL_alSource != null) + { + // The sound has stopped, but hasn't cleaned up yet... + AudioDevice.ALDevice.StopAndDisposeSource(INTERNAL_alSource); + INTERNAL_alSource = null; + } + + INTERNAL_alSource = AudioDevice.ALDevice.GenSource( + INTERNAL_parentEffect.INTERNAL_buffer + ); + if (INTERNAL_alSource == null) + { + System.Console.WriteLine("WARNING: AL SOURCE WAS NOT AVAILABLE. SKIPPING."); + return; + } + + // Apply Pan/Position + if (INTERNAL_positionalAudio) + { + INTERNAL_positionalAudio = false; + AudioDevice.ALDevice.SetSourcePosition( + INTERNAL_alSource, + position + ); + } + else + { + Pan = Pan; + } + + // Reassign Properties, in case the AL properties need to be applied. + Volume = Volume; + IsLooped = IsLooped; + Pitch = Pitch; + + // Apply EFX + if (INTERNAL_alReverb != null) + { + AudioDevice.ALDevice.SetSourceReverb( + INTERNAL_alSource, + INTERNAL_alReverb + ); + } + + AudioDevice.ALDevice.PlaySource(INTERNAL_alSource); + } + + public void Pause() + { + if (INTERNAL_alSource != null && State == SoundState.Playing) + { + AudioDevice.ALDevice.PauseSource(INTERNAL_alSource); + } + } + + public void Resume() + { + if (INTERNAL_alSource == null) + { + // XNA4 just plays if we've not started yet. + Play(); + } + else if (State == SoundState.Paused) + { + AudioDevice.ALDevice.ResumeSource(INTERNAL_alSource); + } + } + + public void Stop() + { + if (INTERNAL_alSource != null) + { + // TODO: GraphicsResource-like reference management -flibit + if (AudioDevice.ALDevice != null) + { + AudioDevice.ALDevice.StopAndDisposeSource(INTERNAL_alSource); + DynamicSoundEffectInstance dsfi = this as DynamicSoundEffectInstance; + if (dsfi != null && AudioDevice.DynamicInstancePool.Contains(dsfi)) + { + AudioDevice.DynamicInstancePool.Remove(dsfi); + } + } + INTERNAL_alSource = null; + } + } + + public void Stop(bool immediate) + { + Stop(); + } + + #endregion + + #region Internal Effects Methods + + internal void INTERNAL_applyReverb(IALReverb reverb) + { + INTERNAL_alReverb = reverb; + if (INTERNAL_alSource != null) + { + AudioDevice.ALDevice.SetSourceReverb( + INTERNAL_alSource, + INTERNAL_alReverb + ); + } + } + + internal void INTERNAL_applyLowPassFilter(float hfGain) + { + if (INTERNAL_alSource != null) + { + AudioDevice.ALDevice.SetSourceLowPassFilter(INTERNAL_alSource, hfGain); + } + } + + internal void INTERNAL_applyHighPassFilter(float lfGain) + { + if (INTERNAL_alSource != null) + { + AudioDevice.ALDevice.SetSourceHighPassFilter(INTERNAL_alSource, lfGain); + } + } + + internal void INTERNAL_applyBandPassFilter(float hfGain, float lfGain) + { + if (INTERNAL_alSource != null) + { + AudioDevice.ALDevice.SetSourceBandPassFilter(INTERNAL_alSource, hfGain, lfGain); + } + } + + #endregion + } +} diff --git a/src/Audio/SoundState.cs b/src/Audio/SoundState.cs new file mode 100644 index 0000000..e9ba1e1 --- /dev/null +++ b/src/Audio/SoundState.cs @@ -0,0 +1,19 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + // http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.soundstate.aspx + public enum SoundState + { + Playing, + Paused, + Stopped + } +} diff --git a/src/Audio/WaveBank.cs b/src/Audio/WaveBank.cs new file mode 100644 index 0000000..e3d3079 --- /dev/null +++ b/src/Audio/WaveBank.cs @@ -0,0 +1,529 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* The unxwb project, written by Luigi Auriemma, was released in 2006 under the + * GNU General Public License, version 2.0: + * + * http://www.gnu.org/licenses/gpl-2.0.html + * + * While the unxwb project was released under the GPL, Luigi has given express + * permission to the MonoGame project to use code from unxwb under the MonoGame + * project license. See LICENSE for details. + * + * The unxwb website can be found here: + * + * http://aluigi.altervista.org/papers.htm#xbox + */ +#endregion + +#region Using Statements +using System; +using System.IO; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + // http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.wavebank.aspx + public class WaveBank : IDisposable + { + #region Private Sound Entry Container Class + + // Used to store sound entry data, mainly for streaming WaveBanks + private class SoundStreamEntry + { + public uint PlayOffset + { + get; + private set; + } + + public uint PlayLength + { + get; + private set; + } + + public uint Codec + { + get; + private set; + } + + public uint Frequency + { + get; + private set; + } + + public uint Channels + { + get; + private set; + } + + public uint LoopOffset + { + get; + private set; + } + + public uint LoopLength + { + get; + private set; + } + + public uint Alignment + { + get; + private set; + } + + public uint BitDepth + { + get; + private set; + } + + public SoundStreamEntry( + uint playOffset, + uint playLength, + uint codec, + uint frequency, + uint channels, + uint loopOffset, + uint loopLength, + uint alignment, + uint bitDepth + ) { + PlayOffset = playOffset; + PlayLength = playLength; + Codec = codec; + Frequency = frequency; + Channels = channels; + LoopOffset = loopOffset; + LoopLength = loopLength; + Alignment = alignment; + BitDepth = bitDepth; + } + } + + #endregion + + #region Public Properties + + public bool IsDisposed + { + get; + private set; + } + + public bool IsPrepared + { + get; + private set; + } + + public bool IsInUse + { + get + { + throw new NotImplementedException("Cue wave entry dependency tracking!"); + } + } + + #endregion + + #region Private Variables + + // We keep this in order to Dispose ourselves later. + private AudioEngine INTERNAL_baseEngine; + private string INTERNAL_name; + + // These are only used for streaming WaveBanks + private BinaryReader INTERNAL_waveBankReader; + private SoundStreamEntry[] INTERNAL_soundStreamEntries; + + // Stores the actual wavedata + private SoundEffect[] INTERNAL_sounds; + + #endregion + + #region Disposing Event + + public event EventHandler Disposing; + + #endregion + + #region Public Constructors + + public WaveBank( + AudioEngine audioEngine, + string nonStreamingWaveBankFilename + ) { + if (audioEngine == null) + { + throw new ArgumentNullException("audioEngine"); + } + if (String.IsNullOrEmpty(nonStreamingWaveBankFilename)) + { + throw new ArgumentNullException("nonStreamingWaveBankFilename"); + } + + using (Stream stream = TitleContainer.OpenStream(nonStreamingWaveBankFilename)) + using (BinaryReader reader = new BinaryReader(stream)) + { + LoadWaveBank(audioEngine, reader, false); + } + } + + public WaveBank( + AudioEngine audioEngine, + string streamingWaveBankFilename, + int offset, + short packetsize + ) { + /* Note that offset and packetsize go unused, + * because we're frauds and aren't actually streaming. + * -flibit + */ + + if (audioEngine == null) + { + throw new ArgumentNullException("audioEngine"); + } + if (String.IsNullOrEmpty(streamingWaveBankFilename)) + { + throw new ArgumentNullException("streamingWaveBankFilename"); + } + + INTERNAL_waveBankReader = new BinaryReader( + TitleContainer.OpenStream(streamingWaveBankFilename) + ); + LoadWaveBank(audioEngine, INTERNAL_waveBankReader, true); + } + + #endregion + + #region Destructor + + ~WaveBank() + { + Dispose(true); + } + + #endregion + + #region Public Dispose Method + + public void Dispose() + { + Dispose(false); + } + + #endregion + + #region Protected Dispose Method + + protected virtual void Dispose(bool disposing) + { + if (!IsDisposed) + { + if (Disposing != null) + { + Disposing.Invoke(this, null); + } + foreach (SoundEffect se in INTERNAL_sounds) + { + if (se != null) + { + se.Dispose(); + } + } + INTERNAL_baseEngine.INTERNAL_removeWaveBank(INTERNAL_name); + INTERNAL_sounds = null; + if (INTERNAL_waveBankReader != null) + { + INTERNAL_waveBankReader.Close(); + INTERNAL_waveBankReader = null; + } + IsDisposed = true; + IsPrepared = false; + } + } + + #endregion + + #region Internal Method + + internal SoundEffect INTERNAL_getTrack(ushort track) + { + if (INTERNAL_sounds[track] == null) + { + LoadWaveEntry( + INTERNAL_soundStreamEntries[track], + track, + INTERNAL_waveBankReader + ); + } + return INTERNAL_sounds[track]; + } + + #endregion + + #region Private WaveBank Load Method + + private void LoadWaveBank(AudioEngine audioEngine, BinaryReader reader, bool streaming) + { + /* Until we finish the LoadWaveBank process, this WaveBank is NOT + * ready to run. For us this doesn't really matter, but the game + * could be loading WaveBanks asynchronously, so let's be careful. + * -flibit + */ + IsPrepared = false; + + INTERNAL_baseEngine = audioEngine; + + // Check the file header. Should be 'WBND' + if (reader.ReadUInt32() != 0x444E4257) + { + throw new ArgumentException("WBND format not recognized!"); + } + + // Check the content version. Assuming XNA4 Refresh. + if (reader.ReadUInt32() != AudioEngine.ContentVersion) + { + throw new ArgumentException("WBND Content version!"); + } + + // Check the tool version. Assuming XNA4 Refresh. + if (reader.ReadUInt32() != 44) + { + throw new ArgumentException("WBND Tool version!"); + } + + // Obtain WaveBank chunk offsets/lengths + uint[] offsets = new uint[5]; + uint[] lengths = new uint[5]; + for (int i = 0; i < 5; i += 1) + { + offsets[i] = reader.ReadUInt32(); + lengths[i] = reader.ReadUInt32(); + } + + // Seek to the first offset, obtain WaveBank info + reader.BaseStream.Seek(offsets[0], SeekOrigin.Begin); + + // IsStreaming bool, unused + reader.ReadUInt16(); + + // WaveBank Flags + ushort wavebankFlags = reader.ReadUInt16(); + // bool containsEntryNames = (wavebankFlags & 0x0001) != 0; + bool compact = (wavebankFlags & 0x0002) != 0; + // bool syncDisabled = (wavebankFlags & 0x0004) != 0; + // bool containsSeekTables = (wavebankFlags & 0x0008) != 0; + + // WaveBank Entry Count + uint numEntries = reader.ReadUInt32(); + + // WaveBank Name + INTERNAL_name = System.Text.Encoding.UTF8.GetString( + reader.ReadBytes(64), 0, 64 + ).Replace("\0", ""); + + // WaveBank entry information + uint metadataElementSize = reader.ReadUInt32(); + reader.ReadUInt32(); // nameElementSize + uint alignment = reader.ReadUInt32(); + + // Determine the generic play region offset + uint playRegionOffset = offsets[4]; + if (playRegionOffset == 0) + { + playRegionOffset = offsets[1] + (numEntries * metadataElementSize); + } + + // Entry format. Read early for Compact data + uint entryFormat = 0; + if (compact) + { + entryFormat = reader.ReadUInt32(); + } + + // Read in the wavedata + INTERNAL_sounds = new SoundEffect[numEntries]; + if (streaming) + { + INTERNAL_soundStreamEntries = new SoundStreamEntry[numEntries]; + } + uint curOffset = offsets[1]; + for (int curEntry = 0; curEntry < numEntries; curEntry += 1) + { + // Seek to the current entry + reader.BaseStream.Seek(curOffset, SeekOrigin.Begin); + + // Entry Information + uint entryPlayOffset = 0; + uint entryPlayLength = 0; + uint entryLoopOffset = 0; + uint entryLoopLength = 0; + + // Obtain Entry Information + if (compact) + { + uint entryLength = reader.ReadUInt32(); + + entryPlayOffset = + (entryLength & ((1 << 21) - 1)) * + alignment; + entryPlayLength = + (entryLength >> 21) & ((1 << 11) - 1); + + // FIXME: Deviation Length + reader.BaseStream.Seek( + curOffset + metadataElementSize, + SeekOrigin.Begin + ); + + if (curEntry == (numEntries - 1)) + { + // Last track, last length. + entryLength = lengths[4]; + } + else + { + entryLength = ( + ( + reader.ReadUInt32() & + ((1 << 21) - 1) + ) * alignment + ); + } + entryPlayLength = entryLength - entryPlayOffset; + } + else + { + if (metadataElementSize >= 4) + reader.ReadUInt32(); // Flags/Duration, unused + if (metadataElementSize >= 8) + entryFormat = reader.ReadUInt32(); + if (metadataElementSize >= 12) + entryPlayOffset = reader.ReadUInt32(); + if (metadataElementSize >= 16) + entryPlayLength = reader.ReadUInt32(); + if (metadataElementSize >= 20) + entryLoopOffset = reader.ReadUInt32(); + if (metadataElementSize >= 24) + entryLoopLength = reader.ReadUInt32(); + else + { + // FIXME: This is a bit hacky. + if (entryPlayLength != 0) + { + entryPlayLength = lengths[4]; + } + } + } + + // Update seek offsets + curOffset += metadataElementSize; + entryPlayOffset += playRegionOffset; + + // Parse Format for Wavedata information + uint entryCodec = (entryFormat >> 0) & ((1 << 2) - 1); + uint entryChannels = (entryFormat >> 2) & ((1 << 3) - 1); + uint entryFrequency = (entryFormat >> (2 + 3)) & ((1 << 18) - 1); + uint entryAlignment = (entryFormat >> (2 + 3 + 18)) & ((1 << 8) - 1); + uint entryBitDepth = (entryFormat >> (2 + 3 + 18 + 8)); + + if (streaming) + { + INTERNAL_soundStreamEntries[curEntry] = new SoundStreamEntry( + entryPlayOffset, + entryPlayLength, + entryCodec, + entryFrequency, + entryChannels, + entryLoopOffset, + entryLoopLength, + entryAlignment, + entryBitDepth + ); + } + else + { + SoundStreamEntry filler = new SoundStreamEntry( + entryPlayOffset, + entryPlayLength, + entryCodec, + entryFrequency, + entryChannels, + entryLoopOffset, + entryLoopLength, + entryAlignment, + entryBitDepth + ); + LoadWaveEntry(filler, (ushort) curEntry, reader); + } + } + + // Add this WaveBank to the AudioEngine Dictionary + audioEngine.INTERNAL_addWaveBank(INTERNAL_name, this); + + // Finally. + IsDisposed = false; + IsPrepared = true; + } + + #endregion + + #region Private WaveBank Entry Load Method + + private void LoadWaveEntry(SoundStreamEntry entry, ushort track, BinaryReader reader) + { + // Read Wavedata + reader.BaseStream.Seek(entry.PlayOffset, SeekOrigin.Begin); + byte[] entryData = reader.ReadBytes((int) entry.PlayLength); + + // Load SoundEffect based on codec + if (entry.Codec == 0x0) // PCM + { + INTERNAL_sounds[track] = new SoundEffect( + "WaveBank Sound", + entryData, + entry.Frequency, + entry.Channels, + entry.LoopOffset, + entry.LoopLength, + false, + entry.BitDepth + ); + } + else if (entry.Codec == 0x2) // ADPCM + { + INTERNAL_sounds[track] = new SoundEffect( + "WaveBank Sound", + entryData, + entry.Frequency, + entry.Channels, + entry.LoopOffset, + entry.LoopLength, + true, + (entry.Alignment + 16) * 2 + ); + } + else // Includes 0x1 - XMA, 0x3 - WMA + { + throw new NotSupportedException("Rebuild your WaveBanks with ADPCM!"); + } + } + + #endregion + } +} diff --git a/src/Audio/XACTInternal.cs b/src/Audio/XACTInternal.cs new file mode 100644 index 0000000..4677ef3 --- /dev/null +++ b/src/Audio/XACTInternal.cs @@ -0,0 +1,466 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +#endregion + +namespace Microsoft.Xna.Framework.Audio +{ + internal static class XACTCalculator + { + public static double ParseDecibel(byte binaryValue) + { + /* FIXME: This calculation probably came from someone's TI-83. + * I plotted out Codename Naddachance's bytes out, and + * the closest formula I could come up with (hastily) + * was this: + * dBValue = 37.5 * Math.Log10(binaryValue * 2.0) - 96.0 + * But of course, volumes are still wrong. So I dunno. + * -flibit + */ + return ( + (-96.0 - 67.7385212334047) / + (1 + Math.Pow( + binaryValue / 80.1748600297963, + 0.432254984608615 + )) + ) + 67.7385212334047; + } + + public static float CalculateAmplitudeRatio(double decibel) + { + return (float) Math.Pow(10, decibel / 20.0); + } + + public static float CalculateVolume(byte binaryValue) + { + return CalculateAmplitudeRatio(ParseDecibel(binaryValue)); + } + } + + internal enum MaxInstanceBehavior : byte + { + Fail, + Queue, + ReplaceOldest, + ReplaceQuietest, + ReplaceLowestPriority + } + + internal enum CrossfadeType : byte + { + Linear, + Logarithmic, + EqualPower + } + + internal class Variable + { + public string Name + { + get; + private set; + } + + // Variable Accessibility + public bool IsPublic + { + get; + private set; + } + + public bool IsReadOnly + { + get; + private set; + } + + public bool IsGlobal + { + get; + private set; + } + + public bool IsReserved + { + get; + private set; + } + + // Variable Value, Boundaries + private float value; + private float minValue; + private float maxValue; + + public Variable( + string name, + bool varIsPublic, + bool varIsReadOnly, + bool varIsGlobal, + bool varIsReserved, + float varInitialValue, + float varMinValue, + float varMaxValue + ) { + Name = name; + IsPublic = varIsPublic; + IsReadOnly = varIsReadOnly; + IsGlobal = varIsGlobal; + IsReserved = varIsReserved; + value = varInitialValue; + minValue = varMinValue; + maxValue = varMaxValue; + } + + public void SetValue(float newValue) + { + if (newValue < minValue) + { + value = minValue; + } + else if (newValue > maxValue) + { + value = maxValue; + } + else + { + value = newValue; + } + } + + public float GetValue() + { + return value; + } + + public Variable Clone() + { + return new Variable( + Name, + IsPublic, + IsReadOnly, + IsGlobal, + IsReserved, + value, + minValue, + maxValue + ); + } + } + + internal enum RPCPointType : byte + { + Linear, + Fast, + Slow, + SinCos + } + + internal enum RPCParameter : ushort + { + Volume, + Pitch, + ReverbSend, + FilterFrequency, + FilterQFactor, + NUM_PARAMETERS // If >=, DSP Parameter! + } + + internal class RPCPoint + { + public float X + { + get; + private set; + } + + public float Y + { + get; + private set; + } + + public RPCPointType Type + { + get; + private set; + } + + public RPCPoint(float x, float y, RPCPointType type) + { + X = x; + Y = y; + Type = type; + } + } + + internal class RPC + { + // Parent Variable + public string Variable + { + get; + private set; + } + + // RPC Parameter + public RPCParameter Parameter + { + get; + private set; + } + + // RPC Curve Points + private RPCPoint[] Points; + + public RPC( + string rpcVariable, + ushort rpcParameter, + RPCPoint[] rpcPoints + ) { + Variable = rpcVariable; + Parameter = (RPCParameter) rpcParameter; + Points = rpcPoints; + } + + public float CalculateRPC(float varInput) + { + // TODO: Non-linear curves + if (varInput == 0.0f) + { + if (Points[0].X == 0.0f) + { + // Some curves may start X->0 elsewhere. + return Points[0].Y; + } + return 0.0f; + } + else if (varInput <= Points[0].X) + { + // Zero to first defined point + return Points[0].Y / (varInput / Points[0].X); + } + else if (varInput >= Points[Points.Length - 1].X) + { + // Last defined point to infinity + return Points[Points.Length - 1].Y / (Points[Points.Length - 1].X / varInput); + } + else + { + // Something between points... + float result = 0.0f; + for (int i = 0; i < Points.Length - 1; i += 1) + { + // y = b + result = Points[i].Y; + if (varInput >= Points[i].X && varInput <= Points[i + 1].X) + { + // y += mx + result += + ((Points[i + 1].Y - Points[i].Y) / + (Points[i + 1].X - Points[i].X)) * + (varInput - Points[i].X); + // Pre-algebra, rockin`! + break; + } + } + return result; + } + } + } + + internal class DSPParameter + { + public byte Type + { + get; + private set; + } + + public float Minimum + { + get; + private set; + } + + public float Maximum + { + get; + private set; + } + + private float INTERNAL_value; + public float Value + { + get + { + return INTERNAL_value; + } + set + { + if (value < Minimum) + { + INTERNAL_value = Minimum; + } + else if (value > Maximum) + { + INTERNAL_value = Maximum; + } + else + { + INTERNAL_value = value; + } + } + } + public DSPParameter(byte type, float val, float min, float max) + { + Type = type; + Minimum = min; + Maximum = max; + INTERNAL_value = val; + } + } + + internal class DSPPreset + { + public IALReverb Effect + { + get; + private set; + } + + public bool IsGlobal + { + get; + private set; + } + + public DSPParameter[] Parameters + { + get; + private set; + } + + public DSPPreset( + bool global, + DSPParameter[] parameters + ) { + IsGlobal = global; + Parameters = parameters; + + // FIXME: Did XACT ever go past Reverb? -flibit + Effect = AudioDevice.GenReverb(Parameters); + } + + public void Dispose() + { + AudioDevice.ALDevice.DeleteReverb(Effect); + } + + public void SetParameter(int index, float value) + { + Parameters[index].Value = value; + + // Apply the value to the effect + if (index == 0) + { + AudioDevice.ALDevice.SetReverbReflectionsDelay(Effect, Parameters[index].Value); + } + else if (index == 1) + { + AudioDevice.ALDevice.SetReverbDelay(Effect, Parameters[index].Value); + } + else if (index == 2) + { + AudioDevice.ALDevice.SetReverbPositionLeft(Effect, Parameters[index].Value); + } + else if (index == 3) + { + AudioDevice.ALDevice.SetReverbPositionRight(Effect, Parameters[index].Value); + } + else if (index == 4) + { + AudioDevice.ALDevice.SetReverbPositionLeftMatrix(Effect, Parameters[index].Value); + } + else if (index == 5) + { + AudioDevice.ALDevice.SetReverbPositionRightMatrix(Effect, Parameters[index].Value); + } + else if (index == 6) + { + AudioDevice.ALDevice.SetReverbEarlyDiffusion(Effect, Parameters[index].Value); + } + else if (index == 7) + { + AudioDevice.ALDevice.SetReverbLateDiffusion(Effect, Parameters[index].Value); + } + else if (index == 8) + { + AudioDevice.ALDevice.SetReverbLowEQGain(Effect, Parameters[index].Value); + } + else if (index == 9) + { + AudioDevice.ALDevice.SetReverbLowEQCutoff(Effect, Parameters[index].Value); + } + else if (index == 10) + { + AudioDevice.ALDevice.SetReverbHighEQGain(Effect, Parameters[index].Value); + } + else if (index == 11) + { + AudioDevice.ALDevice.SetReverbHighEQCutoff(Effect, Parameters[index].Value); + } + else if (index == 12) + { + AudioDevice.ALDevice.SetReverbRearDelay(Effect, Parameters[index].Value); + } + else if (index == 13) + { + AudioDevice.ALDevice.SetReverbRoomFilterFrequency(Effect, Parameters[index].Value); + } + else if (index == 14) + { + AudioDevice.ALDevice.SetReverbRoomFilterMain(Effect, Parameters[index].Value); + } + else if (index == 15) + { + AudioDevice.ALDevice.SetReverbRoomFilterHighFrequency(Effect, Parameters[index].Value); + } + else if (index == 16) + { + AudioDevice.ALDevice.SetReverbReflectionsGain(Effect, Parameters[index].Value); + } + else if (index == 17) + { + AudioDevice.ALDevice.SetReverbGain(Effect, Parameters[index].Value); + } + else if (index == 18) + { + AudioDevice.ALDevice.SetReverbDecayTime(Effect, Parameters[index].Value); + } + else if (index == 19) + { + AudioDevice.ALDevice.SetReverbDensity(Effect, Parameters[index].Value); + } + else if (index == 20) + { + AudioDevice.ALDevice.SetReverbRoomSize(Effect, Parameters[index].Value); + } + else if (index == 21) + { + AudioDevice.ALDevice.SetReverbWetDryMix(Effect, Parameters[index].Value); + } + else + { + throw new Exception("DSP parameter unhandled: " + index.ToString()); + } + } + } +} diff --git a/src/BoundingBox.cs b/src/BoundingBox.cs new file mode 100644 index 0000000..2e8aa82 --- /dev/null +++ b/src/BoundingBox.cs @@ -0,0 +1,624 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; + +using Microsoft.Xna.Framework.Design; +#endregion + +namespace Microsoft.Xna.Framework +{ + [Serializable] + [TypeConverter(typeof(BoundingBoxConverter))] + [DebuggerDisplay("{DebugDisplayString,nq}")] + public struct BoundingBox : IEquatable + { + #region Internal Properties + + internal string DebugDisplayString + { + get + { + return string.Concat( + "Min( ", Min.DebugDisplayString, " ) \r\n", + "Max( ", Max.DebugDisplayString, " )" + ); + } + } + + #endregion + + #region Public Fields + + public Vector3 Min; + + public Vector3 Max; + + public const int CornerCount = 8; + + #endregion + + #region Private Static Variables + + private static readonly Vector3 MaxVector3 = new Vector3(float.MaxValue); + private static readonly Vector3 MinVector3 = new Vector3(float.MinValue); + + #endregion + + #region Public Constructors + + public BoundingBox(Vector3 min, Vector3 max) + { + this.Min = min; + this.Max = max; + } + + #endregion + + #region Public Methods + + public void Contains(ref BoundingBox box, out ContainmentType result) + { + result = Contains(box); + } + + public void Contains(ref BoundingSphere sphere, out ContainmentType result) + { + result = this.Contains(sphere); + } + + public ContainmentType Contains(Vector3 point) + { + ContainmentType result; + this.Contains(ref point, out result); + return result; + } + + public ContainmentType Contains(BoundingBox box) + { + // Test if all corner is in the same side of a face by just checking min and max + if ( box.Max.X < Min.X || + box.Min.X > Max.X || + box.Max.Y < Min.Y || + box.Min.Y > Max.Y || + box.Max.Z < Min.Z || + box.Min.Z > Max.Z ) + { + return ContainmentType.Disjoint; + } + + + if ( box.Min.X >= Min.X && + box.Max.X <= Max.X && + box.Min.Y >= Min.Y && + box.Max.Y <= Max.Y && + box.Min.Z >= Min.Z && + box.Max.Z <= Max.Z ) + { + return ContainmentType.Contains; + } + + return ContainmentType.Intersects; + } + + public ContainmentType Contains(BoundingFrustum frustum) + { + /* TODO: bad done here need a fix. + * Because the question is not if frustum contains box but the reverse and + * this is not the same. + */ + int i; + ContainmentType contained; + Vector3[] corners = frustum.GetCorners(); + + // First we check if frustum is in box. + for (i = 0; i < corners.Length; i += 1) + { + this.Contains(ref corners[i], out contained); + if (contained == ContainmentType.Disjoint) + { + break; + } + } + + // This means we checked all the corners and they were all contain or instersect + if (i == corners.Length) + { + return ContainmentType.Contains; + } + + // If i is not equal to zero, we can fastpath and say that this box intersects + if (i != 0) + { + return ContainmentType.Intersects; + } + + + /* If we get here, it means the first (and only) point we checked was + * actually contained in the frustum. So we assume that all other points + * will also be contained. If one of the points is disjoint, we can + * exit immediately saying that the result is Intersects + */ + i += 1; + for (; i < corners.Length; i += 1) + { + this.Contains(ref corners[i], out contained); + if (contained != ContainmentType.Contains) + { + return ContainmentType.Intersects; + } + + } + + /* If we get here, then we know all the points were actually contained, + * therefore result is Contains. + */ + return ContainmentType.Contains; + } + + public ContainmentType Contains(BoundingSphere sphere) + { + if ( sphere.Center.X - Min.X >= sphere.Radius && + sphere.Center.Y - Min.Y >= sphere.Radius && + sphere.Center.Z - Min.Z >= sphere.Radius && + Max.X - sphere.Center.X >= sphere.Radius && + Max.Y - sphere.Center.Y >= sphere.Radius && + Max.Z - sphere.Center.Z >= sphere.Radius ) + { + return ContainmentType.Contains; + } + + double dmin = 0; + + double e = sphere.Center.X - Min.X; + if (e < 0) + { + if (e < -sphere.Radius) + { + return ContainmentType.Disjoint; + } + dmin += e * e; + } + else + { + e = sphere.Center.X - Max.X; + if (e > 0) + { + if (e > sphere.Radius) + { + return ContainmentType.Disjoint; + } + dmin += e * e; + } + } + + e = sphere.Center.Y - Min.Y; + if (e < 0) + { + if (e < -sphere.Radius) + { + return ContainmentType.Disjoint; + } + dmin += e * e; + } + else + { + e = sphere.Center.Y - Max.Y; + if (e > 0) + { + if (e > sphere.Radius) + { + return ContainmentType.Disjoint; + } + dmin += e * e; + } + } + + e = sphere.Center.Z - Min.Z; + if (e < 0) + { + if (e < -sphere.Radius) + { + return ContainmentType.Disjoint; + } + dmin += e * e; + } + else + { + e = sphere.Center.Z - Max.Z; + if (e > 0) + { + if (e > sphere.Radius) + { + return ContainmentType.Disjoint; + } + dmin += e * e; + } + } + + if (dmin <= sphere.Radius * sphere.Radius) + { + return ContainmentType.Intersects; + } + + return ContainmentType.Disjoint; + } + + public void Contains(ref Vector3 point, out ContainmentType result) + { + // First determine if point is outside of this box. + if ( point.X < this.Min.X || + point.X > this.Max.X || + point.Y < this.Min.Y || + point.Y > this.Max.Y || + point.Z < this.Min.Z || + point.Z > this.Max.Z ) + { + result = ContainmentType.Disjoint; + } + // Or, if the point is on box because coordinate is less than or equal. + else if ( MathHelper.WithinEpsilon(point.X, this.Min.X) || + MathHelper.WithinEpsilon(point.X, this.Max.X) || + MathHelper.WithinEpsilon(point.Y, this.Min.Y) || + MathHelper.WithinEpsilon(point.Y, this.Max.Y) || + MathHelper.WithinEpsilon(point.Z, this.Min.Z) || + MathHelper.WithinEpsilon(point.Z, this.Max.Z) ) + { + result = ContainmentType.Intersects; + } + else + { + result = ContainmentType.Contains; + } + } + + public Vector3[] GetCorners() + { + return new Vector3[] { + new Vector3(this.Min.X, this.Max.Y, this.Max.Z), + new Vector3(this.Max.X, this.Max.Y, this.Max.Z), + new Vector3(this.Max.X, this.Min.Y, this.Max.Z), + new Vector3(this.Min.X, this.Min.Y, this.Max.Z), + new Vector3(this.Min.X, this.Max.Y, this.Min.Z), + new Vector3(this.Max.X, this.Max.Y, this.Min.Z), + new Vector3(this.Max.X, this.Min.Y, this.Min.Z), + new Vector3(this.Min.X, this.Min.Y, this.Min.Z) + }; + } + + public void GetCorners(Vector3[] corners) + { + if (corners == null) + { + throw new ArgumentNullException("corners"); + } + if (corners.Length < 8) + { + throw new ArgumentOutOfRangeException("corners", "Not Enought Corners"); + } + corners[0].X = this.Min.X; + corners[0].Y = this.Max.Y; + corners[0].Z = this.Max.Z; + corners[1].X = this.Max.X; + corners[1].Y = this.Max.Y; + corners[1].Z = this.Max.Z; + corners[2].X = this.Max.X; + corners[2].Y = this.Min.Y; + corners[2].Z = this.Max.Z; + corners[3].X = this.Min.X; + corners[3].Y = this.Min.Y; + corners[3].Z = this.Max.Z; + corners[4].X = this.Min.X; + corners[4].Y = this.Max.Y; + corners[4].Z = this.Min.Z; + corners[5].X = this.Max.X; + corners[5].Y = this.Max.Y; + corners[5].Z = this.Min.Z; + corners[6].X = this.Max.X; + corners[6].Y = this.Min.Y; + corners[6].Z = this.Min.Z; + corners[7].X = this.Min.X; + corners[7].Y = this.Min.Y; + corners[7].Z = this.Min.Z; + } + + public Nullable Intersects(Ray ray) + { + return ray.Intersects(this); + } + + public void Intersects(ref Ray ray, out Nullable result) + { + result = Intersects(ray); + } + + public bool Intersects(BoundingFrustum frustum) + { + return frustum.Intersects(this); + } + + public void Intersects(ref BoundingSphere sphere, out bool result) + { + result = Intersects(sphere); + } + + public bool Intersects(BoundingBox box) + { + bool result; + Intersects(ref box, out result); + return result; + } + + public PlaneIntersectionType Intersects(Plane plane) + { + PlaneIntersectionType result; + Intersects(ref plane, out result); + return result; + } + + public void Intersects(ref BoundingBox box, out bool result) + { + if ((this.Max.X >= box.Min.X) && (this.Min.X <= box.Max.X)) + { + if ((this.Max.Y < box.Min.Y) || (this.Min.Y > box.Max.Y)) + { + result = false; + return; + } + + result = (this.Max.Z >= box.Min.Z) && (this.Min.Z <= box.Max.Z); + return; + } + + result = false; + return; + } + + public bool Intersects(BoundingSphere sphere) + { + if ( sphere.Center.X - Min.X > sphere.Radius && + sphere.Center.Y - Min.Y > sphere.Radius && + sphere.Center.Z - Min.Z > sphere.Radius && + Max.X - sphere.Center.X > sphere.Radius && + Max.Y - sphere.Center.Y > sphere.Radius && + Max.Z - sphere.Center.Z > sphere.Radius ) + { + return true; + } + + double dmin = 0; + + if (sphere.Center.X - Min.X <= sphere.Radius) + { + dmin += (sphere.Center.X - Min.X) * (sphere.Center.X - Min.X); + } + else if (Max.X - sphere.Center.X <= sphere.Radius) + { + dmin += (sphere.Center.X - Max.X) * (sphere.Center.X - Max.X); + } + + if (sphere.Center.Y - Min.Y <= sphere.Radius) + { + dmin += (sphere.Center.Y - Min.Y) * (sphere.Center.Y - Min.Y); + } + else if (Max.Y - sphere.Center.Y <= sphere.Radius) + { + dmin += (sphere.Center.Y - Max.Y) * (sphere.Center.Y - Max.Y); + } + + if (sphere.Center.Z - Min.Z <= sphere.Radius) + { + dmin += (sphere.Center.Z - Min.Z) * (sphere.Center.Z - Min.Z); + } + else if (Max.Z - sphere.Center.Z <= sphere.Radius) + { + dmin += (sphere.Center.Z - Max.Z) * (sphere.Center.Z - Max.Z); + } + + if (dmin <= sphere.Radius * sphere.Radius) + { + return true; + } + + return false; + } + + public void Intersects(ref Plane plane, out PlaneIntersectionType result) + { + // See http://zach.in.tu-clausthal.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html + + Vector3 positiveVertex; + Vector3 negativeVertex; + + if (plane.Normal.X >= 0) + { + positiveVertex.X = Max.X; + negativeVertex.X = Min.X; + } + else + { + positiveVertex.X = Min.X; + negativeVertex.X = Max.X; + } + + if (plane.Normal.Y >= 0) + { + positiveVertex.Y = Max.Y; + negativeVertex.Y = Min.Y; + } + else + { + positiveVertex.Y = Min.Y; + negativeVertex.Y = Max.Y; + } + + if (plane.Normal.Z >= 0) + { + positiveVertex.Z = Max.Z; + negativeVertex.Z = Min.Z; + } + else + { + positiveVertex.Z = Min.Z; + negativeVertex.Z = Max.Z; + } + + // Inline Vector3.Dot(plane.Normal, negativeVertex) + plane.D; + float distance = ( + plane.Normal.X * negativeVertex.X + + plane.Normal.Y * negativeVertex.Y + + plane.Normal.Z * negativeVertex.Z + + plane.D + ); + if (distance > 0) + { + result = PlaneIntersectionType.Front; + return; + } + + // Inline Vector3.Dot(plane.Normal, positiveVertex) + plane.D; + distance = ( + plane.Normal.X * positiveVertex.X + + plane.Normal.Y * positiveVertex.Y + + plane.Normal.Z * positiveVertex.Z + + plane.D + ); + if (distance < 0) + { + result = PlaneIntersectionType.Back; + return; + } + + result = PlaneIntersectionType.Intersecting; + } + + public bool Equals(BoundingBox other) + { + return (this.Min == other.Min) && (this.Max == other.Max); + } + + #endregion + + #region Public Static Methods + + /// + /// Create a bounding box from the given list of points. + /// + /// + /// The list of Vector3 instances defining the point cloud to bound. + /// + /// A bounding box that encapsulates the given point cloud. + /// + /// Thrown if the given list has no points. + /// + public static BoundingBox CreateFromPoints(IEnumerable points) + { + if (points == null) + { + throw new ArgumentNullException("points"); + } + + bool empty = true; + Vector3 minVec = MaxVector3; + Vector3 maxVec = MinVector3; + foreach (Vector3 ptVector in points) + { + minVec.X = (minVec.X < ptVector.X) ? minVec.X : ptVector.X; + minVec.Y = (minVec.Y < ptVector.Y) ? minVec.Y : ptVector.Y; + minVec.Z = (minVec.Z < ptVector.Z) ? minVec.Z : ptVector.Z; + + maxVec.X = (maxVec.X > ptVector.X) ? maxVec.X : ptVector.X; + maxVec.Y = (maxVec.Y > ptVector.Y) ? maxVec.Y : ptVector.Y; + maxVec.Z = (maxVec.Z > ptVector.Z) ? maxVec.Z : ptVector.Z; + + empty = false; + } + if (empty) + { + throw new ArgumentException("Collection is empty", "points"); + } + + return new BoundingBox(minVec, maxVec); + } + + public static BoundingBox CreateFromSphere(BoundingSphere sphere) + { + BoundingBox result; + CreateFromSphere(ref sphere, out result); + return result; + } + + public static void CreateFromSphere(ref BoundingSphere sphere, out BoundingBox result) + { + Vector3 corner = new Vector3(sphere.Radius); + result.Min = sphere.Center - corner; + result.Max = sphere.Center + corner; + } + + public static BoundingBox CreateMerged(BoundingBox original, BoundingBox additional) + { + BoundingBox result; + CreateMerged(ref original, ref additional, out result); + return result; + } + + public static void CreateMerged(ref BoundingBox original, ref BoundingBox additional, out BoundingBox result) + { + result.Min.X = Math.Min(original.Min.X, additional.Min.X); + result.Min.Y = Math.Min(original.Min.Y, additional.Min.Y); + result.Min.Z = Math.Min(original.Min.Z, additional.Min.Z); + result.Max.X = Math.Max(original.Max.X, additional.Max.X); + result.Max.Y = Math.Max(original.Max.Y, additional.Max.Y); + result.Max.Z = Math.Max(original.Max.Z, additional.Max.Z); + } + + #endregion + + #region Public Static Operators and Override Methods + + public override bool Equals(object obj) + { + return (obj is BoundingBox) ? this.Equals((BoundingBox)obj) : false; + } + + public override int GetHashCode() + { + return this.Min.GetHashCode() + this.Max.GetHashCode(); + } + + public static bool operator ==(BoundingBox a, BoundingBox b) + { + return a.Equals(b); + } + + public static bool operator !=(BoundingBox a, BoundingBox b) + { + return !a.Equals(b); + } + + public override string ToString() + { + return ( + "{{Min:" + Min.ToString() + + " Max:" + Max.ToString() + + "}}" + ); + } + + #endregion + } +} diff --git a/src/BoundingFrustum.cs b/src/BoundingFrustum.cs new file mode 100644 index 0000000..43a6d0b --- /dev/null +++ b/src/BoundingFrustum.cs @@ -0,0 +1,785 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Diagnostics; +using System.Text; +#endregion + +namespace Microsoft.Xna.Framework +{ + /// + /// Defines a viewing frustum for intersection operations. + /// + [DebuggerDisplay("{DebugDisplayString,nq}")] + public class BoundingFrustum : IEquatable + { + #region Public Properties + + /// + /// Gets or sets the of the frustum. + /// + public Matrix Matrix + { + get + { + return this.matrix; + } + set + { + /* FIXME: The odds are the planes will be used a lot more often than + * the matrix is updated, so this should help performance. I hope. ;) + */ + this.matrix = value; + this.CreatePlanes(); + this.CreateCorners(); + } + } + + /// + /// Gets the near plane of the frustum. + /// + public Plane Near + { + get + { + return this.planes[0]; + } + } + + /// + /// Gets the far plane of the frustum. + /// + public Plane Far + { + get + { + return this.planes[1]; + } + } + + /// + /// Gets the left plane of the frustum. + /// + public Plane Left + { + get + { + return this.planes[2]; + } + } + + /// + /// Gets the right plane of the frustum. + /// + public Plane Right + { + get + { + return this.planes[3]; + } + } + + /// + /// Gets the top plane of the frustum. + /// + public Plane Top + { + get + { + return this.planes[4]; + } + } + + /// + /// Gets the bottom plane of the frustum. + /// + public Plane Bottom + { + get + { + return this.planes[5]; + } + } + + #endregion + + #region Internal Properties + + internal string DebugDisplayString + { + get + { + return string.Concat( + "Near( ", planes[0].DebugDisplayString, " ) \r\n", + "Far( ", planes[1].DebugDisplayString, " ) \r\n", + "Left( ", planes[2].DebugDisplayString, " ) \r\n", + "Right( ", planes[3].DebugDisplayString, " ) \r\n", + "Top( ", planes[4].DebugDisplayString, " ) \r\n", + "Bottom( ", planes[5].DebugDisplayString, " ) " + ); + } + } + + #endregion + + #region Public Fields + + /// + /// The number of corner points in the frustum. + /// + public const int CornerCount = 8; + + #endregion + + #region Private Fields + + private Matrix matrix; + private readonly Vector3[] corners = new Vector3[CornerCount]; + private readonly Plane[] planes = new Plane[PlaneCount]; + + /// + /// The number of planes in the frustum. + /// + private const int PlaneCount = 6; + + #endregion + + #region Public Constructors + + /// + /// Constructs the frustum by extracting the view planes from a matrix. + /// + /// Combined matrix which usually is (View * Projection). + public BoundingFrustum(Matrix value) + { + this.matrix = value; + this.CreatePlanes(); + this.CreateCorners(); + } + + #endregion + + #region Public Methods + + /// + /// Containment test between this and specified . + /// + /// A for testing. + /// Result of testing for containment between this and specified . + public ContainmentType Contains(BoundingFrustum frustum) + { + if (this == frustum) + { + return ContainmentType.Contains; + } + bool intersects = false; + for (int i = 0; i < PlaneCount; i += 1) + { + PlaneIntersectionType planeIntersectionType; + frustum.Intersects(ref planes[i], out planeIntersectionType); + if (planeIntersectionType == PlaneIntersectionType.Front) + { + return ContainmentType.Disjoint; + } + else if (planeIntersectionType == PlaneIntersectionType.Intersecting) + { + intersects = true; + } + } + return intersects ? ContainmentType.Intersects : ContainmentType.Contains; + } + + /// + /// Containment test between this and specified . + /// + /// A for testing. + /// Result of testing for containment between this and specified . + public ContainmentType Contains(BoundingBox box) + { + ContainmentType result = default(ContainmentType); + this.Contains(ref box, out result); + return result; + } + + /// + /// Containment test between this and specified . + /// + /// A for testing. + /// Result of testing for containment between this and specified as an output parameter. + public void Contains(ref BoundingBox box, out ContainmentType result) + { + bool intersects = false; + for (int i = 0; i < PlaneCount; i += 1) + { + PlaneIntersectionType planeIntersectionType = default(PlaneIntersectionType); + box.Intersects(ref this.planes[i], out planeIntersectionType); + switch (planeIntersectionType) + { + case PlaneIntersectionType.Front: + result = ContainmentType.Disjoint; + return; + case PlaneIntersectionType.Intersecting: + intersects = true; + break; + } + } + result = intersects ? ContainmentType.Intersects : ContainmentType.Contains; + } + + /// + /// Containment test between this and specified . + /// + /// A for testing. + /// Result of testing for containment between this and specified . + public ContainmentType Contains(BoundingSphere sphere) + { + ContainmentType result = default(ContainmentType); + this.Contains(ref sphere, out result); + return result; + } + + /// + /// Containment test between this and specified . + /// + /// A for testing. + /// Result of testing for containment between this and specified as an output parameter. + public void Contains(ref BoundingSphere sphere, out ContainmentType result) + { + bool intersects = false; + for (int i = 0; i < PlaneCount; i += 1) + { + PlaneIntersectionType planeIntersectionType = default(PlaneIntersectionType); + + // TODO: We might want to inline this for performance reasons. + sphere.Intersects(ref this.planes[i], out planeIntersectionType); + switch (planeIntersectionType) + { + case PlaneIntersectionType.Front: + result = ContainmentType.Disjoint; + return; + case PlaneIntersectionType.Intersecting: + intersects = true; + break; + } + } + result = intersects ? ContainmentType.Intersects : ContainmentType.Contains; + } + + /// + /// Containment test between this and specified . + /// + /// A for testing. + /// Result of testing for containment between this and specified . + public ContainmentType Contains(Vector3 point) + { + ContainmentType result = default(ContainmentType); + this.Contains(ref point, out result); + return result; + } + + /// + /// Containment test between this and specified . + /// + /// A for testing. + /// Result of testing for containment between this and specified as an output parameter. + public void Contains(ref Vector3 point, out ContainmentType result) + { + bool intersects = false; + for (int i = 0; i < PlaneCount; i += 1) + { + float classifyPoint = ( + (point.X * planes[i].Normal.X) + + (point.Y * planes[i].Normal.Y) + + (point.Z * planes[i].Normal.Z) + + planes[i].D + ); + if (classifyPoint > 0) + { + result = ContainmentType.Disjoint; + return; + } + else if (classifyPoint == 0) + { + intersects = true; + break; + } + } + result = intersects ? ContainmentType.Intersects : ContainmentType.Contains; + } + + /// + /// Returns a copy of internal corners array. + /// + /// The array of corners. + public Vector3[] GetCorners() + { + return (Vector3[]) this.corners.Clone(); + } + + /// + /// Returns a copy of internal corners array. + /// + /// The array which values will be replaced to corner values of this instance. It must have size of . + public void GetCorners(Vector3[] corners) + { + if (corners == null) + { + throw new ArgumentNullException("corners"); + } + if (corners.Length < CornerCount) + { + throw new ArgumentOutOfRangeException("corners"); + } + + this.corners.CopyTo(corners, 0); + } + + /// + /// Gets whether or not a specified intersects with this . + /// + /// An other for intersection test. + /// true if other intersects with this ; false otherwise. + public bool Intersects(BoundingFrustum frustum) + { + return (Contains(frustum) != ContainmentType.Disjoint); + } + + /// + /// Gets whether or not a specified intersects with this . + /// + /// A for intersection test. + /// true if specified intersects with this ; false otherwise. + public bool Intersects(BoundingBox box) + { + bool result = false; + this.Intersects(ref box, out result); + return result; + } + + /// + /// Gets whether or not a specified intersects with this . + /// + /// A for intersection test. + /// true if specified intersects with this ; false otherwise as an output parameter. + public void Intersects(ref BoundingBox box, out bool result) + { + ContainmentType containment = default(ContainmentType); + this.Contains(ref box, out containment); + result = containment != ContainmentType.Disjoint; + } + + /// + /// Gets whether or not a specified intersects with this . + /// + /// A for intersection test. + /// true if specified intersects with this ; false otherwise. + public bool Intersects(BoundingSphere sphere) + { + bool result = default(bool); + this.Intersects(ref sphere, out result); + return result; + } + + /// + /// Gets whether or not a specified intersects with this . + /// + /// A for intersection test. + /// true if specified intersects with this ; false otherwise as an output parameter. + public void Intersects(ref BoundingSphere sphere, out bool result) + { + ContainmentType containment = default(ContainmentType); + this.Contains(ref sphere, out containment); + result = containment != ContainmentType.Disjoint; + } + + /// + /// Gets type of intersection between specified and this . + /// + /// A for intersection test. + /// A plane intersection type. + public PlaneIntersectionType Intersects(Plane plane) + { + PlaneIntersectionType result; + Intersects(ref plane, out result); + return result; + } + + /// + /// Gets type of intersection between specified and this . + /// + /// A for intersection test. + /// A plane intersection type as an output parameter. + public void Intersects(ref Plane plane, out PlaneIntersectionType result) + { + result = plane.Intersects(ref corners[0]); + for (int i = 1; i < corners.Length; i += 1) + { + if (plane.Intersects(ref corners[i]) != result) + { + result = PlaneIntersectionType.Intersecting; + } + } + } + + /// + /// Gets the distance of intersection of and this or null if no intersection happens. + /// + /// A for intersection test. + /// Distance at which ray intersects with this or null if no intersection happens. + public float? Intersects(Ray ray) + { + float? result; + Intersects(ref ray, out result); + return result; + } + + /// + /// Gets the distance of intersection of and this or null if no intersection happens. + /// + /// A for intersection test. + /// Distance at which ray intersects with this or null if no intersection happens as an output parameter. + public void Intersects(ref Ray ray, out float? result) + { + ContainmentType ctype; + Contains(ref ray.Position, out ctype); + + if (ctype == ContainmentType.Disjoint) + { + result = null; + return; + } + if (ctype == ContainmentType.Contains) + { + result = 0.0f; + return; + } + if (ctype != ContainmentType.Intersects) + { + throw new ArgumentOutOfRangeException("ctype"); + } + + // TODO: Needs additional test for not 0.0 and null results. + result = null; + float min = float.MinValue; + float max = float.MaxValue; + foreach (Plane plane in planes) + { + Vector3 normal = plane.Normal; + float result2; + Vector3.Dot(ref ray.Direction, ref normal, out result2); + float result3; + Vector3.Dot(ref ray.Position, ref normal, out result3); + result3 += plane.D; + if ((double) Math.Abs(result2) < 9.99999974737875E-06) + { + if ((double) result3 > 0.0) + { + return; + } + } + else + { + float result4 = -result3 / result2; + if ((double) result2 < 0.0) + { + if ((double) result4 > (double) max) + { + return; + } + if ((double) result4 > (double) min) + { + min = result4; + } + } + else + { + if ((double) result4 < (double) min) + { + return; + } + if ((double) result4 < (double) max) + { + max = result4; + } + } + } + float? distance = ray.Intersects(plane); + if (distance.HasValue) + { + min = Math.Min(min, distance.Value); + max = Math.Max(max, distance.Value); + } + } + float temp = min >= 0.0 ? min : max; + if (temp < 0.0) + { + return; + } + result = temp; + } + + #endregion + + #region Private Methods + + private void CreateCorners() + { + IntersectionPoint( + ref this.planes[0], + ref this.planes[2], + ref this.planes[4], + out this.corners[0] + ); + IntersectionPoint( + ref this.planes[0], + ref this.planes[3], + ref this.planes[4], + out this.corners[1] + ); + IntersectionPoint( + ref this.planes[0], + ref this.planes[3], + ref this.planes[5], + out this.corners[2] + ); + IntersectionPoint( + ref this.planes[0], + ref this.planes[2], + ref this.planes[5], + out this.corners[3] + ); + IntersectionPoint( + ref this.planes[1], + ref this.planes[2], + ref this.planes[4], + out this.corners[4] + ); + IntersectionPoint( + ref this.planes[1], + ref this.planes[3], + ref this.planes[4], + out this.corners[5] + ); + IntersectionPoint( + ref this.planes[1], + ref this.planes[3], + ref this.planes[5], + out this.corners[6] + ); + IntersectionPoint( + ref this.planes[1], + ref this.planes[2], + ref this.planes[5], + out this.corners[7] + ); + } + + private void CreatePlanes() + { + this.planes[0] = new Plane( + -this.matrix.M13, + -this.matrix.M23, + -this.matrix.M33, + -this.matrix.M43 + ); + this.planes[1] = new Plane( + this.matrix.M13 - this.matrix.M14, + this.matrix.M23 - this.matrix.M24, + this.matrix.M33 - this.matrix.M34, + this.matrix.M43 - this.matrix.M44 + ); + this.planes[2] = new Plane( + -this.matrix.M14 - this.matrix.M11, + -this.matrix.M24 - this.matrix.M21, + -this.matrix.M34 - this.matrix.M31, + -this.matrix.M44 - this.matrix.M41 + ); + this.planes[3] = new Plane( + this.matrix.M11 - this.matrix.M14, + this.matrix.M21 - this.matrix.M24, + this.matrix.M31 - this.matrix.M34, + this.matrix.M41 - this.matrix.M44 + ); + this.planes[4] = new Plane( + this.matrix.M12 - this.matrix.M14, + this.matrix.M22 - this.matrix.M24, + this.matrix.M32 - this.matrix.M34, + this.matrix.M42 - this.matrix.M44 + ); + this.planes[5] = new Plane( + -this.matrix.M14 - this.matrix.M12, + -this.matrix.M24 - this.matrix.M22, + -this.matrix.M34 - this.matrix.M32, + -this.matrix.M44 - this.matrix.M42 + ); + + this.NormalizePlane(ref this.planes[0]); + this.NormalizePlane(ref this.planes[1]); + this.NormalizePlane(ref this.planes[2]); + this.NormalizePlane(ref this.planes[3]); + this.NormalizePlane(ref this.planes[4]); + this.NormalizePlane(ref this.planes[5]); + } + + private void NormalizePlane(ref Plane p) + { + float factor = 1f / p.Normal.Length(); + p.Normal.X *= factor; + p.Normal.Y *= factor; + p.Normal.Z *= factor; + p.D *= factor; + } + + #endregion + + #region Private Static Methods + + private static void IntersectionPoint( + ref Plane a, + ref Plane b, + ref Plane c, + out Vector3 result + ) { + /* Formula used + * d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 ) + * P = ------------------------------------------------------------------- + * N1 . ( N2 * N3 ) + * + * Note: N refers to the normal, d refers to the displacement. '.' means dot + * product. '*' means cross product + */ + + Vector3 v1, v2, v3; + Vector3 cross; + + Vector3.Cross(ref b.Normal, ref c.Normal, out cross); + + float f; + Vector3.Dot(ref a.Normal, ref cross, out f); + f *= -1.0f; + + Vector3.Cross(ref b.Normal, ref c.Normal, out cross); + Vector3.Multiply(ref cross, a.D, out v1); + // v1 = (a.D * (Vector3.Cross(b.Normal, c.Normal))); + + + Vector3.Cross(ref c.Normal, ref a.Normal, out cross); + Vector3.Multiply(ref cross, b.D, out v2); + // v2 = (b.D * (Vector3.Cross(c.Normal, a.Normal))); + + + Vector3.Cross(ref a.Normal, ref b.Normal, out cross); + Vector3.Multiply(ref cross, c.D, out v3); + // v3 = (c.D * (Vector3.Cross(a.Normal, b.Normal))); + + result.X = (v1.X + v2.X + v3.X) / f; + result.Y = (v1.Y + v2.Y + v3.Y) / f; + result.Z = (v1.Z + v2.Z + v3.Z) / f; + } + + #endregion + + #region Public Static Operators and Override Methods + + /// + /// Compares whether two instances are equal. + /// + /// instance on the left of the equal sign. + /// instance on the right of the equal sign. + /// true if the instances are equal; false otherwise. + public static bool operator ==(BoundingFrustum a, BoundingFrustum b) + { + if (object.Equals(a, null)) + { + return (object.Equals(b, null)); + } + + if (object.Equals(b, null)) + { + return (object.Equals(a, null)); + } + + return a.matrix == (b.matrix); + } + + /// + /// Compares whether two instances are not equal. + /// + /// instance on the left of the not equal sign. + /// instance on the right of the not equal sign. + /// true if the instances are not equal; false otherwise. + public static bool operator !=(BoundingFrustum a, BoundingFrustum b) + { + return !(a == b); + } + + /// + /// Compares whether current instance is equal to specified . + /// + /// The to compare. + /// true if the instances are equal; false otherwise. + public bool Equals(BoundingFrustum other) + { + return (this == other); + } + + /// + /// Compares whether current instance is equal to specified . + /// + /// The to compare. + /// true if the instances are equal; false otherwise. + public override bool Equals(object obj) + { + BoundingFrustum f = obj as BoundingFrustum; + return (object.Equals(f, null)) ? false : (this == f); + } + + /// + /// Returns a representation of this in the format: + /// {Near:[nearPlane] Far:[farPlane] Left:[leftPlane] Right:[rightPlane] Top:[topPlane] Bottom:[bottomPlane]} + /// + /// representation of this . + public override string ToString() + { + StringBuilder sb = new StringBuilder(256); + sb.Append("{Near:"); + sb.Append(this.planes[0].ToString()); + sb.Append(" Far:"); + sb.Append(this.planes[1].ToString()); + sb.Append(" Left:"); + sb.Append(this.planes[2].ToString()); + sb.Append(" Right:"); + sb.Append(this.planes[3].ToString()); + sb.Append(" Top:"); + sb.Append(this.planes[4].ToString()); + sb.Append(" Bottom:"); + sb.Append(this.planes[5].ToString()); + sb.Append("}"); + return sb.ToString(); + } + + /// + /// Gets the hash code of this . + /// + /// Hash code of this . + public override int GetHashCode() + { + return this.matrix.GetHashCode(); + } + + #endregion + } +} + diff --git a/src/BoundingSphere.cs b/src/BoundingSphere.cs new file mode 100644 index 0000000..a226b71 --- /dev/null +++ b/src/BoundingSphere.cs @@ -0,0 +1,688 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; + +using Microsoft.Xna.Framework.Design; +#endregion + +namespace Microsoft.Xna.Framework +{ + /// + /// Describes a sphere in 3D-space for bounding operations. + /// + [Serializable] + [TypeConverter(typeof(BoundingSphereConverter))] + [DebuggerDisplay("{DebugDisplayString,nq}")] + public struct BoundingSphere : IEquatable + { + #region Internal Properties + + internal string DebugDisplayString + { + get + { + return string.Concat( + "Center( ", Center.DebugDisplayString, " ) \r\n", + "Radius( ", Radius.ToString(), " ) " + ); + } + } + + #endregion + + #region Public Fields + + /// + /// The sphere center. + /// + public Vector3 Center; + + /// + /// The sphere radius. + /// + public float Radius; + + #endregion + + #region Public Constructors + + /// + /// Constructs a bounding sphere with the specified center and radius. + /// + /// The sphere center. + /// The sphere radius. + public BoundingSphere(Vector3 center, float radius) + { + this.Center = center; + this.Radius = radius; + } + + #endregion + + #region Public Methods + + /// + /// Creates a new that contains a transformation of translation and scale from this sphere by the specified . + /// + /// The transformation . + /// Transformed . + public BoundingSphere Transform(Matrix matrix) + { + BoundingSphere sphere = new BoundingSphere(); + sphere.Center = Vector3.Transform(this.Center, matrix); + sphere.Radius = this.Radius * + ( + (float) Math.Sqrt((double) Math.Max( + ((matrix.M11 * matrix.M11) + (matrix.M12 * matrix.M12)) + (matrix.M13 * matrix.M13), + Math.Max( + ((matrix.M21 * matrix.M21) + (matrix.M22 * matrix.M22)) + (matrix.M23 * matrix.M23), + ((matrix.M31 * matrix.M31) + (matrix.M32 * matrix.M32)) + (matrix.M33 * matrix.M33)) + ) + ) + ); + return sphere; + } + + /// + /// Creates a new that contains a transformation of translation and scale from this sphere by the specified . + /// + /// The transformation . + /// Transformed as an output parameter. + public void Transform(ref Matrix matrix, out BoundingSphere result) + { + result.Center = Vector3.Transform(this.Center, matrix); + result.Radius = this.Radius * + ( + (float) Math.Sqrt((double) Math.Max( + ((matrix.M11 * matrix.M11) + (matrix.M12 * matrix.M12)) + (matrix.M13 * matrix.M13), + Math.Max( + ((matrix.M21 * matrix.M21) + (matrix.M22 * matrix.M22)) + (matrix.M23 * matrix.M23), + ((matrix.M31 * matrix.M31) + (matrix.M32 * matrix.M32)) + (matrix.M33 * matrix.M33)) + ) + ) + ); + } + + /// + /// Test if a bounding box is fully inside, outside, or just intersecting the sphere. + /// + /// The box for testing. + /// The containment type as an output parameter. + public void Contains(ref BoundingBox box, out ContainmentType result) + { + result = this.Contains(box); + } + + /// + /// Test if a sphere is fully inside, outside, or just intersecting the sphere. + /// + /// The other sphere for testing. + /// The containment type as an output parameter. + public void Contains(ref BoundingSphere sphere, out ContainmentType result) + { + result = Contains(sphere); + } + + /// + /// Test if a point is fully inside, outside, or just intersecting the sphere. + /// + /// The vector in 3D-space for testing. + /// The containment type as an output parameter. + public void Contains(ref Vector3 point, out ContainmentType result) + { + result = Contains(point); + } + + /// + /// Test if a bounding box is fully inside, outside, or just intersecting the sphere. + /// + /// The box for testing. + /// The containment type. + public ContainmentType Contains(BoundingBox box) + { + // Check if all corners are in sphere. + bool inside = true; + foreach (Vector3 corner in box.GetCorners()) + { + if (this.Contains(corner) == ContainmentType.Disjoint) + { + inside = false; + break; + } + } + + if (inside) + { + return ContainmentType.Contains; + } + + // Check if the distance from sphere center to cube face is less than radius. + double dmin = 0; + + if (Center.X < box.Min.X) + { + dmin += (Center.X - box.Min.X) * (Center.X - box.Min.X); + } + else if (Center.X > box.Max.X) + { + dmin += (Center.X - box.Max.X) * (Center.X - box.Max.X); + } + + if (Center.Y < box.Min.Y) + { + dmin += (Center.Y - box.Min.Y) * (Center.Y - box.Min.Y); + } + else if (Center.Y > box.Max.Y) + { + dmin += (Center.Y - box.Max.Y) * (Center.Y - box.Max.Y); + } + + if (Center.Z < box.Min.Z) + { + dmin += (Center.Z - box.Min.Z) * (Center.Z - box.Min.Z); + } + else if (Center.Z > box.Max.Z) + { + dmin += (Center.Z - box.Max.Z) * (Center.Z - box.Max.Z); + } + + if (dmin <= Radius * Radius) + { + return ContainmentType.Intersects; + } + + // Else disjoint + return ContainmentType.Disjoint; + } + + /// + /// Test if a frustum is fully inside, outside, or just intersecting the sphere. + /// + /// The box for testing. + /// The containment type as an output parameter. + public ContainmentType Contains(BoundingFrustum frustum) + { + // Check if all corners are in sphere. + bool inside = true; + + Vector3[] corners = frustum.GetCorners(); + foreach (Vector3 corner in corners) + { + if (this.Contains(corner) == ContainmentType.Disjoint) + { + inside = false; + break; + } + } + if (inside) + { + return ContainmentType.Contains; + } + + // Check if the distance from sphere center to frustrum face is less than radius. + double dmin = 0; + // TODO : calcul dmin + + if (dmin <= Radius * Radius) + { + return ContainmentType.Intersects; + } + + // Else disjoint + return ContainmentType.Disjoint; + } + + /// + /// Test if a sphere is fully inside, outside, or just intersecting the sphere. + /// + /// The other sphere for testing. + /// The containment type. + public ContainmentType Contains(BoundingSphere sphere) + { + float sqDistance; + Vector3.DistanceSquared(ref sphere.Center, ref Center, out sqDistance); + + if (sqDistance > (sphere.Radius + Radius) * (sphere.Radius + Radius)) + { + return ContainmentType.Disjoint; + } + else if (sqDistance <= (Radius * sphere.Radius) * (Radius - sphere.Radius)) + { + return ContainmentType.Contains; + } + return ContainmentType.Intersects; + } + + /// + /// Test if a point is fully inside, outside, or just intersecting the sphere. + /// + /// The vector in 3D-space for testing. + /// The containment type. + public ContainmentType Contains(Vector3 point) + { + float sqRadius = Radius * Radius; + float sqDistance; + Vector3.DistanceSquared(ref point, ref Center, out sqDistance); + + if (sqDistance > sqRadius) + { + return ContainmentType.Disjoint; + } + else if (sqDistance < sqRadius) + { + return ContainmentType.Contains; + } + return ContainmentType.Intersects; + } + + /// + /// Compares whether current instance is equal to specified . + /// + /// The to compare. + /// true if the instances are equal; false otherwise. + public bool Equals(BoundingSphere other) + { + return ( this.Center == other.Center && + MathHelper.WithinEpsilon(this.Radius, other.Radius) ); + } + + #endregion + + #region Public Static Methods + + /// + /// Creates the smallest that can contain a specified . + /// + /// The box to create the sphere from. + /// The new . + public static BoundingSphere CreateFromBoundingBox(BoundingBox box) + { + BoundingSphere result; + CreateFromBoundingBox(ref box, out result); + return result; + } + + /// + /// Creates the smallest that can contain a specified . + /// + /// The box to create the sphere from. + /// The new as an output parameter. + public static void CreateFromBoundingBox(ref BoundingBox box, out BoundingSphere result) + { + // Find the center of the box. + Vector3 center = new Vector3( + (box.Min.X + box.Max.X) / 2.0f, + (box.Min.Y + box.Max.Y) / 2.0f, + (box.Min.Z + box.Max.Z) / 2.0f + ); + + // Find the distance between the center and one of the corners of the box. + float radius = Vector3.Distance(center, box.Max); + + result = new BoundingSphere(center, radius); + } + + /// + /// Creates the smallest that can contain a specified . + /// + /// The frustum to create the sphere from. + /// The new . + public static BoundingSphere CreateFromFrustum(BoundingFrustum frustum) + { + return CreateFromPoints(frustum.GetCorners()); + } + + /// + /// Creates the smallest that can contain a specified list of points in 3D-space. + /// + /// List of point to create the sphere from. + /// The new . + public static BoundingSphere CreateFromPoints(IEnumerable points) + { + if (points == null) + { + throw new ArgumentNullException("points"); + } + + // From "Real-Time Collision Detection" (Page 89) + + Vector3 minx = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); + Vector3 maxx = -minx; + Vector3 miny = minx; + Vector3 maxy = -minx; + Vector3 minz = minx; + Vector3 maxz = -minx; + + // Find the most extreme points along the principle axis. + int numPoints = 0; + foreach (Vector3 pt in points) + { + numPoints += 1; + + if (pt.X < minx.X) + { + minx = pt; + } + if (pt.X > maxx.X) + { + maxx = pt; + } + if (pt.Y < miny.Y) + { + miny = pt; + } + if (pt.Y > maxy.Y) + { + maxy = pt; + } + if (pt.Z < minz.Z) + { + minz = pt; + } + if (pt.Z > maxz.Z) + { + maxz = pt; + } + } + + if (numPoints == 0) + { + throw new ArgumentException( + "You should have at least one point in points." + ); + } + + float sqDistX = Vector3.DistanceSquared(maxx, minx); + float sqDistY = Vector3.DistanceSquared(maxy, miny); + float sqDistZ = Vector3.DistanceSquared(maxz, minz); + + // Pick the pair of most distant points. + Vector3 min = minx; + Vector3 max = maxx; + if (sqDistY > sqDistX && sqDistY > sqDistZ) + { + max = maxy; + min = miny; + } + if (sqDistZ > sqDistX && sqDistZ > sqDistY) + { + max = maxz; + min = minz; + } + + Vector3 center = (min + max) * 0.5f; + float radius = Vector3.Distance(max, center); + + // Test every point and expand the sphere. + // The current bounding sphere is just a good approximation and may not enclose all points. + // From: Mathematics for 3D Game Programming and Computer Graphics, Eric Lengyel, Third Edition. + // Page 218 + float sqRadius = radius * radius; + foreach (Vector3 pt in points) + { + Vector3 diff = (pt - center); + float sqDist = diff.LengthSquared(); + if (sqDist > sqRadius) + { + float distance = (float) Math.Sqrt(sqDist); // equal to diff.Length(); + Vector3 direction = diff / distance; + Vector3 G = center - radius * direction; + center = (G + pt) / 2; + radius = Vector3.Distance(pt, center); + sqRadius = radius * radius; + } + } + + return new BoundingSphere(center, radius); + } + + /// + /// Creates the smallest that can contain two spheres. + /// + /// First sphere. + /// Second sphere. + /// The new . + public static BoundingSphere CreateMerged(BoundingSphere original, BoundingSphere additional) + { + BoundingSphere result; + CreateMerged(ref original, ref additional, out result); + return result; + } + + /// + /// Creates the smallest that can contain two spheres. + /// + /// First sphere. + /// Second sphere. + /// The new as an output parameter. + public static void CreateMerged( + ref BoundingSphere original, + ref BoundingSphere additional, + out BoundingSphere result + ) { + Vector3 ocenterToaCenter = Vector3.Subtract(additional.Center, original.Center); + float distance = ocenterToaCenter.Length(); + + // Intersect + if (distance <= original.Radius + additional.Radius) + { + // Original contains additional. + if (distance <= original.Radius - additional.Radius) + { + result = original; + return; + } + + // Additional contains original. + if (distance <= additional.Radius - original.Radius) + { + result = additional; + return; + } + } + + // Else find center of new sphere and radius + float leftRadius = Math.Max(original.Radius - distance, additional.Radius); + float Rightradius = Math.Max(original.Radius + distance, additional.Radius); + + // oCenterToResultCenter + ocenterToaCenter = ocenterToaCenter + + ( + ((leftRadius - Rightradius) / (2 * ocenterToaCenter.Length())) + * ocenterToaCenter + ); + + result = new BoundingSphere(); + result.Center = original.Center + ocenterToaCenter; + result.Radius = (leftRadius + Rightradius) / 2; + } + + /// + /// Gets whether or not a specified intersects with this sphere. + /// + /// The box for testing. + /// true if intersects with this sphere; false otherwise. + public bool Intersects(BoundingBox box) + { + return box.Intersects(this); + } + + /// + /// Gets whether or not a specified intersects with this sphere. + /// + /// The box for testing. + /// true if intersects with this sphere; false otherwise. As an output parameter. + public void Intersects(ref BoundingBox box, out bool result) + { + box.Intersects(ref this, out result); + } + + public bool Intersects(BoundingFrustum frustum) + { + return frustum.Intersects(this); + } + + /// + /// Gets whether or not the other intersects with this sphere. + /// + /// The other sphere for testing. + /// true if other intersects with this sphere; false otherwise. + public bool Intersects(BoundingSphere sphere) + { + bool result; + Intersects(ref sphere, out result); + return result; + } + + /// + /// Gets whether or not the other intersects with this sphere. + /// + /// The other sphere for testing. + /// true if other intersects with this sphere; false otherwise. As an output parameter. + public void Intersects(ref BoundingSphere sphere, out bool result) + { + float sqDistance; + Vector3.DistanceSquared(ref sphere.Center, ref Center, out sqDistance); + result = !(sqDistance > (sphere.Radius + Radius) * (sphere.Radius + Radius)); + } + + /// + /// Gets whether or not a specified intersects with this sphere. + /// + /// The ray for testing. + /// Distance of ray intersection or null if there is no intersection. + public float? Intersects(Ray ray) + { + return ray.Intersects(this); + } + + /// + /// Gets whether or not a specified intersects with this sphere. + /// + /// The ray for testing. + /// Distance of ray intersection or null if there is no intersection as an output parameter. + public void Intersects(ref Ray ray, out float? result) + { + ray.Intersects(ref this, out result); + } + + /// + /// Gets whether or not a specified intersects with this sphere. + /// + /// The plane for testing. + /// Type of intersection. + public PlaneIntersectionType Intersects(Plane plane) + { + PlaneIntersectionType result = default(PlaneIntersectionType); + // TODO: We might want to inline this for performance reasons. + this.Intersects(ref plane, out result); + return result; + } + + /// + /// Gets whether or not a specified intersects with this sphere. + /// + /// The plane for testing. + /// Type of intersection as an output parameter. + public void Intersects(ref Plane plane, out PlaneIntersectionType result) + { + float distance = default(float); + // TODO: We might want to inline this for performance reasons. + Vector3.Dot(ref plane.Normal, ref this.Center, out distance); + distance += plane.D; + if (distance > this.Radius) + { + result = PlaneIntersectionType.Front; + } + else if (distance < -this.Radius) + { + result = PlaneIntersectionType.Back; + } + else + { + result = PlaneIntersectionType.Intersecting; + } + } + + #endregion + + #region Public Static Operators and Override Methods + + /// + /// Compares whether current instance is equal to specified . + /// + /// The to compare. + /// true if the instances are equal; false otherwise. + public override bool Equals(object obj) + { + if (obj is BoundingSphere) + { + return this.Equals((BoundingSphere)obj); + } + + return false; + } + + /// + /// Gets the hash code of this . + /// + /// Hash code of this . + public override int GetHashCode() + { + return this.Center.GetHashCode() + this.Radius.GetHashCode(); + } + + /// + /// Returns a representation of this in the format: + /// {Center:[] Radius:[]} + /// + /// A representation of this . + public override string ToString() + { + return ( + "{Center:" + Center.ToString() + + " Radius:" + Radius.ToString() + + "}" + ); + } + + /// + /// Compares whether two instances are equal. + /// + /// instance on the left of the equal sign. + /// instance on the right of the equal sign. + /// true if the instances are equal; false otherwise. + public static bool operator ==(BoundingSphere a, BoundingSphere b) + { + return a.Equals(b); + } + + /// + /// Compares whether two instances are not equal. + /// + /// instance on the left of the not equal sign. + /// instance on the right of the not equal sign. + /// true if the instances are not equal; false otherwise. + public static bool operator !=(BoundingSphere a, BoundingSphere b) + { + return !a.Equals(b); + } + + #endregion + } +} diff --git a/src/Color.cs b/src/Color.cs new file mode 100644 index 0000000..9c96974 --- /dev/null +++ b/src/Color.cs @@ -0,0 +1,1903 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Text; + +using Microsoft.Xna.Framework.Design; +#endregion + +namespace Microsoft.Xna.Framework +{ + /// + /// Describes a 32-bit packed color. + /// + [Serializable] + [TypeConverter(typeof(ColorConverter))] + [DebuggerDisplay("{DebugDisplayString,nq}")] + public struct Color : IEquatable + { + #region Public Properties + + /// + /// Gets or sets the blue component. + /// + public byte B + { + get + { + unchecked + { + return (byte) (this._packedValue >> 16); + } + } + set + { + this._packedValue = (this._packedValue & 0xff00ffff) | ((uint) value << 16); + } + } + + /// + /// Gets or sets the green component. + /// + public byte G + { + get + { + unchecked + { + return (byte) (this._packedValue >> 8); + } + } + set + { + this._packedValue = (this._packedValue & 0xffff00ff) | ((uint) value << 8); + } + } + + /// + /// Gets or sets the red component. + /// + public byte R + { + get + { + unchecked + { + return (byte) (this._packedValue); + } + } + set + { + this._packedValue = (this._packedValue & 0xffffff00) | value; + } + } + + /// + /// Gets or sets the alpha component. + /// + public byte A + { + get + { + unchecked + { + return (byte) (this._packedValue >> 24); + } + } + set + { + this._packedValue = (this._packedValue & 0x00ffffff) | ((uint) value << 24); + } + } + + /// + /// Gets or sets packed value of this . + /// + [CLSCompliant(false)] + public UInt32 PackedValue + { + get + { + return _packedValue; + } + set + { + _packedValue = value; + } + } + + #endregion + + #region Public Static Color Properties + + /// + /// Transparent color (R:0,G:0,B:0,A:0). + /// + public static Color Transparent + { + get; + private set; + } + + /// + /// AliceBlue color (R:240,G:248,B:255,A:255). + /// + public static Color AliceBlue + { + get; + private set; + } + + /// + /// AntiqueWhite color (R:250,G:235,B:215,A:255). + /// + public static Color AntiqueWhite + { + get; + private set; + } + + /// + /// Aqua color (R:0,G:255,B:255,A:255). + /// + public static Color Aqua + { + get; + private set; + } + + /// + /// Aquamarine color (R:127,G:255,B:212,A:255). + /// + public static Color Aquamarine + { + get; + private set; + } + + /// + /// Azure color (R:240,G:255,B:255,A:255). + /// + public static Color Azure + { + get; + private set; + } + + /// + /// Beige color (R:245,G:245,B:220,A:255). + /// + public static Color Beige + { + get; + private set; + } + + /// + /// Bisque color (R:255,G:228,B:196,A:255). + /// + public static Color Bisque + { + get; + private set; + } + + /// + /// Black color (R:0,G:0,B:0,A:255). + /// + public static Color Black + { + get; + private set; + } + + /// + /// BlanchedAlmond color (R:255,G:235,B:205,A:255). + /// + public static Color BlanchedAlmond + { + get; + private set; + } + + /// + /// Blue color (R:0,G:0,B:255,A:255). + /// + public static Color Blue + { + get; + private set; + } + + /// + /// BlueViolet color (R:138,G:43,B:226,A:255). + /// + public static Color BlueViolet + { + get; + private set; + } + + /// + /// Brown color (R:165,G:42,B:42,A:255). + /// + public static Color Brown + { + get; + private set; + } + + /// + /// BurlyWood color (R:222,G:184,B:135,A:255). + /// + public static Color BurlyWood + { + get; + private set; + } + + /// + /// CadetBlue color (R:95,G:158,B:160,A:255). + /// + public static Color CadetBlue + { + get; + private set; + } + + /// + /// Chartreuse color (R:127,G:255,B:0,A:255). + /// + public static Color Chartreuse + { + get; + private set; + } + + /// + /// Chocolate color (R:210,G:105,B:30,A:255). + /// + public static Color Chocolate + { + get; + private set; + } + + /// + /// Coral color (R:255,G:127,B:80,A:255). + /// + public static Color Coral + { + get; + private set; + } + + /// + /// CornflowerBlue color (R:100,G:149,B:237,A:255). + /// + public static Color CornflowerBlue + { + get; + private set; + } + + /// + /// Cornsilk color (R:255,G:248,B:220,A:255). + /// + public static Color Cornsilk + { + get; + private set; + } + + /// + /// Crimson color (R:220,G:20,B:60,A:255). + /// + public static Color Crimson + { + get; + private set; + } + + /// + /// Cyan color (R:0,G:255,B:255,A:255). + /// + public static Color Cyan + { + get; + private set; + } + + /// + /// DarkBlue color (R:0,G:0,B:139,A:255). + /// + public static Color DarkBlue + { + get; + private set; + } + + /// + /// DarkCyan color (R:0,G:139,B:139,A:255). + /// + public static Color DarkCyan + { + get; + private set; + } + + /// + /// DarkGoldenrod color (R:184,G:134,B:11,A:255). + /// + public static Color DarkGoldenrod + { + get; + private set; + } + + /// + /// DarkGray color (R:169,G:169,B:169,A:255). + /// + public static Color DarkGray + { + get; + private set; + } + + /// + /// DarkGreen color (R:0,G:100,B:0,A:255). + /// + public static Color DarkGreen + { + get; + private set; + } + + /// + /// DarkKhaki color (R:189,G:183,B:107,A:255). + /// + public static Color DarkKhaki + { + get; + private set; + } + + /// + /// DarkMagenta color (R:139,G:0,B:139,A:255). + /// + public static Color DarkMagenta + { + get; + private set; + } + + /// + /// DarkOliveGreen color (R:85,G:107,B:47,A:255). + /// + public static Color DarkOliveGreen + { + get; + private set; + } + + /// + /// DarkOrange color (R:255,G:140,B:0,A:255). + /// + public static Color DarkOrange + { + get; + private set; + } + + /// + /// DarkOrchid color (R:153,G:50,B:204,A:255). + /// + public static Color DarkOrchid + { + get; + private set; + } + + /// + /// DarkRed color (R:139,G:0,B:0,A:255). + /// + public static Color DarkRed + { + get; + private set; + } + + /// + /// DarkSalmon color (R:233,G:150,B:122,A:255). + /// + public static Color DarkSalmon + { + get; + private set; + } + + /// + /// DarkSeaGreen color (R:143,G:188,B:139,A:255). + /// + public static Color DarkSeaGreen + { + get; + private set; + } + + /// + /// DarkSlateBlue color (R:72,G:61,B:139,A:255). + /// + public static Color DarkSlateBlue + { + get; + private set; + } + + /// + /// DarkSlateGray color (R:47,G:79,B:79,A:255). + /// + public static Color DarkSlateGray + { + get; + private set; + } + + /// + /// DarkTurquoise color (R:0,G:206,B:209,A:255). + /// + public static Color DarkTurquoise + { + get; + private set; + } + + /// + /// DarkViolet color (R:148,G:0,B:211,A:255). + /// + public static Color DarkViolet + { + get; + private set; + } + + /// + /// DeepPink color (R:255,G:20,B:147,A:255). + /// + public static Color DeepPink + { + get; + private set; + } + + /// + /// DeepSkyBlue color (R:0,G:191,B:255,A:255). + /// + public static Color DeepSkyBlue + { + get; + private set; + } + + /// + /// DimGray color (R:105,G:105,B:105,A:255). + /// + public static Color DimGray + { + get; + private set; + } + + /// + /// DodgerBlue color (R:30,G:144,B:255,A:255). + /// + public static Color DodgerBlue + { + get; + private set; + } + + /// + /// Firebrick color (R:178,G:34,B:34,A:255). + /// + public static Color Firebrick + { + get; + private set; + } + + /// + /// FloralWhite color (R:255,G:250,B:240,A:255). + /// + public static Color FloralWhite + { + get; + private set; + } + + /// + /// ForestGreen color (R:34,G:139,B:34,A:255). + /// + public static Color ForestGreen + { + get; + private set; + } + + /// + /// Fuchsia color (R:255,G:0,B:255,A:255). + /// + public static Color Fuchsia + { + get; + private set; + } + + /// + /// Gainsboro color (R:220,G:220,B:220,A:255). + /// + public static Color Gainsboro + { + get; + private set; + } + + /// + /// GhostWhite color (R:248,G:248,B:255,A:255). + /// + public static Color GhostWhite + { + get; + private set; + } + /// + /// Gold color (R:255,G:215,B:0,A:255). + /// + public static Color Gold + { + get; + private set; + } + + /// + /// Goldenrod color (R:218,G:165,B:32,A:255). + /// + public static Color Goldenrod + { + get; + private set; + } + + /// + /// Gray color (R:128,G:128,B:128,A:255). + /// + public static Color Gray + { + get; + private set; + } + + /// + /// Green color (R:0,G:128,B:0,A:255). + /// + public static Color Green + { + get; + private set; + } + + /// + /// GreenYellow color (R:173,G:255,B:47,A:255). + /// + public static Color GreenYellow + { + get; + private set; + } + + /// + /// Honeydew color (R:240,G:255,B:240,A:255). + /// + public static Color Honeydew + { + get; + private set; + } + + /// + /// HotPink color (R:255,G:105,B:180,A:255). + /// + public static Color HotPink + { + get; + private set; + } + + /// + /// IndianRed color (R:205,G:92,B:92,A:255). + /// + public static Color IndianRed + { + get; + private set; + } + + /// + /// Indigo color (R:75,G:0,B:130,A:255). + /// + public static Color Indigo + { + get; + private set; + } + + /// + /// Ivory color (R:255,G:255,B:240,A:255). + /// + public static Color Ivory + { + get; + private set; + } + + /// + /// Khaki color (R:240,G:230,B:140,A:255). + /// + public static Color Khaki + { + get; + private set; + } + + /// + /// Lavender color (R:230,G:230,B:250,A:255). + /// + public static Color Lavender + { + get; + private set; + } + + /// + /// LavenderBlush color (R:255,G:240,B:245,A:255). + /// + public static Color LavenderBlush + { + get; + private set; + } + + /// + /// LawnGreen color (R:124,G:252,B:0,A:255). + /// + public static Color LawnGreen + { + get; + private set; + } + + /// + /// LemonChiffon color (R:255,G:250,B:205,A:255). + /// + public static Color LemonChiffon + { + get; + private set; + } + + /// + /// LightBlue color (R:173,G:216,B:230,A:255). + /// + public static Color LightBlue + { + get; + private set; + } + + /// + /// LightCoral color (R:240,G:128,B:128,A:255). + /// + public static Color LightCoral + { + get; + private set; + } + + /// + /// LightCyan color (R:224,G:255,B:255,A:255). + /// + public static Color LightCyan + { + get; + private set; + } + + /// + /// LightGoldenrodYellow color (R:250,G:250,B:210,A:255). + /// + public static Color LightGoldenrodYellow + { + get; + private set; + } + + /// + /// LightGray color (R:211,G:211,B:211,A:255). + /// + public static Color LightGray + { + get; + private set; + } + + /// + /// LightGreen color (R:144,G:238,B:144,A:255). + /// + public static Color LightGreen + { + get; + private set; + } + + /// + /// LightPink color (R:255,G:182,B:193,A:255). + /// + public static Color LightPink + { + get; + private set; + } + + /// + /// LightSalmon color (R:255,G:160,B:122,A:255). + /// + public static Color LightSalmon + { + get; + private set; + } + + /// + /// LightSeaGreen color (R:32,G:178,B:170,A:255). + /// + public static Color LightSeaGreen + { + get; + private set; + } + + /// + /// LightSkyBlue color (R:135,G:206,B:250,A:255). + /// + public static Color LightSkyBlue + { + get; + private set; + } + + /// + /// LightSlateGray color (R:119,G:136,B:153,A:255). + /// + public static Color LightSlateGray + { + get; + private set; + } + + /// + /// LightSteelBlue color (R:176,G:196,B:222,A:255). + /// + public static Color LightSteelBlue + { + get; + private set; + } + + /// + /// LightYellow color (R:255,G:255,B:224,A:255). + /// + public static Color LightYellow + { + get; + private set; + } + + /// + /// Lime color (R:0,G:255,B:0,A:255). + /// + public static Color Lime + { + get; + private set; + } + + /// + /// LimeGreen color (R:50,G:205,B:50,A:255). + /// + public static Color LimeGreen + { + get; + private set; + } + + /// + /// Linen color (R:250,G:240,B:230,A:255). + /// + public static Color Linen + { + get; + private set; + } + + /// + /// Magenta color (R:255,G:0,B:255,A:255). + /// + public static Color Magenta + { + get; + private set; + } + + /// + /// Maroon color (R:128,G:0,B:0,A:255). + /// + public static Color Maroon + { + get; + private set; + } + + /// + /// MediumAquamarine color (R:102,G:205,B:170,A:255). + /// + public static Color MediumAquamarine + { + get; + private set; + } + + /// + /// MediumBlue color (R:0,G:0,B:205,A:255). + /// + public static Color MediumBlue + { + get; + private set; + } + + /// + /// MediumOrchid color (R:186,G:85,B:211,A:255). + /// + public static Color MediumOrchid + { + get; + private set; + } + + /// + /// MediumPurple color (R:147,G:112,B:219,A:255). + /// + public static Color MediumPurple + { + get; + private set; + } + + /// + /// MediumSeaGreen color (R:60,G:179,B:113,A:255). + /// + public static Color MediumSeaGreen + { + get; + private set; + } + + /// + /// MediumSlateBlue color (R:123,G:104,B:238,A:255). + /// + public static Color MediumSlateBlue + { + get; + private set; + } + + /// + /// MediumSpringGreen color (R:0,G:250,B:154,A:255). + /// + public static Color MediumSpringGreen + { + get; + private set; + } + + /// + /// MediumTurquoise color (R:72,G:209,B:204,A:255). + /// + public static Color MediumTurquoise + { + get; + private set; + } + + /// + /// MediumVioletRed color (R:199,G:21,B:133,A:255). + /// + public static Color MediumVioletRed + { + get; + private set; + } + + /// + /// MidnightBlue color (R:25,G:25,B:112,A:255). + /// + public static Color MidnightBlue + { + get; + private set; + } + + /// + /// MintCream color (R:245,G:255,B:250,A:255). + /// + public static Color MintCream + { + get; + private set; + } + + /// + /// MistyRose color (R:255,G:228,B:225,A:255). + /// + public static Color MistyRose + { + get; + private set; + } + + /// + /// Moccasin color (R:255,G:228,B:181,A:255). + /// + public static Color Moccasin + { + get; + private set; + } + + /// + /// NavajoWhite color (R:255,G:222,B:173,A:255). + /// + public static Color NavajoWhite + { + get; + private set; + } + + /// + /// Navy color (R:0,G:0,B:128,A:255). + /// + public static Color Navy + { + get; + private set; + } + + /// + /// OldLace color (R:253,G:245,B:230,A:255). + /// + public static Color OldLace + { + get; + private set; + } + + /// + /// Olive color (R:128,G:128,B:0,A:255). + /// + public static Color Olive + { + get; + private set; + } + + /// + /// OliveDrab color (R:107,G:142,B:35,A:255). + /// + public static Color OliveDrab + { + get; + private set; + } + + /// + /// Orange color (R:255,G:165,B:0,A:255). + /// + public static Color Orange + { + get; + private set; + } + + /// + /// OrangeRed color (R:255,G:69,B:0,A:255). + /// + public static Color OrangeRed + { + get; + private set; + } + + /// + /// Orchid color (R:218,G:112,B:214,A:255). + /// + public static Color Orchid + { + get; + private set; + } + + /// + /// PaleGoldenrod color (R:238,G:232,B:170,A:255). + /// + public static Color PaleGoldenrod + { + get; + private set; + } + + /// + /// PaleGreen color (R:152,G:251,B:152,A:255). + /// + public static Color PaleGreen + { + get; + private set; + } + + /// + /// PaleTurquoise color (R:175,G:238,B:238,A:255). + /// + public static Color PaleTurquoise + { + get; + private set; + } + /// + /// PaleVioletRed color (R:219,G:112,B:147,A:255). + /// + public static Color PaleVioletRed + { + get; + private set; + } + + /// + /// PapayaWhip color (R:255,G:239,B:213,A:255). + /// + public static Color PapayaWhip + { + get; + private set; + } + + /// + /// PeachPuff color (R:255,G:218,B:185,A:255). + /// + public static Color PeachPuff + { + get; + private set; + } + + /// + /// Peru color (R:205,G:133,B:63,A:255). + /// + public static Color Peru + { + get; + private set; + } + + /// + /// Pink color (R:255,G:192,B:203,A:255). + /// + public static Color Pink + { + get; + private set; + } + + /// + /// Plum color (R:221,G:160,B:221,A:255). + /// + public static Color Plum + { + get; + private set; + } + + /// + /// PowderBlue color (R:176,G:224,B:230,A:255). + /// + public static Color PowderBlue + { + get; + private set; + } + + /// + /// Purple color (R:128,G:0,B:128,A:255). + /// + public static Color Purple + { + get; + private set; + } + + /// + /// Red color (R:255,G:0,B:0,A:255). + /// + public static Color Red + { + get; + private set; + } + + /// + /// RosyBrown color (R:188,G:143,B:143,A:255). + /// + public static Color RosyBrown + { + get; + private set; + } + + /// + /// RoyalBlue color (R:65,G:105,B:225,A:255). + /// + public static Color RoyalBlue + { + get; + private set; + } + + /// + /// SaddleBrown color (R:139,G:69,B:19,A:255). + /// + public static Color SaddleBrown + { + get; + private set; + } + + /// + /// Salmon color (R:250,G:128,B:114,A:255). + /// + public static Color Salmon + { + get; + private set; + } + + /// + /// SandyBrown color (R:244,G:164,B:96,A:255). + /// + public static Color SandyBrown + { + get; + private set; + } + + /// + /// SeaGreen color (R:46,G:139,B:87,A:255). + /// + public static Color SeaGreen + { + get; + private set; + } + + /// + /// SeaShell color (R:255,G:245,B:238,A:255). + /// + public static Color SeaShell + { + get; + private set; + } + + /// + /// Sienna color (R:160,G:82,B:45,A:255). + /// + public static Color Sienna + { + get; + private set; + } + + /// + /// Silver color (R:192,G:192,B:192,A:255). + /// + public static Color Silver + { + get; + private set; + } + + /// + /// SkyBlue color (R:135,G:206,B:235,A:255). + /// + public static Color SkyBlue + { + get; + private set; + } + + /// + /// SlateBlue color (R:106,G:90,B:205,A:255). + /// + public static Color SlateBlue + { + get; + private set; + } + + /// + /// SlateGray color (R:112,G:128,B:144,A:255). + /// + public static Color SlateGray + { + get; + private set; + } + + /// + /// Snow color (R:255,G:250,B:250,A:255). + /// + public static Color Snow + { + get; + private set; + } + + /// + /// SpringGreen color (R:0,G:255,B:127,A:255). + /// + public static Color SpringGreen + { + get; + private set; + } + + /// + /// SteelBlue color (R:70,G:130,B:180,A:255). + /// + public static Color SteelBlue + { + get; + private set; + } + + /// + /// Tan color (R:210,G:180,B:140,A:255). + /// + public static Color Tan + { + get; + private set; + } + + /// + /// Teal color (R:0,G:128,B:128,A:255). + /// + public static Color Teal + { + get; + private set; + } + + /// + /// Thistle color (R:216,G:191,B:216,A:255). + /// + public static Color Thistle + { + get; + private set; + } + + /// + /// Tomato color (R:255,G:99,B:71,A:255). + /// + public static Color Tomato + { + get; + private set; + } + + /// + /// Turquoise color (R:64,G:224,B:208,A:255). + /// + public static Color Turquoise + { + get; + private set; + } + + /// + /// Violet color (R:238,G:130,B:238,A:255). + /// + public static Color Violet + { + get; + private set; + } + + /// + /// Wheat color (R:245,G:222,B:179,A:255). + /// + public static Color Wheat + { + get; + private set; + } + + /// + /// White color (R:255,G:255,B:255,A:255). + /// + public static Color White + { + get; + private set; + } + + /// + /// WhiteSmoke color (R:245,G:245,B:245,A:255). + /// + public static Color WhiteSmoke + { + get; + private set; + } + + /// + /// Yellow color (R:255,G:255,B:0,A:255). + /// + public static Color Yellow + { + get; + private set; + } + + /// + /// YellowGreen color (R:154,G:205,B:50,A:255). + /// + public static Color YellowGreen + { + get; + private set; + } + + #endregion + + #region Internal Properties + + internal string DebugDisplayString + { + get + { + return string.Concat( + R.ToString(), " ", + G.ToString(), " ", + B.ToString(), " ", + A.ToString() + ); + } + } + + #endregion + + #region Private Variables + + // ARGB + private uint _packedValue; + + #endregion + + #region Private Static Constructors + + static Color() + { + Transparent = new Color(0); + AliceBlue = new Color(0xfffff8f0); + AntiqueWhite = new Color(0xffd7ebfa); + Aqua = new Color(0xffffff00); + Aquamarine = new Color(0xffd4ff7f); + Azure = new Color(0xfffffff0); + Beige = new Color(0xffdcf5f5); + Bisque = new Color(0xffc4e4ff); + Black = new Color(0xff000000); + BlanchedAlmond = new Color(0xffcdebff); + Blue = new Color(0xffff0000); + BlueViolet = new Color(0xffe22b8a); + Brown = new Color(0xff2a2aa5); + BurlyWood = new Color(0xff87b8de); + CadetBlue = new Color(0xffa09e5f); + Chartreuse = new Color(0xff00ff7f); + Chocolate = new Color(0xff1e69d2); + Coral = new Color(0xff507fff); + CornflowerBlue = new Color(0xffed9564); + Cornsilk = new Color(0xffdcf8ff); + Crimson = new Color(0xff3c14dc); + Cyan = new Color(0xffffff00); + DarkBlue = new Color(0xff8b0000); + DarkCyan = new Color(0xff8b8b00); + DarkGoldenrod = new Color(0xff0b86b8); + DarkGray = new Color(0xffa9a9a9); + DarkGreen = new Color(0xff006400); + DarkKhaki = new Color(0xff6bb7bd); + DarkMagenta = new Color(0xff8b008b); + DarkOliveGreen = new Color(0xff2f6b55); + DarkOrange = new Color(0xff008cff); + DarkOrchid = new Color(0xffcc3299); + DarkRed = new Color(0xff00008b); + DarkSalmon = new Color(0xff7a96e9); + DarkSeaGreen = new Color(0xff8bbc8f); + DarkSlateBlue = new Color(0xff8b3d48); + DarkSlateGray = new Color(0xff4f4f2f); + DarkTurquoise = new Color(0xffd1ce00); + DarkViolet = new Color(0xffd30094); + DeepPink = new Color(0xff9314ff); + DeepSkyBlue = new Color(0xffffbf00); + DimGray = new Color(0xff696969); + DodgerBlue = new Color(0xffff901e); + Firebrick = new Color(0xff2222b2); + FloralWhite = new Color(0xfff0faff); + ForestGreen = new Color(0xff228b22); + Fuchsia = new Color(0xffff00ff); + Gainsboro = new Color(0xffdcdcdc); + GhostWhite = new Color(0xfffff8f8); + Gold = new Color(0xff00d7ff); + Goldenrod = new Color(0xff20a5da); + Gray = new Color(0xff808080); + Green = new Color(0xff008000); + GreenYellow = new Color(0xff2fffad); + Honeydew = new Color(0xfff0fff0); + HotPink = new Color(0xffb469ff); + IndianRed = new Color(0xff5c5ccd); + Indigo = new Color(0xff82004b); + Ivory = new Color(0xfff0ffff); + Khaki = new Color(0xff8ce6f0); + Lavender = new Color(0xfffae6e6); + LavenderBlush = new Color(0xfff5f0ff); + LawnGreen = new Color(0xff00fc7c); + LemonChiffon = new Color(0xffcdfaff); + LightBlue = new Color(0xffe6d8ad); + LightCoral = new Color(0xff8080f0); + LightCyan = new Color(0xffffffe0); + LightGoldenrodYellow = new Color(0xffd2fafa); + LightGray = new Color(0xffd3d3d3); + LightGreen = new Color(0xff90ee90); + LightPink = new Color(0xffc1b6ff); + LightSalmon = new Color(0xff7aa0ff); + LightSeaGreen = new Color(0xffaab220); + LightSkyBlue = new Color(0xffface87); + LightSlateGray = new Color(0xff998877); + LightSteelBlue = new Color(0xffdec4b0); + LightYellow = new Color(0xffe0ffff); + Lime = new Color(0xff00ff00); + LimeGreen = new Color(0xff32cd32); + Linen = new Color(0xffe6f0fa); + Magenta = new Color(0xffff00ff); + Maroon = new Color(0xff000080); + MediumAquamarine = new Color(0xffaacd66); + MediumBlue = new Color(0xffcd0000); + MediumOrchid = new Color(0xffd355ba); + MediumPurple = new Color(0xffdb7093); + MediumSeaGreen = new Color(0xff71b33c); + MediumSlateBlue = new Color(0xffee687b); + MediumSpringGreen = new Color(0xff9afa00); + MediumTurquoise = new Color(0xffccd148); + MediumVioletRed = new Color(0xff8515c7); + MidnightBlue = new Color(0xff701919); + MintCream = new Color(0xfffafff5); + MistyRose = new Color(0xffe1e4ff); + Moccasin = new Color(0xffb5e4ff); + NavajoWhite = new Color(0xffaddeff); + Navy = new Color(0xff800000); + OldLace = new Color(0xffe6f5fd); + Olive = new Color(0xff008080); + OliveDrab = new Color(0xff238e6b); + Orange = new Color(0xff00a5ff); + OrangeRed = new Color(0xff0045ff); + Orchid = new Color(0xffd670da); + PaleGoldenrod = new Color(0xffaae8ee); + PaleGreen = new Color(0xff98fb98); + PaleTurquoise = new Color(0xffeeeeaf); + PaleVioletRed = new Color(0xff9370db); + PapayaWhip = new Color(0xffd5efff); + PeachPuff = new Color(0xffb9daff); + Peru = new Color(0xff3f85cd); + Pink = new Color(0xffcbc0ff); + Plum = new Color(0xffdda0dd); + PowderBlue = new Color(0xffe6e0b0); + Purple = new Color(0xff800080); + Red = new Color(0xff0000ff); + RosyBrown = new Color(0xff8f8fbc); + RoyalBlue = new Color(0xffe16941); + SaddleBrown = new Color(0xff13458b); + Salmon= new Color(0xff7280fa); + SandyBrown = new Color(0xff60a4f4); + SeaGreen = new Color(0xff578b2e); + SeaShell = new Color(0xffeef5ff); + Sienna = new Color(0xff2d52a0); + Silver = new Color(0xffc0c0c0); + SkyBlue = new Color(0xffebce87); + SlateBlue= new Color(0xffcd5a6a); + SlateGray= new Color(0xff908070); + Snow= new Color(0xfffafaff); + SpringGreen= new Color(0xff7fff00); + SteelBlue= new Color(0xffb48246); + Tan= new Color(0xff8cb4d2); + Teal= new Color(0xff808000); + Thistle= new Color(0xffd8bfd8); + Tomato= new Color(0xff4763ff); + Turquoise= new Color(0xffd0e040); + Violet= new Color(0xffee82ee); + Wheat= new Color(0xffb3def5); + White= new Color(uint.MaxValue); + WhiteSmoke= new Color(0xfff5f5f5); + Yellow = new Color(0xff00ffff); + YellowGreen = new Color(0xff32cd9a); + } + + #endregion + + #region Public Constructors + + /// + /// Creates a new instance of struct. + /// + /// A representing a color. + public Color(Vector4 color) + { + _packedValue = 0; + + R = (byte) MathHelper.Clamp(color.X * 255, Byte.MinValue, Byte.MaxValue); + G = (byte) MathHelper.Clamp(color.Y * 255, Byte.MinValue, Byte.MaxValue); + B = (byte) MathHelper.Clamp(color.Z * 255, Byte.MinValue, Byte.MaxValue); + A = (byte) MathHelper.Clamp(color.W * 255, Byte.MinValue, Byte.MaxValue); + } + + /// + /// Constructs an RGBA color from the XYZW unit length components of a vector. + /// + /// A representing a color. + public Color(Vector3 color) + { + _packedValue = 0; + + R = (byte) MathHelper.Clamp(color.X * 255, Byte.MinValue, Byte.MaxValue); + G = (byte) MathHelper.Clamp(color.Y * 255, Byte.MinValue, Byte.MaxValue); + B = (byte) MathHelper.Clamp(color.Z * 255, Byte.MinValue, Byte.MaxValue); + A = 255; + } + + /// + /// Constructs an RGBA color from a and an alpha value. + /// + /// + /// A for RGB values of new instance. + /// + /// The alpha component value from 0 to 255. + public Color(Color color, int alpha) + { + _packedValue = 0; + + R = color.R; + G = color.G; + B = color.B; + A = (byte) MathHelper.Clamp(alpha, Byte.MinValue, Byte.MaxValue); + } + + /// + /// Constructs an RGBA color from color and alpha value. + /// + /// + /// A for RGB values of new instance. + /// + /// Alpha component value from 0.0f to 1.0f. + public Color(Color color, float alpha) + { + _packedValue = 0; + + R = color.R; + G = color.G; + B = color.B; + A = (byte) MathHelper.Clamp(alpha * 255, Byte.MinValue, Byte.MaxValue); + } + + /// + /// Constructs an RGBA color from scalars which representing red, green and blue values. Alpha value will be opaque. + /// + /// Red component value from 0.0f to 1.0f. + /// Green component value from 0.0f to 1.0f. + /// Blue component value from 0.0f to 1.0f. + public Color(float r, float g, float b) + { + _packedValue = 0; + + R = (byte) MathHelper.Clamp(r * 255, Byte.MinValue, Byte.MaxValue); + G = (byte) MathHelper.Clamp(g * 255, Byte.MinValue, Byte.MaxValue); + B = (byte) MathHelper.Clamp(b * 255, Byte.MinValue, Byte.MaxValue); + A = 255; + } + + /// + /// Constructs an RGBA color from scalars which representing red, green and blue values. Alpha value will be opaque. + /// + /// Red component value from 0 to 255. + /// Green component value from 0 to 255. + /// Blue component value from 0 to 255. + public Color(int r, int g, int b) + { + _packedValue = 0; + R = (byte) MathHelper.Clamp(r, Byte.MinValue, Byte.MaxValue); + G = (byte) MathHelper.Clamp(g, Byte.MinValue, Byte.MaxValue); + B = (byte) MathHelper.Clamp(b, Byte.MinValue, Byte.MaxValue); + A = (byte)255; + } + + /// + /// Constructs an RGBA color from scalars which representing red, green, blue and alpha values. + /// + /// Red component value from 0 to 255. + /// Green component value from 0 to 255. + /// Blue component value from 0 to 255. + /// Alpha component value from 0 to 255. + public Color(int r, int g, int b, int alpha) + { + _packedValue = 0; + R = (byte) MathHelper.Clamp(r, Byte.MinValue, Byte.MaxValue); + G = (byte) MathHelper.Clamp(g, Byte.MinValue, Byte.MaxValue); + B = (byte) MathHelper.Clamp(b, Byte.MinValue, Byte.MaxValue); + A = (byte) MathHelper.Clamp(alpha, Byte.MinValue, Byte.MaxValue); + } + + /// + /// Constructs an RGBA color from scalars which representing red, green, blue and alpha values. + /// + /// Red component value from 0.0f to 1.0f. + /// Green component value from 0.0f to 1.0f. + /// Blue component value from 0.0f to 1.0f. + /// Alpha component value from 0.0f to 1.0f. + public Color(float r, float g, float b, float alpha) + { + _packedValue = 0; + + R = (byte) MathHelper.Clamp(r * 255, Byte.MinValue, Byte.MaxValue); + G = (byte) MathHelper.Clamp(g * 255, Byte.MinValue, Byte.MaxValue); + B = (byte) MathHelper.Clamp(b * 255, Byte.MinValue, Byte.MaxValue); + A = (byte) MathHelper.Clamp(alpha * 255, Byte.MinValue, Byte.MaxValue); + } + + #endregion + + #region Private Constructors + + private Color(uint packedValue) + { + _packedValue = packedValue; + } + + #endregion + + #region Public Methods + + /// + /// Compares whether current instance is equal to specified . + /// + /// The to compare. + /// true if the instances are equal; false otherwise. + public bool Equals(Color other) + { + return this.PackedValue == other.PackedValue; + } + + /// + /// Gets a representation for this object. + /// + /// A representation for this object. + public Vector3 ToVector3() + { + return new Vector3(R / 255.0f, G / 255.0f, B / 255.0f); + } + + /// + /// Gets a representation for this object. + /// + /// A representation for this object. + public Vector4 ToVector4() + { + return new Vector4(R / 255.0f, G / 255.0f, B / 255.0f, A / 255.0f); + } + + #endregion + + #region Public Static Methods + + /// + /// Performs linear interpolation of . + /// + /// Source . + /// Destination . + /// Interpolation factor. + /// Interpolated . + public static Color Lerp(Color value1, Color value2, float amount) + { + amount = MathHelper.Clamp(amount, 0.0f, 1.0f); + return new Color( + (int) MathHelper.Lerp(value1.R, value2.R, amount), + (int) MathHelper.Lerp(value1.G, value2.G, amount), + (int) MathHelper.Lerp(value1.B, value2.B, amount), + (int) MathHelper.Lerp(value1.A, value2.A, amount) + ); + } + + /// + /// Translate a non-premultipled alpha to a + /// that contains premultiplied alpha. + /// + /// A representing color. + /// A which contains premultiplied alpha data. + public static Color FromNonPremultiplied(Vector4 vector) + { + return new Color( + vector.X * vector.W, + vector.Y * vector.W, + vector.Z * vector.W, + vector.W + ); + } + + /// + /// Translate a non-premultipled alpha to a + /// that contains premultiplied alpha. + /// + /// Red component value. + /// Green component value. + /// Blue component value. + /// Alpha component value. + /// A which contains premultiplied alpha data. + public static Color FromNonPremultiplied(int r, int g, int b, int a) + { + return new Color( + (byte) (r * a / 255), + (byte) (g * a / 255), + (byte) (b * a / 255), + a + ); + } + + #endregion + + #region Public Static Operators and Override Methods + + /// + /// Compares whether two instances are equal. + /// + /// instance on the left of the equal sign. + /// instance on the right of the equal sign. + /// True if the instances are equal; false otherwise. + public static bool operator ==(Color a, Color b) + { + return ( a.A == b.A && + a.R == b.R && + a.G == b.G && + a.B == b.B ); + } + + /// + /// Compares whether two instances are not equal. + /// + /// + /// instance on the left of the not equal sign. + /// + /// + /// instance on the right of the not equal sign. + /// + /// + /// True if the instances are not equal; false otherwise. + /// + public static bool operator !=(Color a, Color b) + { + return !(a == b); + } + + /// + /// Gets the hash code of this . + /// + /// Hash code of this . + public override int GetHashCode() + { + return this._packedValue.GetHashCode(); + } + + /// + /// Compares whether current instance is equal to specified object. + /// + /// The to compare. + /// True if the instances are equal; false otherwise. + public override bool Equals(object obj) + { + return ((obj is Color) && this.Equals((Color) obj)); + } + + /// + /// Multiply by value. + /// + /// Source . + /// Multiplicator. + /// Multiplication result. + public static Color Multiply(Color value, float scale) + { + return new Color( + (int) (value.R * scale), + (int) (value.G * scale), + (int) (value.B * scale), + (int) (value.A * scale) + ); + } + + /// + /// Multiply by value. + /// + /// Source . + /// Multiplicator. + /// Multiplication result. + public static Color operator *(Color value, float scale) + { + return new Color( + (int) (value.R * scale), + (int) (value.G * scale), + (int) (value.B * scale), + (int) (value.A * scale) + ); + } + + /// + /// Returns a representation of this in the format: + /// {R:[red] G:[green] B:[blue] A:[alpha]} + /// + /// representation of this . + public override string ToString() + { + StringBuilder sb = new StringBuilder(25); + sb.Append("{R:"); + sb.Append(R); + sb.Append(" G:"); + sb.Append(G); + sb.Append(" B:"); + sb.Append(B); + sb.Append(" A:"); + sb.Append(A); + sb.Append("}"); + return sb.ToString(); + } + + #endregion + } +} diff --git a/src/ContainmentType.cs b/src/ContainmentType.cs new file mode 100644 index 0000000..b8b62fe --- /dev/null +++ b/src/ContainmentType.cs @@ -0,0 +1,34 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework +{ + /// + /// Defines how the bounding volumes intersects or contain one another. + /// + public enum ContainmentType + { + /// + /// Indicates that there is no overlap between two bounding volumes. + /// + Disjoint, + /// + /// Indicates that one bounding volume completely contains another volume. + /// + Contains, + /// + /// Indicates that bounding volumes partially overlap one another. + /// + Intersects + } +} diff --git a/src/Content/ContentExtensions.cs b/src/Content/ContentExtensions.cs new file mode 100644 index 0000000..3a9060a --- /dev/null +++ b/src/Content/ContentExtensions.cs @@ -0,0 +1,72 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal static class ContentExtensions + { + #region Public Static Constructor Extractor Method + + public static ConstructorInfo GetDefaultConstructor(this Type type) + { + BindingFlags attrs = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance; + return type.GetConstructor(attrs, null, new Type[0], null); + } + + #endregion + + #region Public Static Property Extractor Method + + public static PropertyInfo[] GetAllProperties(this Type type) + { + + /* Sometimes, overridden properties of abstract classes can show up even with + * BindingFlags.DeclaredOnly is passed to GetProperties. Make sure that + * all properties in this list are defined in this class by comparing + * its get method with that of its base class. If they're the same + * Then it's an overridden property. + */ + const BindingFlags attrs = ( + BindingFlags.NonPublic | + BindingFlags.Public | + BindingFlags.Instance | + BindingFlags.DeclaredOnly + ); + List allProps = type.GetProperties(attrs).ToList(); + PropertyInfo[] props = allProps.FindAll( + p => p.GetGetMethod(true) != null && p.GetGetMethod(true) == p.GetGetMethod(true).GetBaseDefinition() + ).ToArray(); + return props; + } + + #endregion + + #region Public Static Field Extractor Method + + public static FieldInfo[] GetAllFields(this Type type) + { + BindingFlags attrs = ( + BindingFlags.NonPublic | + BindingFlags.Public | + BindingFlags.Instance | + BindingFlags.DeclaredOnly + ); + return type.GetFields(attrs); + } + + #endregion + } +} diff --git a/src/Content/ContentLoadException.cs b/src/Content/ContentLoadException.cs new file mode 100644 index 0000000..b108d85 --- /dev/null +++ b/src/Content/ContentLoadException.cs @@ -0,0 +1,35 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + public class ContentLoadException : Exception + { + #region Public Constructors + + public ContentLoadException() : base() + { + } + + public ContentLoadException(string message) : base(message) + { + } + + public ContentLoadException(string message, Exception innerException) : base(message,innerException) + { + } + + #endregion + } +} + diff --git a/src/Content/ContentManager.cs b/src/Content/ContentManager.cs new file mode 100644 index 0000000..4735261 --- /dev/null +++ b/src/Content/ContentManager.cs @@ -0,0 +1,596 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Reflection; + +using Microsoft.Xna.Framework.Audio; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Media; +using Microsoft.Xna.Framework.Utilities; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + public partial class ContentManager : IDisposable + { + #region Public ServiceProvider Property + + public IServiceProvider ServiceProvider + { + get; + private set; + } + + #endregion + + #region Public RootDirectory Property + + public string RootDirectory + { + get; + set; + } + + #endregion + + #region Internal Root Directory Path Property + + internal string RootDirectoryFullPath + { + get + { + if (Path.IsPathRooted(RootDirectory)) + { + return RootDirectory; + } + return Path.Combine(TitleContainer.Location, RootDirectory); + } + } + + #endregion + + #region Private Variables + + private IGraphicsDeviceService graphicsDeviceService; + private Dictionary loadedAssets = new Dictionary(StringComparer.OrdinalIgnoreCase); + private List disposableAssets = new List(); + private bool disposed; + + #endregion + + #region Private Static Variables + + private static object ContentManagerLock = new object(); + private static List ContentManagers = new List(); + + private static readonly byte[] xnbHeader = new byte[4]; + private static List targetPlatformIdentifiers = new List() + { + 'w', // Windows (DirectX) + 'x', // Xbox360 + 'm', // WindowsPhone + 'i', // iOS + 'a', // Android + 'd', // DesktopGL + 'X', // MacOSX + 'W', // WindowsStoreApp + 'n', // NativeClient + 'u', // Ouya + 'p', // PlayStationMobile + 'M', // WindowsPhone8 + 'r', // RaspberryPi + 'P', // Playstation 4 + 'g', // WindowsGL (deprecated for DesktopGL) + 'l', // Linux (deprecated for DesktopGL) + }; + + #endregion + + #region Public Constructors + + public ContentManager(IServiceProvider serviceProvider) + { + if (serviceProvider == null) + { + throw new ArgumentNullException("serviceProvider"); + } + ServiceProvider = serviceProvider; + RootDirectory = string.Empty; + AddContentManager(this); + } + + public ContentManager(IServiceProvider serviceProvider, string rootDirectory) + { + if (serviceProvider == null) + { + throw new ArgumentNullException("serviceProvider"); + } + if (rootDirectory == null) + { + throw new ArgumentNullException("rootDirectory"); + } + ServiceProvider = serviceProvider; + RootDirectory = rootDirectory; + AddContentManager(this); + } + + #endregion + + #region Destructor + + /* Use C# destructor syntax for finalization code. + * This destructor will run only if the Dispose method + * does not get called. + * It gives your base class the opportunity to finalize. + * Do not provide destructors in types derived from this class. + */ + ~ContentManager() + { + /* Do not re-create Dispose clean-up code here. + * Calling Dispose(false) is optimal in terms of + * readability and maintainability. + */ + Dispose(false); + } + + #endregion + + #region Dispose Methods + + public void Dispose() + { + Dispose(true); + /* Tell the garbage collector not to call the finalizer + * since all the cleanup will already be done. + */ + GC.SuppressFinalize(this); + // Once disposed, content manager wont be used again + RemoveContentManager(this); + } + + /* If disposing is true, it was called explicitly and we should dispose managed + * objects. If disposing is false, it was called by the finalizer and managed + * objects should not be disposed. + */ + protected virtual void Dispose(bool disposing) + { + if (!disposed) + { + if (disposing) + { + Unload(); + } + disposed = true; + } + } + + #endregion + + #region Public Methods + + public virtual T Load(string assetName) + { + if (string.IsNullOrEmpty(assetName)) + { + throw new ArgumentNullException("assetName"); + } + if (disposed) + { + throw new ObjectDisposedException("ContentManager"); + } + T result = default(T); + + /* On some platforms, name and slash direction matter. + * We store the asset by a /-separating key rather than + * how the path to the file was passed to us to avoid + * loading "content/asset1.xnb" and "content\\ASSET1.xnb" + * as if they were two different files. this matches + * stock XNA behavior. The Dictionary will ignore case + * differences. + */ + string key = assetName.Replace('\\', '/'); + + // Check for a previously loaded asset first + object asset = null; + if (loadedAssets.TryGetValue(key, out asset)) + { + if (asset is T) + { + return (T) asset; + } + } + // Load the asset. + result = ReadAsset(assetName, null); + loadedAssets[key] = result; + return result; + } + + public virtual void Unload() + { + // Look for disposable assets. + foreach (IDisposable disposable in disposableAssets) + { + if (disposable != null) + { + disposable.Dispose(); + } + } + disposableAssets.Clear(); + loadedAssets.Clear(); + } + + #endregion + + #region Protected Methods + + protected virtual Stream OpenStream(string assetName) + { + Stream stream; + try + { + stream = TitleContainer.OpenStream( + Path.Combine(RootDirectory, assetName) + ".xnb" + ); + } + catch (FileNotFoundException fileNotFound) + { + throw new ContentLoadException("The content file was not found.", fileNotFound); + } + catch (DirectoryNotFoundException directoryNotFound) + { + throw new ContentLoadException("The directory was not found.", directoryNotFound); + } + catch (Exception exception) + { + throw new ContentLoadException("Opening stream error.", exception); + } + return stream; + } + + protected T ReadAsset(string assetName, Action recordDisposableObject) + { + if (string.IsNullOrEmpty(assetName)) + { + throw new ArgumentNullException("assetName"); + } + if (disposed) + { + throw new ObjectDisposedException("ContentManager"); + } + + object result = null; + + // FIXME: Should this block be here? -flibit + if (graphicsDeviceService == null) + { + graphicsDeviceService = ServiceProvider.GetService(typeof(IGraphicsDeviceService)) as IGraphicsDeviceService; + if (graphicsDeviceService == null) + { + throw new InvalidOperationException("No Graphics Device Service"); + } + } + + Stream stream = null; + string modifiedAssetName = String.Empty; // Will be used if we have to guess a filename + try + { + stream = OpenStream(assetName); + } + catch (Exception e) + { + // Okay, so we couldn't open it. Maybe it needs a different extension? + // FIXME: This only works for files on the disk, what about custom streams? -flibit + modifiedAssetName = FileHelpers.NormalizeFilePathSeparators( + Path.Combine(RootDirectoryFullPath, assetName) + ); + if (typeof(T) == typeof(Texture2D) || typeof(T) == typeof(Texture)) + { + modifiedAssetName = Texture2DReader.Normalize(modifiedAssetName); + } + else if ((typeof(T) == typeof(SoundEffect))) + { + modifiedAssetName = SoundEffectReader.Normalize(modifiedAssetName); + } + else if ((typeof(T) == typeof(Effect))) + { + modifiedAssetName = EffectReader.Normalize(modifiedAssetName); + } + else if ((typeof(T) == typeof(Song))) + { + modifiedAssetName = SongReader.Normalize(modifiedAssetName); + } + else if ((typeof(T) == typeof(Video))) + { + modifiedAssetName = VideoReader.Normalize(modifiedAssetName); + } + + // Did we get anything...? + if (String.IsNullOrEmpty(modifiedAssetName)) + { + // Nope, nothing we're aware of! + throw new ContentLoadException( + "Could not load asset " + assetName + "! Error: " + e.Message, + e + ); + } + + stream = TitleContainer.OpenStream(modifiedAssetName); + } + + // Check for XNB header + stream.Read(xnbHeader, 0, xnbHeader.Length); + if ( xnbHeader[0] == 'X' && + xnbHeader[1] == 'N' && + xnbHeader[2] == 'B' && + targetPlatformIdentifiers.Contains((char) xnbHeader[3]) ) + { + using (BinaryReader xnbReader = new BinaryReader(stream)) + using (ContentReader reader = GetContentReaderFromXnb(assetName, ref stream, xnbReader, recordDisposableObject)) + { + result = reader.ReadAsset(); + GraphicsResource resource = result as GraphicsResource; + if (resource != null) + { + resource.Name = assetName; + } + } + } + else + { + // It's not an XNB file. Try to load as a raw asset instead. + + // FIXME: Assuming seekable streams! -flibit + stream.Seek(0, SeekOrigin.Begin); + + if (typeof(T) == typeof(Texture2D) || typeof(T) == typeof(Texture)) + { + Texture2D texture = Texture2D.FromStream( + graphicsDeviceService.GraphicsDevice, + stream + ); + texture.Name = assetName; + result = texture; + } + else if ((typeof(T) == typeof(SoundEffect))) + { + result = SoundEffect.FromStream(stream); + } + else if ((typeof(T) == typeof(Effect))) + { + byte[] data = new byte[stream.Length]; + stream.Read(data, 0, (int) stream.Length); + result = new Effect(graphicsDeviceService.GraphicsDevice, data); + } + else if ((typeof(T) == typeof(Song))) + { + // FIXME: Not using the stream! -flibit + result = new Song(modifiedAssetName); + } + else if ((typeof(T) == typeof(Video))) + { + // FIXME: Not using the stream! -flibit + result = new Video(modifiedAssetName); + } + else + { + stream.Close(); + throw new ContentLoadException("Could not load " + assetName + " asset!"); + } + + /* Because Raw Assets skip the ContentReader step, they need to have their + * disposables recorded here. Doing it outside of this catch will + * result in disposables being logged twice. + */ + IDisposable disposableResult = result as IDisposable; + if (disposableResult != null) + { + if (recordDisposableObject != null) + { + recordDisposableObject(disposableResult); + } + else + { + disposableAssets.Add(disposableResult); + } + } + + /* Because we're not using a BinaryReader for raw assets, we + * need to close the stream ourselves. + * -flibit + */ + stream.Close(); + } + + return (T) result; + } + + #endregion + + #region Internal Methods + + internal void RecordDisposable(IDisposable disposable) + { + Debug.Assert(disposable != null, "The disposable is null!"); + + /* Avoid recording disposable objects twice. ReloadAsset will try to record + * the disposables again. We don't know which asset recorded which + * disposable so just guard against storing multiple of the same instance. + */ + if (!disposableAssets.Contains(disposable)) + { + disposableAssets.Add(disposable); + } + } + + #endregion + + #region Private Methods + + private ContentReader GetContentReaderFromXnb(string originalAssetName, ref Stream stream, BinaryReader xnbReader, Action recordDisposableObject) + { + byte version = xnbReader.ReadByte(); + byte flags = xnbReader.ReadByte(); + bool compressed = (flags & 0x80) != 0; + if (version != 5 && version != 4) + { + throw new ContentLoadException("Invalid XNB version"); + } + // The next int32 is the length of the XNB file + int xnbLength = xnbReader.ReadInt32(); + ContentReader reader; + if (compressed) + { + /* Decompress the XNB + * Thanks to ShinAli (https://bitbucket.org/alisci01/xnbdecompressor) + */ + int compressedSize = xnbLength - 14; + int decompressedSize = xnbReader.ReadInt32(); + MemoryStream decompressedStream = new MemoryStream( + new byte[decompressedSize], + 0, + decompressedSize, + true, + true // This MUST be true! We may need GetBuffer()! + ); + // Default window size for XNB encoded files is 64Kb (need 16 bits to represent it) + LzxDecoder dec = new LzxDecoder(16); + int decodedBytes = 0; + long startPos = stream.Position; + long pos = startPos; + + while (pos - startPos < compressedSize) + { + /* The compressed stream is separated into blocks that will + * decompress into 32kB or some other size if specified. + * Normal, 32kB output blocks will have a short indicating + * the size of the block before the block starts. Blocks + * that have a defined output will be preceded by a byte of + * value 0xFF (255), then a short indicating the output size + * and another for the block size. All shorts for these + * cases are encoded in big endian order. + */ + int hi = stream.ReadByte(); + int lo = stream.ReadByte(); + int block_size = (hi << 8) | lo; + int frame_size = 0x8000; // Frame size is 32kB by default + // Does this block define a frame size? + if (hi == 0xFF) + { + hi = lo; + lo = (byte) stream.ReadByte(); + frame_size = (hi << 8) | lo; + hi = (byte) stream.ReadByte(); + lo = (byte) stream.ReadByte(); + block_size = (hi << 8) | lo; + pos += 5; + } + else + { + pos += 2; + } + // Either says there is nothing to decode + if (block_size == 0 || frame_size == 0) + { + break; + } + dec.Decompress(stream, block_size, decompressedStream, frame_size); + pos += block_size; + decodedBytes += frame_size; + /* Reset the position of the input just in case the bit + * buffer read in some unused bytes. + */ + stream.Seek(pos, SeekOrigin.Begin); + } + if (decompressedStream.Position != decompressedSize) + { + throw new ContentLoadException( + "Decompression of " + originalAssetName + " failed. " + ); + } + decompressedStream.Seek(0, SeekOrigin.Begin); + reader = new ContentReader( + this, + decompressedStream, + graphicsDeviceService.GraphicsDevice, + originalAssetName, + version, + recordDisposableObject + ); + } + else + { + reader = new ContentReader( + this, + stream, + graphicsDeviceService.GraphicsDevice, + originalAssetName, + version, + recordDisposableObject + ); + } + return reader; + } + + #endregion + + #region Private Static Methods + + private static void AddContentManager(ContentManager contentManager) + { + lock (ContentManagerLock) + { + /* Check if the list contains this content manager already. Also take + * the opportunity to prune the list of any finalized content managers. + */ + bool contains = false; + for (int i = ContentManagers.Count - 1; i >= 0; i -= 1) + { + WeakReference contentRef = ContentManagers[i]; + if (ReferenceEquals(contentRef.Target, contentManager)) + { + contains = true; + } + if (!contentRef.IsAlive) + { + ContentManagers.RemoveAt(i); + } + } + if (!contains) + { + ContentManagers.Add(new WeakReference(contentManager)); + } + } + } + + private static void RemoveContentManager(ContentManager contentManager) + { + lock (ContentManagerLock) + { + /* Check if the list contains this content manager and remove it. Also + * take the opportunity to prune the list of any finalized content managers. + */ + for (int i = ContentManagers.Count - 1; i >= 0; i -= 1) + { + WeakReference contentRef = ContentManagers[i]; + if (!contentRef.IsAlive || ReferenceEquals(contentRef.Target, contentManager)) + { + ContentManagers.RemoveAt(i); + } + } + } + } + + #endregion + } +} diff --git a/src/Content/ContentReader.cs b/src/Content/ContentReader.cs new file mode 100644 index 0000000..fe7ad53 --- /dev/null +++ b/src/Content/ContentReader.cs @@ -0,0 +1,363 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +using System.IO; + +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Utilities; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + public sealed class ContentReader : BinaryReader + { + #region Public Properties + + public ContentManager ContentManager + { + get + { + return contentManager; + } + } + + public string AssetName + { + get + { + return assetName; + } + } + + #endregion + + #region Internal Properties + + internal ContentTypeReader[] TypeReaders + { + get + { + return typeReaders; + } + } + + internal GraphicsDevice GraphicsDevice + { + get + { + return this.graphicsDevice; + } + } + + #endregion + + #region Internal Variables + + internal int version; + internal int sharedResourceCount; + + #endregion + + #region Private Variables + + private ContentManager contentManager; + private Action recordDisposableObject; + private ContentTypeReaderManager typeReaderManager; + private GraphicsDevice graphicsDevice; + private string assetName; + private List>> sharedResourceFixups; + private ContentTypeReader[] typeReaders; + + #endregion + + #region Internal Constructor + + internal ContentReader( + ContentManager manager, + Stream stream, + GraphicsDevice graphicsDevice, + string assetName, + int version, + Action recordDisposableObject + ) : base(stream) { + this.graphicsDevice = graphicsDevice; + this.recordDisposableObject = recordDisposableObject; + this.contentManager = manager; + this.assetName = assetName; + this.version = version; + } + + #endregion + + #region Public Read Methods + + public T ReadExternalReference() + { + string externalReference = ReadString(); + if (!String.IsNullOrEmpty(externalReference)) + { + return contentManager.Load(FileHelpers.ResolveRelativePath(assetName, externalReference)); + } + return default(T); + } + + public Matrix ReadMatrix() + { + Matrix result = new Matrix(); + result.M11 = ReadSingle(); + result.M12 = ReadSingle(); + result.M13 = ReadSingle(); + result.M14 = ReadSingle(); + result.M21 = ReadSingle(); + result.M22 = ReadSingle(); + result.M23 = ReadSingle(); + result.M24 = ReadSingle(); + result.M31 = ReadSingle(); + result.M32 = ReadSingle(); + result.M33 = ReadSingle(); + result.M34 = ReadSingle(); + result.M41 = ReadSingle(); + result.M42 = ReadSingle(); + result.M43 = ReadSingle(); + result.M44 = ReadSingle(); + return result; + } + + public T ReadObject() + { + return ReadObject(default(T)); + } + + public T ReadObject(ContentTypeReader typeReader) + { + T result = (T) typeReader.Read(this, default(T)); + RecordDisposable(result); + return result; + } + + public T ReadObject(T existingInstance) + { + return InnerReadObject(existingInstance); + } + + public T ReadObject(ContentTypeReader typeReader, T existingInstance) + { + if (!typeReader.TargetType.IsValueType) + { + return ReadObject(existingInstance); + } + T result = (T) typeReader.Read(this, existingInstance); + RecordDisposable(result); + return result; + } + + public Quaternion ReadQuaternion() + { + Quaternion result = new Quaternion(); + result.X = ReadSingle(); + result.Y = ReadSingle(); + result.Z = ReadSingle(); + result.W = ReadSingle(); + return result; + } + + public T ReadRawObject() + { + return (T) ReadRawObject(default(T)); + } + + public T ReadRawObject(ContentTypeReader typeReader) + { + return (T) ReadRawObject(typeReader, default(T)); + } + + public T ReadRawObject(T existingInstance) + { + Type objectType = typeof(T); + foreach (ContentTypeReader typeReader in typeReaders) + { + if (typeReader.TargetType == objectType) + { + return (T) ReadRawObject(typeReader,existingInstance); + } + } + throw new NotSupportedException(); + } + + public T ReadRawObject(ContentTypeReader typeReader, T existingInstance) + { + return (T) typeReader.Read(this, existingInstance); + } + + public void ReadSharedResource(Action fixup) + { + int index = Read7BitEncodedInt(); + if (index > 0) + { + sharedResourceFixups.Add( + new KeyValuePair> ( + index - 1, + delegate(object v) + { + if (!(v is T)) + { + throw new ContentLoadException( + String.Format( + "Error loading shared resource. Expected type {0}, received type {1}", + typeof(T).Name, v.GetType().Name + ) + ); + } + fixup((T) v); + } + ) + ); + } + } + + public Vector2 ReadVector2() + { + Vector2 result = new Vector2(); + result.X = ReadSingle(); + result.Y = ReadSingle(); + return result; + } + + public Vector3 ReadVector3() + { + Vector3 result = new Vector3(); + result.X = ReadSingle(); + result.Y = ReadSingle(); + result.Z = ReadSingle(); + return result; + } + + public Vector4 ReadVector4() + { + Vector4 result = new Vector4(); + result.X = ReadSingle(); + result.Y = ReadSingle(); + result.Z = ReadSingle(); + result.W = ReadSingle(); + return result; + } + + public Color ReadColor() + { + Color result = new Color(); + result.R = ReadByte(); + result.G = ReadByte(); + result.B = ReadByte(); + result.A = ReadByte(); + return result; + } + + #endregion + + #region Internal Methods + + internal object ReadAsset() + { + InitializeTypeReaders(); + // Read primary object + object result = ReadObject(); + // Read shared resources + ReadSharedResources(); + return result; + } + + internal void InitializeTypeReaders() + { + typeReaderManager = new ContentTypeReaderManager(); + typeReaders = typeReaderManager.LoadAssetReaders(this); + sharedResourceCount = Read7BitEncodedInt(); + sharedResourceFixups = new List>>(); + } + + internal void ReadSharedResources() + { + if (sharedResourceCount <= 0) + { + return; + } + + object[] sharedResources = new object[sharedResourceCount]; + for (int i = 0; i < sharedResourceCount; i += 1) + { + sharedResources[i] = InnerReadObject(null); + } + // Fixup shared resources by calling each registered action + foreach (KeyValuePair> fixup in sharedResourceFixups) + { + fixup.Value(sharedResources[fixup.Key]); + } + } + + internal new int Read7BitEncodedInt() + { + return base.Read7BitEncodedInt(); + } + + internal BoundingSphere ReadBoundingSphere() + { + Vector3 position = ReadVector3(); + float radius = ReadSingle(); + return new BoundingSphere(position, radius); + } + + #endregion + + #region Private Methods + + private T InnerReadObject(T existingInstance) + { + int typeReaderIndex = Read7BitEncodedInt(); + if (typeReaderIndex == 0) + { + return existingInstance; + } + if (typeReaderIndex > typeReaders.Length) + { + throw new ContentLoadException( + "Incorrect type reader index found!" + ); + } + ContentTypeReader typeReader = typeReaders[typeReaderIndex - 1]; + T result = (T) typeReader.Read(this, default(T)); + RecordDisposable(result); + return result; + } + + private void RecordDisposable(T result) + { + IDisposable disposable = result as IDisposable; + if (disposable == null) + { + return; + } + if (recordDisposableObject != null) + { + recordDisposableObject(disposable); + } + else + { + contentManager.RecordDisposable(disposable); + } + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/AlphaTestEffectReader.cs b/src/Content/ContentReaders/AlphaTestEffectReader.cs new file mode 100644 index 0000000..7a135ec --- /dev/null +++ b/src/Content/ContentReaders/AlphaTestEffectReader.cs @@ -0,0 +1,34 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using Microsoft.Xna.Framework.Graphics; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + class AlphaTestEffectReader : ContentTypeReader + { + #region Protected Read Method + + protected internal override AlphaTestEffect Read(ContentReader input, AlphaTestEffect existingInstance) + { + AlphaTestEffect effect = new AlphaTestEffect(input.GraphicsDevice); + effect.Texture = input.ReadExternalReference() as Texture2D; + effect.AlphaFunction = (CompareFunction) input.ReadInt32(); + effect.ReferenceAlpha = (int) input.ReadUInt32(); + effect.DiffuseColor = input.ReadVector3(); + effect.Alpha = input.ReadSingle(); + effect.VertexColorEnabled = input.ReadBoolean(); + return effect; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/ArrayReader.cs b/src/Content/ContentReaders/ArrayReader.cs new file mode 100644 index 0000000..a185d36 --- /dev/null +++ b/src/Content/ContentReaders/ArrayReader.cs @@ -0,0 +1,85 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class ArrayReader : ContentTypeReader + { + #region Private ContentTypeReader Instance + + ContentTypeReader elementReader; + + #endregion + + #region Public Constructor + + public ArrayReader() + { + } + + #endregion + + #region Protected Initialization Method + + protected internal override void Initialize(ContentTypeReaderManager manager) + { + Type readerType = typeof(T); + elementReader = manager.GetTypeReader(readerType); + } + + #endregion + + #region Protected Read Method + + protected internal override T[] Read(ContentReader input, T[] existingInstance) + { + uint count = input.ReadUInt32(); + T[] array = existingInstance; + if (array == null) + { + array = new T[count]; + } + + if (typeof(T).IsValueType) + { + for (uint i = 0; i < count; i += 1) + { + array[i] = input.ReadObject(elementReader); + } + } + else + { + for (uint i = 0; i < count; i += 1) + { + int readerType = input.Read7BitEncodedInt(); + if (readerType > 0) + { + array[i] = input.ReadObject( + input.TypeReaders[readerType - 1] + ); + } + else { + array[i] = default(T); + } + } + } + return array; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/BasicEffectReader.cs b/src/Content/ContentReaders/BasicEffectReader.cs new file mode 100644 index 0000000..772d2f9 --- /dev/null +++ b/src/Content/ContentReaders/BasicEffectReader.cs @@ -0,0 +1,42 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using Microsoft.Xna.Framework.Graphics; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class BasicEffectReader : ContentTypeReader + { + #region Protected Read Method + + protected internal override BasicEffect Read( + ContentReader input, + BasicEffect existingInstance + ) { + BasicEffect effect = new BasicEffect(input.GraphicsDevice); + Texture2D texture = input.ReadExternalReference() as Texture2D; + if (texture != null) + { + effect.Texture = texture; + effect.TextureEnabled = true; + } + effect.DiffuseColor = input.ReadVector3(); + effect.EmissiveColor = input.ReadVector3(); + effect.SpecularColor = input.ReadVector3(); + effect.SpecularPower = input.ReadSingle(); + effect.Alpha = input.ReadSingle(); + effect.VertexColorEnabled = input.ReadBoolean(); + return effect; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/BooleanReader.cs b/src/Content/ContentReaders/BooleanReader.cs new file mode 100644 index 0000000..91d6529 --- /dev/null +++ b/src/Content/ContentReaders/BooleanReader.cs @@ -0,0 +1,33 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class BooleanReader : ContentTypeReader + { + #region Internal Constructor + + internal BooleanReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override bool Read( + ContentReader input, + bool existingInstance + ) { + return input.ReadBoolean(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/BoundingBoxReader.cs b/src/Content/ContentReaders/BoundingBoxReader.cs new file mode 100644 index 0000000..324bf4a --- /dev/null +++ b/src/Content/ContentReaders/BoundingBoxReader.cs @@ -0,0 +1,29 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + class BoundingBoxReader : ContentTypeReader + { + #region Protected Read Method + + protected internal override BoundingBox Read( + ContentReader input, + BoundingBox existingInstance + ) { + BoundingBox result = new BoundingBox( + input.ReadVector3(), + input.ReadVector3() + ); + return result; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/BoundingFrustumReader.cs b/src/Content/ContentReaders/BoundingFrustumReader.cs new file mode 100644 index 0000000..cae33e5 --- /dev/null +++ b/src/Content/ContentReaders/BoundingFrustumReader.cs @@ -0,0 +1,33 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class BoundingFrustumReader : ContentTypeReader + { + #region Internal Constructor + + internal BoundingFrustumReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override BoundingFrustum Read( + ContentReader input, + BoundingFrustum existingInstance + ) { + return new BoundingFrustum(input.ReadMatrix()); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/BoundingSphereReader.cs b/src/Content/ContentReaders/BoundingSphereReader.cs new file mode 100644 index 0000000..8970e53 --- /dev/null +++ b/src/Content/ContentReaders/BoundingSphereReader.cs @@ -0,0 +1,35 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class BoundingSphereReader : ContentTypeReader + { + #region Internal Constructor + + internal BoundingSphereReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override BoundingSphere Read( + ContentReader input, + BoundingSphere existingInstance + ) { + Vector3 center = input.ReadVector3(); + float radius = input.ReadSingle(); + return new BoundingSphere(center, radius); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/ByteReader.cs b/src/Content/ContentReaders/ByteReader.cs new file mode 100644 index 0000000..9d2ef51 --- /dev/null +++ b/src/Content/ContentReaders/ByteReader.cs @@ -0,0 +1,33 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class ByteReader : ContentTypeReader + { + #region Internal Constructor + + internal ByteReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override byte Read( + ContentReader input, + byte existingInstance + ) { + return input.ReadByte(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/CharReader.cs b/src/Content/ContentReaders/CharReader.cs new file mode 100644 index 0000000..d51d043 --- /dev/null +++ b/src/Content/ContentReaders/CharReader.cs @@ -0,0 +1,37 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion License + +namespace Microsoft.Xna.Framework.Content +{ + internal class CharReader : ContentTypeReader + { + #region Internal Constructor + + internal CharReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override char Read( + ContentReader input, + char existingInstance + ) { + return input.ReadChar(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/ColorReader.cs b/src/Content/ContentReaders/ColorReader.cs new file mode 100644 index 0000000..bd58530 --- /dev/null +++ b/src/Content/ContentReaders/ColorReader.cs @@ -0,0 +1,40 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class ColorReader : ContentTypeReader + { + #region Internal Constructor + + internal ColorReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override Color Read( + ContentReader input, + Color existingInstance + ) { + /* Read RGBA as four separate bytes to make sure we + * comply with XNB format document + */ + byte r = input.ReadByte(); + byte g = input.ReadByte(); + byte b = input.ReadByte(); + byte a = input.ReadByte(); + return new Color(r, g, b, a); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/CurveReader.cs b/src/Content/ContentReaders/CurveReader.cs new file mode 100644 index 0000000..c970686 --- /dev/null +++ b/src/Content/ContentReaders/CurveReader.cs @@ -0,0 +1,52 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class CurveReader : ContentTypeReader + { + #region Protected Read Method + + protected internal override Curve Read( + ContentReader input, + Curve existingInstance + ) { + Curve curve = existingInstance; + if (curve == null) + { + curve = new Curve(); + } + + curve.PreLoop = (CurveLoopType) input.ReadInt32(); + curve.PostLoop = (CurveLoopType) input.ReadInt32(); + int num6 = input.ReadInt32(); + for (int i = 0; i < num6; i += 1) + { + float position = input.ReadSingle(); + float num4 = input.ReadSingle(); + float tangentIn = input.ReadSingle(); + float tangentOut = input.ReadSingle(); + CurveContinuity continuity = (CurveContinuity) input.ReadInt32(); + curve.Keys.Add( + new CurveKey( + position, + num4, + tangentIn, + tangentOut, + continuity + ) + ); + } + return curve; + } + + #endregion + } +} + diff --git a/src/Content/ContentReaders/DateTimeReader.cs b/src/Content/ContentReaders/DateTimeReader.cs new file mode 100644 index 0000000..056e567 --- /dev/null +++ b/src/Content/ContentReaders/DateTimeReader.cs @@ -0,0 +1,41 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class DateTimeReader : ContentTypeReader + { + #region Internal Constructor + + internal DateTimeReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override DateTime Read( + ContentReader input, + DateTime existingInstance + ) { + UInt64 value = input.ReadUInt64(); + UInt64 mask = (UInt64) 3 << 62; + long ticks = (long) (value & ~mask); + DateTimeKind kind = (DateTimeKind) ((value >> 62) & 3); + return new DateTime(ticks, kind); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/DecimalReader.cs b/src/Content/ContentReaders/DecimalReader.cs new file mode 100644 index 0000000..c12948c --- /dev/null +++ b/src/Content/ContentReaders/DecimalReader.cs @@ -0,0 +1,33 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class DecimalReader : ContentTypeReader + { + #region Internal Constructor + + internal DecimalReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override decimal Read( + ContentReader input, + decimal existingInstance + ) { + return input.ReadDecimal(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/DictionaryReader.cs b/src/Content/ContentReaders/DictionaryReader.cs new file mode 100644 index 0000000..69c878f --- /dev/null +++ b/src/Content/ContentReaders/DictionaryReader.cs @@ -0,0 +1,106 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class DictionaryReader : ContentTypeReader> + { + #region Public Properties + + public override bool CanDeserializeIntoExistingObject + { + get + { + return true; + } + } + + #endregion + + #region Private Variables + + ContentTypeReader keyReader; + ContentTypeReader valueReader; + + Type keyType; + Type valueType; + + #endregion + + #region Public Constructor + + public DictionaryReader() + { + } + + #endregion + + #region Protected Initialization Method + + protected internal override void Initialize(ContentTypeReaderManager manager) + { + keyType = typeof(TKey); + valueType = typeof(TValue); + keyReader = manager.GetTypeReader(keyType); + valueReader = manager.GetTypeReader(valueType); + } + + #endregion + + #region Protected Read Method + + protected internal override Dictionary Read(ContentReader input, Dictionary existingInstance) + { + int count = input.ReadInt32(); + Dictionary dictionary = existingInstance; + if (dictionary == null) + { + dictionary = new Dictionary(count); + } + else + { + dictionary.Clear(); + } + + for (int i = 0; i < count; i += 1) + { + TKey key; + TValue value; + if (keyType.IsValueType) + { + key = input.ReadObject(keyReader); + } + else + { + int readerType = input.Read7BitEncodedInt(); + key = (readerType > 0) ? input.ReadObject(input.TypeReaders[readerType - 1]) : default(TKey); + } + if (valueType.IsValueType) + { + value = input.ReadObject(valueReader); + } + else + { + int readerType = input.Read7BitEncodedInt(); + value = (readerType > 0) ? input.ReadObject(input.TypeReaders[readerType - 1]) : default(TValue); + } + dictionary.Add(key, value); + } + return dictionary; + } + + #endregion + } +} + diff --git a/src/Content/ContentReaders/DoubleReader.cs b/src/Content/ContentReaders/DoubleReader.cs new file mode 100644 index 0000000..acc5f1e --- /dev/null +++ b/src/Content/ContentReaders/DoubleReader.cs @@ -0,0 +1,34 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class DoubleReader : ContentTypeReader + { + #region Internal Constructor + + internal DoubleReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override double Read( + ContentReader input, + double existingInstance + ) { + return input.ReadDouble(); + } + + #endregion + } +} + diff --git a/src/Content/ContentReaders/DualTextureEffectReader.cs b/src/Content/ContentReaders/DualTextureEffectReader.cs new file mode 100644 index 0000000..9624348 --- /dev/null +++ b/src/Content/ContentReaders/DualTextureEffectReader.cs @@ -0,0 +1,36 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using Microsoft.Xna.Framework.Graphics; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + class DualTextureEffectReader : ContentTypeReader + { + #region Protected Read Method + + protected internal override DualTextureEffect Read( + ContentReader input, + DualTextureEffect existingInstance + ) { + DualTextureEffect effect = new DualTextureEffect(input.GraphicsDevice); + effect.Texture = input.ReadExternalReference() as Texture2D; + effect.Texture2 = input.ReadExternalReference() as Texture2D; + effect.DiffuseColor = input.ReadVector3(); + effect.Alpha = input.ReadSingle(); + effect.VertexColorEnabled = input.ReadBoolean(); + return effect; + } + + #endregion + } +} + diff --git a/src/Content/ContentReaders/EffectMaterialReader.cs b/src/Content/ContentReaders/EffectMaterialReader.cs new file mode 100644 index 0000000..6e4c4cf --- /dev/null +++ b/src/Content/ContentReaders/EffectMaterialReader.cs @@ -0,0 +1,107 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +using System.Diagnostics; + +using Microsoft.Xna.Framework.Graphics; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class EffectMaterialReader : ContentTypeReader + { + #region Protected Read Method + + protected internal override EffectMaterial Read( + ContentReader input, + EffectMaterial existingInstance + ) { + Effect effect = input.ReadExternalReference(); + EffectMaterial effectMaterial = new EffectMaterial(effect); + Dictionary dict = input.ReadObject>(); + foreach (KeyValuePair item in dict) { + EffectParameter parameter = effectMaterial.Parameters[item.Key]; + if (parameter != null) + { + Type itemType = item.Value.GetType(); + if (typeof(Texture).IsAssignableFrom(itemType)) + { + parameter.SetValue((Texture) item.Value); + } + else if (typeof(int).IsAssignableFrom(itemType)) + { + parameter.SetValue((int) item.Value); + } + else if (typeof(bool).IsAssignableFrom(itemType)) + { + parameter.SetValue((bool) item.Value); + } + else if (typeof(float).IsAssignableFrom(itemType)) + { + parameter.SetValue((float) item.Value); + } + else if (typeof(float[]).IsAssignableFrom(itemType)) + { + parameter.SetValue((float[]) item.Value); + } + else if (typeof(Vector2).IsAssignableFrom(itemType)) + { + parameter.SetValue((Vector2) item.Value); + } + else if (typeof(Vector2[]).IsAssignableFrom(itemType)) + { + parameter.SetValue((Vector2[]) item.Value); + } + else if (typeof(Vector3).IsAssignableFrom(itemType)) + { + parameter.SetValue((Vector3) item.Value); + } + else if (typeof(Vector3[]).IsAssignableFrom(itemType)) + { + parameter.SetValue((Vector3[]) item.Value); + } + else if (typeof(Vector4).IsAssignableFrom(itemType)) + { + parameter.SetValue((Vector4) item.Value); + } + else if (typeof(Vector4[]).IsAssignableFrom(itemType)) + { + parameter.SetValue((Vector4[]) item.Value); + } + else if (typeof(Matrix).IsAssignableFrom(itemType)) + { + parameter.SetValue((Matrix) item.Value); + } + else if (typeof(Matrix[]).IsAssignableFrom(itemType)) + { + parameter.SetValue((Matrix[]) item.Value); + } + else if (typeof(Quaternion).IsAssignableFrom(itemType)) + { + parameter.SetValue((Quaternion) item.Value); + } + else + { + throw new NotSupportedException("Parameter type is not supported"); + } + } + else + { + Debug.WriteLine("No parameter " + item.Key); + } + } + return effectMaterial; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/EffectReader.cs b/src/Content/ContentReaders/EffectReader.cs new file mode 100644 index 0000000..f632ed5 --- /dev/null +++ b/src/Content/ContentReaders/EffectReader.cs @@ -0,0 +1,52 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System.Linq; + +using Microsoft.Xna.Framework.Graphics; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class EffectReader : ContentTypeReader + { + #region Private Supported File Extensions Variable + + private static string[] supportedExtensions = new string[] { ".fxb" }; + + #endregion + + #region Internal Filename Normalizer Method + + internal static string Normalize(string FileName) + { + return Normalize(FileName, supportedExtensions); + } + + #endregion + + #region Protected Read Method + + protected internal override Effect Read( + ContentReader input, + Effect existingInstance + ) { + int length = input.ReadInt32(); + Effect effect = new Effect( + input.GraphicsDevice, + input.ReadBytes(length) + ); + effect.Name = input.AssetName; + return effect; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/EnumReader.cs b/src/Content/ContentReaders/EnumReader.cs new file mode 100644 index 0000000..44d9f9b --- /dev/null +++ b/src/Content/ContentReaders/EnumReader.cs @@ -0,0 +1,51 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class EnumReader : ContentTypeReader + { + #region Private ContentTypeReader Instance + + ContentTypeReader elementReader; + + #endregion + + #region Public Constructor + + public EnumReader() + { + } + + #endregion + + #region Protected Initialization Method + + protected internal override void Initialize(ContentTypeReaderManager manager) + { + Type readerType = Enum.GetUnderlyingType(typeof(T)); + elementReader = manager.GetTypeReader(readerType); + } + + #endregion + + #region Protected Read Method + + protected internal override T Read(ContentReader input, T existingInstance) + { + return input.ReadRawObject(elementReader); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/EnvironmentMapEffectReader.cs b/src/Content/ContentReaders/EnvironmentMapEffectReader.cs new file mode 100644 index 0000000..1a2b068 --- /dev/null +++ b/src/Content/ContentReaders/EnvironmentMapEffectReader.cs @@ -0,0 +1,38 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using Microsoft.Xna.Framework.Graphics; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + class EnvironmentMapEffectReader : ContentTypeReader + { + #region Protected Read Method + + protected internal override EnvironmentMapEffect Read( + ContentReader input, + EnvironmentMapEffect existingInstance + ) { + EnvironmentMapEffect effect = new EnvironmentMapEffect(input.GraphicsDevice); + effect.Texture = input.ReadExternalReference() as Texture2D; + effect.EnvironmentMap = input.ReadExternalReference() as TextureCube; + effect.EnvironmentMapAmount = input.ReadSingle(); + effect.EnvironmentMapSpecular = input.ReadVector3(); + effect.FresnelFactor = input.ReadSingle(); + effect.DiffuseColor = input.ReadVector3(); + effect.EmissiveColor = input.ReadVector3(); + effect.Alpha = input.ReadSingle(); + return effect; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/ExternalReferenceReader.cs b/src/Content/ContentReaders/ExternalReferenceReader.cs new file mode 100644 index 0000000..66c99ad --- /dev/null +++ b/src/Content/ContentReaders/ExternalReferenceReader.cs @@ -0,0 +1,36 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + /// + /// External reference reader, provided for compatibility with XNA Framework built content + /// + internal class ExternalReferenceReader : ContentTypeReader + { + #region Public Constructor + + public ExternalReferenceReader() : base(typeof(object)) + { + } + + #endregion + + #region Protected Read Method + + protected internal override object Read( + ContentReader input, + object existingInstance + ) { + return input.ReadExternalReference(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/IndexBufferReader.cs b/src/Content/ContentReaders/IndexBufferReader.cs new file mode 100644 index 0000000..fc9b3ce --- /dev/null +++ b/src/Content/ContentReaders/IndexBufferReader.cs @@ -0,0 +1,56 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using Microsoft.Xna.Framework.Graphics; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + class IndexBufferReader : ContentTypeReader + { + #region Protected Read Method + + protected internal override IndexBuffer Read( + ContentReader input, + IndexBuffer existingInstance + ) { + IndexBuffer indexBuffer = existingInstance; + bool sixteenBits = input.ReadBoolean(); + int dataSize = input.ReadInt32(); + byte[] data = input.ReadBytes(dataSize); + if (indexBuffer == null) + { + if (sixteenBits) + { + indexBuffer = new IndexBuffer( + input.GraphicsDevice, + IndexElementSize.SixteenBits, + dataSize / 2, + BufferUsage.None + ); + } + else + { + indexBuffer = new IndexBuffer( + input.GraphicsDevice, + IndexElementSize.ThirtyTwoBits, + dataSize / 4, + BufferUsage.None + ); + } + } + + indexBuffer.SetData(data); + return indexBuffer; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/Int16Reader.cs b/src/Content/ContentReaders/Int16Reader.cs new file mode 100644 index 0000000..8e22057 --- /dev/null +++ b/src/Content/ContentReaders/Int16Reader.cs @@ -0,0 +1,33 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class Int16Reader : ContentTypeReader + { + #region Internal Constructor + + internal Int16Reader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override short Read( + ContentReader input, + short existingInstance + ) { + return input.ReadInt16(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/Int32Reader.cs b/src/Content/ContentReaders/Int32Reader.cs new file mode 100644 index 0000000..72a4e9d --- /dev/null +++ b/src/Content/ContentReaders/Int32Reader.cs @@ -0,0 +1,33 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class Int32Reader : ContentTypeReader + { + #region Internal Constructor + + internal Int32Reader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override int Read( + ContentReader input, + int existingInstance + ) { + return input.ReadInt32(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/Int64Reader.cs b/src/Content/ContentReaders/Int64Reader.cs new file mode 100644 index 0000000..93853bb --- /dev/null +++ b/src/Content/ContentReaders/Int64Reader.cs @@ -0,0 +1,33 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class Int64Reader : ContentTypeReader + { + #region Internal Constructor + + internal Int64Reader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override long Read( + ContentReader input, + long existingInstance + ) { + return input.ReadInt64(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/ListReader.cs b/src/Content/ContentReaders/ListReader.cs new file mode 100644 index 0000000..8c8bf4f --- /dev/null +++ b/src/Content/ContentReaders/ListReader.cs @@ -0,0 +1,89 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class ListReader : ContentTypeReader> + { + #region Public Properties + + public override bool CanDeserializeIntoExistingObject + { + get + { + return true; + } + } + + #endregion + + #region Private ContentTypeReader Instance + + ContentTypeReader elementReader; + + #endregion + + #region Public Constructor + + public ListReader() + { + } + + #endregion + + #region Protected Initialization Method + + protected internal override void Initialize(ContentTypeReaderManager manager) + { + Type readerType = typeof(T); + elementReader = manager.GetTypeReader(readerType); + } + + #endregion + + #region Protected Read Method + + protected internal override List Read( + ContentReader input, + List existingInstance + ) { + int count = input.ReadInt32(); + List list = existingInstance; + if (list == null) + { + list = new List(count); + } + for (int i = 0; i < count; i += 1) + { + Type objectType = typeof(T); + if (objectType.IsValueType) + { + list.Add(input.ReadObject(elementReader)); + } + else + { + int readerType = input.Read7BitEncodedInt(); + list.Add((readerType > 0) ? input.ReadObject(input.TypeReaders[readerType - 1]) : default(T)); + } + } + return list; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/MatrixReader.cs b/src/Content/ContentReaders/MatrixReader.cs new file mode 100644 index 0000000..2e6e456 --- /dev/null +++ b/src/Content/ContentReaders/MatrixReader.cs @@ -0,0 +1,43 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + class MatrixReader : ContentTypeReader + { + #region Protected Read Method + + protected internal override Matrix Read( + ContentReader input, + Matrix existingInstance + ) { + // 4x4 matrix + return new Matrix( + input.ReadSingle(), + input.ReadSingle(), + input.ReadSingle(), + input.ReadSingle(), + input.ReadSingle(), + input.ReadSingle(), + input.ReadSingle(), + input.ReadSingle(), + input.ReadSingle(), + input.ReadSingle(), + input.ReadSingle(), + input.ReadSingle(), + input.ReadSingle(), + input.ReadSingle(), + input.ReadSingle(), + input.ReadSingle() + ); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/ModelReader.cs b/src/Content/ContentReaders/ModelReader.cs new file mode 100644 index 0000000..2a3cce1 --- /dev/null +++ b/src/Content/ContentReaders/ModelReader.cs @@ -0,0 +1,188 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System.Collections.Generic; + +using Microsoft.Xna.Framework.Graphics; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class ModelReader : ContentTypeReader + { + #region Public Constructor + + public ModelReader() + { + } + + #endregion + + #region Private Bone Helper Method + + private static int ReadBoneReference(ContentReader reader, uint boneCount) + { + uint boneId; + // Read the bone ID, which may be encoded as either an 8 or 32 bit value. + if (boneCount < 255) + { + boneId = reader.ReadByte(); + } + else + { + boneId = reader.ReadUInt32(); + } + if (boneId != 0) + { + return (int) (boneId - 1); + } + + return -1; + } + + #endregion + + #region Protected Read Method + + protected internal override Model Read(ContentReader reader, Model existingInstance) + { + // Read the bone names and transforms. + uint boneCount = reader.ReadUInt32(); + List bones = new List((int) boneCount); + for (uint i = 0; i < boneCount; i += 1) + { + string name = reader.ReadObject(); + Matrix matrix = reader.ReadMatrix(); + ModelBone bone = new ModelBone { + Transform = matrix, + Index = (int) i, + Name = name + }; + bones.Add(bone); + } + // Read the bone hierarchy. + for (int i = 0; i < boneCount; i += 1) + { + ModelBone bone = bones[i]; + // Read the parent bone reference. + int parentIndex = ReadBoneReference(reader, boneCount); + if (parentIndex != -1) + { + bone.Parent = bones[parentIndex]; + } + // Read the child bone references. + uint childCount = reader.ReadUInt32(); + if (childCount != 0) + { + for (uint j = 0; j < childCount; j += 1) + { + int childIndex = ReadBoneReference(reader, boneCount); + if (childIndex != -1) + { + bone.AddChild(bones[childIndex]); + } + } + } + } + + List meshes = new List(); + + // Read the mesh data. + int meshCount = reader.ReadInt32(); + + for (int i = 0; i < meshCount; i += 1) + { + + string name = reader.ReadObject(); + int parentBoneIndex = ReadBoneReference(reader, boneCount); + BoundingSphere boundingSphere = reader.ReadBoundingSphere(); + + // Tag + object meshTag = reader.ReadObject(); + + // Read the mesh part data. + int partCount = reader.ReadInt32(); + + List parts = new List(partCount); + + for (uint j = 0; j < partCount; j += 1) + { + ModelMeshPart part; + if (existingInstance != null) + { + part = existingInstance.Meshes[i].MeshParts[(int) j]; + } + else + { + part = new ModelMeshPart(); + } + + part.VertexOffset = reader.ReadInt32(); + part.NumVertices = reader.ReadInt32(); + part.StartIndex = reader.ReadInt32(); + part.PrimitiveCount = reader.ReadInt32(); + + // Tag + part.Tag = reader.ReadObject(); + + parts.Add(part); + + int jj = (int) j; + reader.ReadSharedResource( + delegate (VertexBuffer v) + { + parts[jj].VertexBuffer = v; + } + ); + reader.ReadSharedResource( + delegate (IndexBuffer v) + { + parts[jj].IndexBuffer = v; + } + ); + reader.ReadSharedResource( + delegate (Effect v) + { + parts[jj].Effect = v; + } + ); + } + if (existingInstance != null) + { + continue; + } + ModelMesh mesh = new ModelMesh(reader.GraphicsDevice, parts); + mesh.Tag = meshTag; + mesh.Name = name; + mesh.ParentBone = bones[parentBoneIndex]; + mesh.ParentBone.AddMesh(mesh); + mesh.BoundingSphere = boundingSphere; + meshes.Add(mesh); + } + if (existingInstance != null) + { + // Read past remaining data and return existing instance + ReadBoneReference(reader, boneCount); + reader.ReadObject(); + return existingInstance; + } + // Read the final pieces of model data. + int rootBoneIndex = ReadBoneReference(reader, boneCount); + Model model = new Model(reader.GraphicsDevice, bones, meshes); + model.Root = bones[rootBoneIndex]; + model.BuildHierarchy(); + // Tag? + model.Tag = reader.ReadObject(); + return model; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/NullableReader.cs b/src/Content/ContentReaders/NullableReader.cs new file mode 100644 index 0000000..33d65e5 --- /dev/null +++ b/src/Content/ContentReaders/NullableReader.cs @@ -0,0 +1,55 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class NullableReader : ContentTypeReader where T : struct + { + #region Private ContentTypeReader Instance + + ContentTypeReader elementReader; + + #endregion + + #region Internal Constructor + + internal NullableReader() + { + } + + #endregion + + #region Protected Initialization Method + + protected internal override void Initialize(ContentTypeReaderManager manager) + { + Type readerType = typeof(T); + elementReader = manager.GetTypeReader(readerType); + } + + #endregion + + #region Protected Read Method + + protected internal override T? Read(ContentReader input, T? existingInstance) + { + if (input.ReadBoolean()) + { + return input.ReadObject(elementReader); + } + return null; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/PlaneReader.cs b/src/Content/ContentReaders/PlaneReader.cs new file mode 100644 index 0000000..ba8f5af --- /dev/null +++ b/src/Content/ContentReaders/PlaneReader.cs @@ -0,0 +1,39 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class PlaneReader : ContentTypeReader + { + #region Internal Constructor + + internal PlaneReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override Plane Read( + ContentReader input, + Plane existingInstance + ) { + existingInstance.Normal = input.ReadVector3(); + existingInstance.D = input.ReadSingle(); + return existingInstance; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/PointReader.cs b/src/Content/ContentReaders/PointReader.cs new file mode 100644 index 0000000..7098424 --- /dev/null +++ b/src/Content/ContentReaders/PointReader.cs @@ -0,0 +1,39 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class PointReader : ContentTypeReader + { + #region Internal Constructor + + internal PointReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override Point Read( + ContentReader input, + Point existingInstance + ) { + int X = input.ReadInt32(); + int Y = input.ReadInt32(); + return new Point(X, Y); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/QuaternionReader.cs b/src/Content/ContentReaders/QuaternionReader.cs new file mode 100644 index 0000000..3521754 --- /dev/null +++ b/src/Content/ContentReaders/QuaternionReader.cs @@ -0,0 +1,37 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class QuaternionReader : ContentTypeReader + { + #region Internal Constructor + + internal QuaternionReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override Quaternion Read( + ContentReader input, + Quaternion existingInstance + ) { + return input.ReadQuaternion(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/RayReader.cs b/src/Content/ContentReaders/RayReader.cs new file mode 100644 index 0000000..04129a1 --- /dev/null +++ b/src/Content/ContentReaders/RayReader.cs @@ -0,0 +1,35 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class RayReader : ContentTypeReader + { + #region Internal Constructor + + internal RayReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override Ray Read( + ContentReader input, + Ray existingInstance + ) { + Vector3 position = input.ReadVector3(); + Vector3 direction = input.ReadVector3(); + return new Ray(position, direction); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/RectangleReader.cs b/src/Content/ContentReaders/RectangleReader.cs new file mode 100644 index 0000000..ebd2df5 --- /dev/null +++ b/src/Content/ContentReaders/RectangleReader.cs @@ -0,0 +1,41 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class RectangleReader : ContentTypeReader + { + #region Internal Constructor + + internal RectangleReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override Rectangle Read( + ContentReader input, + Rectangle existingInstance + ) { + int left = input.ReadInt32(); + int top = input.ReadInt32(); + int width = input.ReadInt32(); + int height = input.ReadInt32(); + return new Rectangle(left, top, width, height); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/ReflectiveReader.cs b/src/Content/ContentReaders/ReflectiveReader.cs new file mode 100644 index 0000000..c924fbd --- /dev/null +++ b/src/Content/ContentReaders/ReflectiveReader.cs @@ -0,0 +1,290 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class ReflectiveReader : ContentTypeReader + { + #region Reader Delegates + + delegate void ReadElement(ContentReader input, object parent); + + private List readers; + + #endregion + + #region Public Properties + + public override bool CanDeserializeIntoExistingObject + { + get + { + return TargetType.IsClass; + } + } + + #endregion + + #region Private Variables + + private ConstructorInfo constructor; + + private ContentTypeReader baseTypeReader; + + #endregion + + #region Internal Constructor + + internal ReflectiveReader() : base(typeof(T)) + { + } + + #endregion + + #region Protected ContentTypeReader Methods + + protected internal override void Initialize(ContentTypeReaderManager manager) + { + base.Initialize(manager); + + Type baseType = TargetType.BaseType; + if (baseType != null && baseType != typeof(object)) + { + baseTypeReader = manager.GetTypeReader(baseType); + } + + constructor = TargetType.GetDefaultConstructor(); + + PropertyInfo[] properties = TargetType.GetAllProperties(); + FieldInfo[] fields = TargetType.GetAllFields(); + readers = new List(fields.Length + properties.Length); + + // Gather the properties. + foreach (PropertyInfo property in properties) + { + ReadElement read = GetElementReader(manager, property); + if (read != null) + { + readers.Add(read); + } + } + + // Gather the fields. + foreach (FieldInfo field in fields) + { + ReadElement read = GetElementReader(manager, field); + if (read != null) + { + readers.Add(read); + } + } + } + + protected internal override object Read(ContentReader input, object existingInstance) + { + T obj; + if (existingInstance != null) + { + obj = (T) existingInstance; + } + else + { + if (constructor == null) + { + obj = (T) Activator.CreateInstance(typeof(T)); + } + else + { + obj = (T) constructor.Invoke(null); + } + } + + if (baseTypeReader != null) + { + baseTypeReader.Read(input, obj); + } + + // Box the type. + object boxed = (object) obj; + + foreach (ReadElement reader in readers) + { + reader(input, boxed); + } + + // Unbox it... required for value types. + obj = (T) boxed; + + return obj; + } + + #endregion + + #region Private Static Methods + + private static ReadElement GetElementReader( + ContentTypeReaderManager manager, + MemberInfo member + ) { + PropertyInfo property = member as PropertyInfo; + FieldInfo field = member as FieldInfo; + + // Properties must have public get and set + if ( property != null && + ( property.CanWrite == false || + property.CanRead == false ) ) + { + return null; + } + + if (property != null) + { + // Properties must have at least a getter. + if (property.CanRead == false) + { + return null; + } + + // Skip over indexer properties + if (property.GetIndexParameters().Any()) + { + return null; + } + } + + // Are we explicitly asked to ignore this item? + Attribute attr = Attribute.GetCustomAttribute( + member, + typeof(ContentSerializerIgnoreAttribute) + ); + if (attr != null) + { + return null; + } + + ContentSerializerAttribute contentSerializerAttribute = Attribute.GetCustomAttribute( + member, + typeof(ContentSerializerAttribute) + ) as ContentSerializerAttribute; + if (contentSerializerAttribute == null) + { + if (property != null) + { + /* There is no ContentSerializerAttribute, so non-public + * properties cannot be deserialized. + */ + MethodInfo getMethod = property.GetGetMethod(true); + if (getMethod != null && !getMethod.IsPublic) + { + return null; + } + MethodInfo setMethod = property.GetSetMethod(true); + if (setMethod != null && !setMethod.IsPublic) + { + return null; + } + + /* If the read-only property has a type reader, + * and CanDeserializeIntoExistingObject is true, + * then it is safe to deserialize into the existing object. + */ + if (!property.CanWrite) + { + ContentTypeReader typeReader = manager.GetTypeReader(property.PropertyType); + if (typeReader == null || !typeReader.CanDeserializeIntoExistingObject) + { + return null; + } + } + } + else + { + /* There is no ContentSerializerAttribute, so non-public + * fields cannot be deserialized. + */ + if (!field.IsPublic) + { + return null; + } + + // evolutional: Added check to skip initialise only fields + if (field.IsInitOnly) + { + return null; + } + } + } + + Action setter; + Type elementType; + if (property != null) + { + elementType = property.PropertyType; + if (property.CanWrite) + { + setter = (o, v) => property.SetValue(o, v, null); + } + else + { + setter = (o, v) => { }; + } + } + else + { + elementType = field.FieldType; + setter = field.SetValue; + } + + if ( contentSerializerAttribute != null && + contentSerializerAttribute.SharedResource ) + { + return (input, parent) => + { + Action action = value => setter(parent, value); + input.ReadSharedResource(action); + }; + } + + // We need to have a reader at this point. + ContentTypeReader reader = manager.GetTypeReader(elementType); + if (reader == null) + { + throw new ContentLoadException(string.Format( + "Content reader could not be found for {0} type.", + elementType.FullName + )); + } + + /* We use the construct delegate to pick the correct existing + * object to be the target of deserialization. + */ + Func construct = parent => null; + if (property != null && !property.CanWrite) + { + construct = parent => property.GetValue(parent, null); + } + + return (input, parent) => + { + object existing = construct(parent); + object obj2 = input.ReadObject(reader, existing); + setter(parent, obj2); + }; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/SByteReader.cs b/src/Content/ContentReaders/SByteReader.cs new file mode 100644 index 0000000..b7b73a8 --- /dev/null +++ b/src/Content/ContentReaders/SByteReader.cs @@ -0,0 +1,33 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class SByteReader : ContentTypeReader + { + #region Internal Constructor + + internal SByteReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override sbyte Read( + ContentReader input, + sbyte existingInstance + ) { + return input.ReadSByte(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/SingleReader.cs b/src/Content/ContentReaders/SingleReader.cs new file mode 100644 index 0000000..76593c4 --- /dev/null +++ b/src/Content/ContentReaders/SingleReader.cs @@ -0,0 +1,33 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class SingleReader : ContentTypeReader + { + #region Internal Constructor + + internal SingleReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override float Read( + ContentReader input, + float existingInstance + ) { + return input.ReadSingle(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/SkinnedEffectReader.cs b/src/Content/ContentReaders/SkinnedEffectReader.cs new file mode 100644 index 0000000..f970a2e --- /dev/null +++ b/src/Content/ContentReaders/SkinnedEffectReader.cs @@ -0,0 +1,37 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using Microsoft.Xna.Framework.Graphics; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + class SkinnedEffectReader : ContentTypeReader + { + #region Protected Read Method + + protected internal override SkinnedEffect Read( + ContentReader input, + SkinnedEffect existingInstance + ) { + SkinnedEffect effect = new SkinnedEffect(input.GraphicsDevice); + effect.Texture = input.ReadExternalReference() as Texture2D; + effect.WeightsPerVertex = input.ReadInt32(); + effect.DiffuseColor = input.ReadVector3(); + effect.EmissiveColor = input.ReadVector3(); + effect.SpecularColor = input.ReadVector3(); + effect.SpecularPower = input.ReadSingle(); + effect.Alpha = input.ReadSingle(); + return effect; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/SongReader.cs b/src/Content/ContentReaders/SongReader.cs new file mode 100644 index 0000000..2c921d5 --- /dev/null +++ b/src/Content/ContentReaders/SongReader.cs @@ -0,0 +1,65 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.IO; + +using Microsoft.Xna.Framework.Media; +using Microsoft.Xna.Framework.Utilities; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class SongReader : ContentTypeReader + { + #region Private Supported File Extensions Variable + + static string[] supportedExtensions = new string[] { ".flac", ".ogg" }; + + #endregion + + #region Internal Filename Normalizer Method + + internal static string Normalize(string fileName) + { + return Normalize(fileName, supportedExtensions); + } + + #endregion + + #region Protected Read Method + + protected internal override Song Read(ContentReader input, Song existingInstance) + { + string path = FileHelpers.ResolveRelativePath( + Path.Combine( + input.ContentManager.RootDirectoryFullPath, + input.AssetName + ), + input.ReadString() + ); + + /* The path string includes the ".wma" extension. Let's see if this + * file exists in a format we actually support... + */ + path = Normalize(path.Substring(0, path.Length - 4)); + if (String.IsNullOrEmpty(path)) + { + throw new ContentLoadException(); + } + + int durationMs = input.ReadInt32(); + + return new Song(path, durationMs); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/SoundEffectReader.cs b/src/Content/ContentReaders/SoundEffectReader.cs new file mode 100644 index 0000000..4e19aba --- /dev/null +++ b/src/Content/ContentReaders/SoundEffectReader.cs @@ -0,0 +1,92 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System.IO; + +using Microsoft.Xna.Framework.Audio; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class SoundEffectReader : ContentTypeReader + { + #region Private Supported File Extensions Variable + + static string[] supportedExtensions = new string[] { ".wav" }; + + #endregion + + #region Internal Filename Normalizer Method + + internal static string Normalize(string fileName) + { + return Normalize(fileName, supportedExtensions); + } + + #endregion + + #region Protected Read Method + + protected internal override SoundEffect Read( + ContentReader input, + SoundEffect existingInstance + ) { + // Format block length + uint formatLength = input.ReadUInt32(); + + // Wavedata format + ushort format = input.ReadUInt16(); + + // Number of channels + ushort channels = input.ReadUInt16(); + + // Sample rate + uint sampleRate = input.ReadUInt32(); + + // Averate bytes per second, unused + input.ReadUInt32(); + + // Block alignment, needed for MSADPCM + ushort blockAlign = input.ReadUInt16(); + + // Bit depth + ushort bitDepth = input.ReadUInt16(); + + // cbSize, unused + input.ReadUInt16(); + + // Seek past the rest of this crap + input.BaseStream.Seek(formatLength - 18, SeekOrigin.Current); + + // Wavedata + byte[] data = input.ReadBytes(input.ReadInt32()); + + // Loop information + uint loopStart = input.ReadUInt32(); + uint loopLength = input.ReadUInt32(); + + // Sound duration in milliseconds, unused + input.ReadUInt32(); + + return new SoundEffect( + input.AssetName, + data, + sampleRate, + channels, + loopStart, + loopLength, + format == 2, + (uint) ((format == 2) ? (((blockAlign / channels) - 6) * 2) : (bitDepth / 16)) + ); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/SpriteFontReader.cs b/src/Content/ContentReaders/SpriteFontReader.cs new file mode 100644 index 0000000..e2d5ec8 --- /dev/null +++ b/src/Content/ContentReaders/SpriteFontReader.cs @@ -0,0 +1,88 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +#region Using Statements +using System.Collections.Generic; + +using Microsoft.Xna.Framework.Graphics; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class SpriteFontReader : ContentTypeReader + { + #region Internal Constructor + + internal SpriteFontReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override SpriteFont Read( + ContentReader input, + SpriteFont existingInstance + ) { + if (existingInstance != null) + { + // Read the texture into the existing texture instance + input.ReadObject(existingInstance.textureValue); + + /* Discard the rest of the SpriteFont data as we are only + * reloading GPU resources for now + */ + input.ReadObject>(); + input.ReadObject>(); + input.ReadObject>(); + input.ReadInt32(); + input.ReadSingle(); + input.ReadObject>(); + if (input.ReadBoolean()) + { + input.ReadChar(); + } + return existingInstance; + } + else + { + // Create a fresh SpriteFont instance + Texture2D texture = input.ReadObject(); + List glyphs = input.ReadObject>(); + List cropping = input.ReadObject>(); + List charMap = input.ReadObject>(); + int lineSpacing = input.ReadInt32(); + float spacing = input.ReadSingle(); + List kerning = input.ReadObject>(); + char? defaultCharacter = null; + if (input.ReadBoolean()) + { + defaultCharacter = new char?(input.ReadChar()); + } + return new SpriteFont( + texture, + glyphs, + cropping, + charMap, + lineSpacing, + spacing, + kerning, + defaultCharacter + ); + } + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/StringReader.cs b/src/Content/ContentReaders/StringReader.cs new file mode 100644 index 0000000..01f9621 --- /dev/null +++ b/src/Content/ContentReaders/StringReader.cs @@ -0,0 +1,41 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class StringReader : ContentTypeReader + { + #region Internal Constructor + + internal StringReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override string Read( + ContentReader input, + string existingInstance + ) { + return input.ReadString(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/Texture2DReader.cs b/src/Content/ContentReaders/Texture2DReader.cs new file mode 100644 index 0000000..84b7773 --- /dev/null +++ b/src/Content/ContentReaders/Texture2DReader.cs @@ -0,0 +1,213 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +#region Using Statements +using System; + +using Microsoft.Xna.Framework.Graphics; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class Texture2DReader : ContentTypeReader + { + #region Private Supported File Extensions Variable + + private static string[] supportedExtensions = new string[] + { + ".bmp", ".gif", ".jpg", ".jpeg", ".png", ".tga", ".tif", ".tiff" + }; + + #endregion + + #region Internal Constructor + + internal Texture2DReader() + { + } + + #endregion + + #region Internal Filename Normalizer Method + + internal static string Normalize(string fileName) + { + return Normalize(fileName, supportedExtensions); + } + + #endregion + + #region Protected Read Method + + protected internal override Texture2D Read( + ContentReader reader, + Texture2D existingInstance + ) { + Texture2D texture = null; + + SurfaceFormat surfaceFormat; + if (reader.version < 5) + { + /* These integer values are based on the enum values + * from previous XNA versions. + * -flibit + */ + int legacyFormat = reader.ReadInt32(); + if (legacyFormat == 1) + { + surfaceFormat = SurfaceFormat.Color; + } + if (legacyFormat == 28) + { + surfaceFormat = SurfaceFormat.Dxt1; + } + else if (legacyFormat == 30) + { + surfaceFormat = SurfaceFormat.Dxt3; + } + else if (legacyFormat == 32) + { + surfaceFormat = SurfaceFormat.Dxt5; + } + else + { + throw new NotSupportedException( + "Unsupported legacy surface format." + ); + } + } + else + { + surfaceFormat = (SurfaceFormat) reader.ReadInt32(); + } + int width = reader.ReadInt32(); + int height = reader.ReadInt32(); + int levelCount = reader.ReadInt32(); + int levelCountOutput = levelCount; + + // Check to see if we need to convert the surface data + SurfaceFormat convertedFormat = surfaceFormat; + if ( surfaceFormat == SurfaceFormat.Dxt1 && + !reader.GraphicsDevice.GLDevice.SupportsDxt1 ) + { + convertedFormat = SurfaceFormat.Color; + } + else if ( ( surfaceFormat == SurfaceFormat.Dxt3 || + surfaceFormat == SurfaceFormat.Dxt5 ) && + !reader.GraphicsDevice.GLDevice.SupportsS3tc ) + { + convertedFormat = SurfaceFormat.Color; + } + + // Check for duplicate instances + if (existingInstance == null) + { + texture = new Texture2D( + reader.GraphicsDevice, + width, + height, + levelCountOutput > 1, + convertedFormat + ); + } + else + { + texture = existingInstance; + } + + for (int level = 0; level < levelCount; level += 1) + { + int levelDataSizeInBytes = reader.ReadInt32(); + byte[] levelData = null; // Don't assign this quite yet... + int levelWidth = width >> level; + int levelHeight = height >> level; + if (level >= levelCountOutput) + { + continue; + } + + // Convert the image data if required + if ( surfaceFormat == SurfaceFormat.Dxt1 && + !reader.GraphicsDevice.GLDevice.SupportsDxt1 ) + { + levelData = reader.ReadBytes(levelDataSizeInBytes); + levelData = DxtUtil.DecompressDxt1( + levelData, + levelWidth, + levelHeight + ); + } + else if ( surfaceFormat == SurfaceFormat.Dxt3 && + !reader.GraphicsDevice.GLDevice.SupportsS3tc ) + { + levelData = reader.ReadBytes(levelDataSizeInBytes); + levelData = DxtUtil.DecompressDxt3( + levelData, + levelWidth, + levelHeight + ); + } + else if ( surfaceFormat == SurfaceFormat.Dxt5 && + !reader.GraphicsDevice.GLDevice.SupportsS3tc ) + { + levelData = reader.ReadBytes(levelDataSizeInBytes); + levelData = DxtUtil.DecompressDxt5( + levelData, + levelWidth, + levelHeight + ); + } + + if ( levelData == null && + reader.BaseStream.GetType() != typeof(System.IO.MemoryStream) ) + { + /* If the ContentReader is not backed by a + * MemoryStream, we have to read the data in. + */ + levelData = reader.ReadBytes(levelDataSizeInBytes); + } + if (levelData != null) + { + /* If we had to convert the data, or get the data from a + * non-MemoryStream, we set the data with our levelData + * reference. + */ + texture.SetData(level, null, levelData, 0, levelData.Length); + } + else + { + /* Ideally, we didn't have to perform any conversion or + * unnecessary reading. Just throw the buffer directly + * into SetData, skipping a redundant byte[] copy. + */ + texture.SetData( + level, + null, + (((System.IO.MemoryStream) (reader.BaseStream)).GetBuffer()), + (int) reader.BaseStream.Position, + levelDataSizeInBytes + ); + reader.BaseStream.Seek( + levelDataSizeInBytes, + System.IO.SeekOrigin.Current + ); + } + + } + + return texture; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/Texture3DReader.cs b/src/Content/ContentReaders/Texture3DReader.cs new file mode 100644 index 0000000..8b2714b --- /dev/null +++ b/src/Content/ContentReaders/Texture3DReader.cs @@ -0,0 +1,78 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; + +using Microsoft.Xna.Framework.Graphics; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class Texture3DReader : ContentTypeReader + { + #region Protected Read Method + + protected internal override Texture3D Read( + ContentReader reader, + Texture3D existingInstance + ) { + Texture3D texture = null; + + SurfaceFormat format = (SurfaceFormat) reader.ReadInt32(); + int width = reader.ReadInt32(); + int height = reader.ReadInt32(); + int depth = reader.ReadInt32(); + int levelCount = reader.ReadInt32(); + + if (existingInstance == null) + { + texture = new Texture3D( + reader.GraphicsDevice, + width, + height, + depth, + levelCount > 1, + format + ); + } + else + { + texture = existingInstance; + } + + for (int i = 0; i < levelCount; i += 1) + { + int dataSize = reader.ReadInt32(); + byte[] data = reader.ReadBytes(dataSize); + texture.SetData( + i, + 0, + 0, + width, + height, + 0, + depth, + data, + 0, + dataSize + ); + + // Calculate dimensions of next mip level. + width = Math.Max(width >> 1, 1); + height = Math.Max(height >> 1, 1); + depth = Math.Max(depth >> 1, 1); + } + + return texture; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/TextureCubeReader.cs b/src/Content/ContentReaders/TextureCubeReader.cs new file mode 100644 index 0000000..6ab3a5b --- /dev/null +++ b/src/Content/ContentReaders/TextureCubeReader.cs @@ -0,0 +1,66 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using Microsoft.Xna.Framework.Graphics; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class TextureCubeReader : ContentTypeReader + { + #region Protected Read Method + + protected internal override TextureCube Read( + ContentReader reader, + TextureCube existingInstance + ) { + TextureCube textureCube = null; + + SurfaceFormat surfaceFormat = (SurfaceFormat) reader.ReadInt32(); + int size = reader.ReadInt32(); + int levels = reader.ReadInt32(); + + if (existingInstance == null) + { + textureCube = new TextureCube( + reader.GraphicsDevice, + size, + levels > 1, + surfaceFormat + ); + } + else + { + textureCube = existingInstance; + } + + for (int face = 0; face < 6; face += 1) + { + for (int i = 0; i < levels; i += 1) + { + int faceSize = reader.ReadInt32(); + byte[] faceData = reader.ReadBytes(faceSize); + textureCube.SetData( + (CubeMapFace) face, + i, + null, + faceData, + 0, + faceSize + ); + } + } + + return textureCube; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/TextureReader.cs b/src/Content/ContentReaders/TextureReader.cs new file mode 100644 index 0000000..55fd78e --- /dev/null +++ b/src/Content/ContentReaders/TextureReader.cs @@ -0,0 +1,29 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using Microsoft.Xna.Framework.Graphics; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class TextureReader : ContentTypeReader + { + #region Protected Read Method + + protected internal override Texture Read( + ContentReader reader, + Texture existingInstance + ) { + return existingInstance; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/TimeSpanReader.cs b/src/Content/ContentReaders/TimeSpanReader.cs new file mode 100644 index 0000000..dc6d943 --- /dev/null +++ b/src/Content/ContentReaders/TimeSpanReader.cs @@ -0,0 +1,43 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class TimeSpanReader : ContentTypeReader + { + #region Internal Constructor + + internal TimeSpanReader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override TimeSpan Read( + ContentReader input, + TimeSpan existingInstance + ) { + /* Could not find any information on this really but from + * all the searching it looks like the constructor of number + * of ticks is long so I have placed that here for now. + * long is a Int64 so we read with 64 + * PT2S + */ + return new TimeSpan(input.ReadInt64()); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/UInt16Reader.cs b/src/Content/ContentReaders/UInt16Reader.cs new file mode 100644 index 0000000..cb6e7a1 --- /dev/null +++ b/src/Content/ContentReaders/UInt16Reader.cs @@ -0,0 +1,33 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class UInt16Reader : ContentTypeReader + { + #region Internal Constructor + + internal UInt16Reader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override ushort Read( + ContentReader input, + ushort existingInstance + ) { + return input.ReadUInt16(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/UInt32Reader.cs b/src/Content/ContentReaders/UInt32Reader.cs new file mode 100644 index 0000000..bb3bd39 --- /dev/null +++ b/src/Content/ContentReaders/UInt32Reader.cs @@ -0,0 +1,33 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class UInt32Reader : ContentTypeReader + { + #region Internal Constructor + + internal UInt32Reader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override uint Read( + ContentReader input, + uint existingInstance + ) { + return input.ReadUInt32(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/UInt64Reader.cs b/src/Content/ContentReaders/UInt64Reader.cs new file mode 100644 index 0000000..79d3d36 --- /dev/null +++ b/src/Content/ContentReaders/UInt64Reader.cs @@ -0,0 +1,33 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class UInt64Reader : ContentTypeReader + { + #region Internal Constructor + + internal UInt64Reader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override ulong Read( + ContentReader input, + ulong existingInstance + ) { + return input.ReadUInt64(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/Vector2Reader.cs b/src/Content/ContentReaders/Vector2Reader.cs new file mode 100644 index 0000000..8bb9211 --- /dev/null +++ b/src/Content/ContentReaders/Vector2Reader.cs @@ -0,0 +1,33 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class Vector2Reader : ContentTypeReader + { + #region Internal Constructor + + internal Vector2Reader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override Vector2 Read( + ContentReader input, + Vector2 existingInstance + ) { + return input.ReadVector2(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/Vector3Reader.cs b/src/Content/ContentReaders/Vector3Reader.cs new file mode 100644 index 0000000..e85e6b1 --- /dev/null +++ b/src/Content/ContentReaders/Vector3Reader.cs @@ -0,0 +1,37 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class Vector3Reader : ContentTypeReader + { + #region Internal Constructor + + internal Vector3Reader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override Vector3 Read( + ContentReader input, + Vector3 existingInstance + ) { + return input.ReadVector3(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/Vector4Reader.cs b/src/Content/ContentReaders/Vector4Reader.cs new file mode 100644 index 0000000..c0f1e65 --- /dev/null +++ b/src/Content/ContentReaders/Vector4Reader.cs @@ -0,0 +1,37 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class Vector4Reader : ContentTypeReader + { + #region Internal Constructor + + internal Vector4Reader() + { + } + + #endregion + + #region Protected Read Method + + protected internal override Vector4 Read( + ContentReader input, + Vector4 existingInstance + ) { + return input.ReadVector4(); + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/VertexBufferReader.cs b/src/Content/ContentReaders/VertexBufferReader.cs new file mode 100644 index 0000000..696bd0c --- /dev/null +++ b/src/Content/ContentReaders/VertexBufferReader.cs @@ -0,0 +1,44 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ + +/* Derived from code by the Mono.Xna Team (Copyright 2006). + * Released under the MIT License. See monoxna.LICENSE for details. + */ +#endregion + +#region Using Statements +using Microsoft.Xna.Framework.Graphics; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + class VertexBufferReader : ContentTypeReader + { + #region Protected Read Method + + protected internal override VertexBuffer Read( + ContentReader input, + VertexBuffer existingInstance + ) { + VertexDeclaration declaration = input.ReadRawObject(); + int vertexCount = (int) input.ReadUInt32(); + byte[] data = input.ReadBytes(vertexCount * declaration.VertexStride); + + VertexBuffer buffer = new VertexBuffer( + input.GraphicsDevice, + declaration, + vertexCount, + BufferUsage.None + ); + buffer.SetData(data); + return buffer; + } + + #endregion + } +} diff --git a/src/Content/ContentReaders/VertexDeclarationReader.cs b/src/Content/ContentReaders/VertexDeclarationReader.cs new file mode 100644 index 0000000..313b2ca --- /dev/null +++ b/src/Content/ContentReaders/VertexDeclarationReader.cs @@ -0,0 +1,54 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using Microsoft.Xna.Framework.Graphics; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class VertexDeclarationReader : ContentTypeReader + { + #region Protected Read Method + + protected internal override VertexDeclaration Read( + ContentReader reader, + VertexDeclaration existingInstance + ) { + int vertexStride = reader.ReadInt32(); + int elementCount = reader.ReadInt32(); + VertexElement[] elements = new VertexElement[elementCount]; + for (int i = 0; i < elementCount; i += 1) + { + int offset = reader.ReadInt32(); + VertexElementFormat elementFormat = (VertexElementFormat) reader.ReadInt32(); + VertexElementUsage elementUsage = (VertexElementUsage) reader.ReadInt32(); + int usageIndex = reader.ReadInt32(); + elements[i] = new VertexElement( + offset, + elementFormat, + elementUsage, + usageIndex + ); + } + + /* TODO: This process generates alot of duplicate VertexDeclarations + * which in turn complicates other systems trying to share GPU resources + * like DX11 vertex input layouts. + * + * We should consider caching vertex declarations here and returning + * previously created declarations when they are in our cache. + */ + return new VertexDeclaration(vertexStride, elements); + } + + #endregion + } +} + diff --git a/src/Content/ContentReaders/VideoReader.cs b/src/Content/ContentReaders/VideoReader.cs new file mode 100644 index 0000000..7ef7c85 --- /dev/null +++ b/src/Content/ContentReaders/VideoReader.cs @@ -0,0 +1,71 @@ +#region License +/* FNA - XNA4 Reimplementation for Desktop Platforms + * Copyright 2009-2015 Ethan Lee and the MonoGame Team + * + * Released under the Microsoft Public License. + * See LICENSE for details. + */ +#endregion + +#region Using Statements +using System; +using System.IO; + +using Microsoft.Xna.Framework.Media; +using Microsoft.Xna.Framework.Utilities; +#endregion + +namespace Microsoft.Xna.Framework.Content +{ + internal class VideoReader : ContentTypeReader