From 438836078d5f64f9cc3b97c6edf50abc52375fd0 Mon Sep 17 00:00:00 2001 From: Dylan Wilson Date: Tue, 25 Jun 2019 23:20:58 +1000 Subject: [PATCH 01/15] almost worked out the generic json importer --- Source/Demos/Features/Content/Content.mgcb | 442 +++++++++--------- Source/Demos/Features/Content/example.xml | 9 + Source/Demos/Features/Demos/AnimationsDemo.cs | 2 +- .../SpriteSheetAnimationFactoryReader.cs | 3 +- .../Json/JsonContentImporter.cs | 15 + .../Json/JsonContentProcessor.cs | 23 + .../Json/JsonContentProcessorResult.cs | 7 + .../Json/JsonContentTypeWriter.cs | 29 ++ .../TexturePackerJsonImporter.cs | 1 + .../TextureAtlases/TexturePackerProcessor.cs | 1 + .../TexturePackerProcessorResult.cs | 4 +- .../Content/ContentReaderExtensions.cs | 7 +- .../Serialization/JsonContentTypeReader.cs | 59 +++ .../TextureAtlases/TexturePackerFile.cs | 2 +- .../TextureAtlases/TexturePackerMeta.cs | 2 +- .../TextureAtlases/TexturePackerPoint.cs | 2 +- .../TextureAtlases/TexturePackerRectangle.cs | 2 +- .../TextureAtlases/TexturePackerRegion.cs | 4 +- .../TextureAtlases/TexturePackerSize.cs | 2 +- 19 files changed, 384 insertions(+), 232 deletions(-) create mode 100644 Source/Demos/Features/Content/example.xml create mode 100644 Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentImporter.cs create mode 100644 Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentProcessor.cs create mode 100644 Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentProcessorResult.cs create mode 100644 Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentTypeWriter.cs create mode 100644 Source/MonoGame.Extended/Serialization/JsonContentTypeReader.cs rename Source/{MonoGame.Extended.Content.Pipeline => MonoGame.Extended}/TextureAtlases/TexturePackerFile.cs (83%) rename Source/{MonoGame.Extended.Content.Pipeline => MonoGame.Extended}/TextureAtlases/TexturePackerMeta.cs (92%) rename Source/{MonoGame.Extended.Content.Pipeline => MonoGame.Extended}/TextureAtlases/TexturePackerPoint.cs (84%) rename Source/{MonoGame.Extended.Content.Pipeline => MonoGame.Extended}/TextureAtlases/TexturePackerRectangle.cs (88%) rename Source/{MonoGame.Extended.Content.Pipeline => MonoGame.Extended}/TextureAtlases/TexturePackerRegion.cs (86%) rename Source/{MonoGame.Extended.Content.Pipeline => MonoGame.Extended}/TextureAtlases/TexturePackerSize.cs (83%) diff --git a/Source/Demos/Features/Content/Content.mgcb b/Source/Demos/Features/Content/Content.mgcb index 3fa77c22..0f748aca 100644 --- a/Source/Demos/Features/Content/Content.mgcb +++ b/Source/Demos/Features/Content/Content.mgcb @@ -31,12 +31,7 @@ /processor:TexturePackerProcessor /build:adventure-gui-atlas.json -#begin small-font.fnt -/importer:BitmapFontImporter -/processor:BitmapFontProcessor -/build:small-font.fnt - -#begin small-font_0.png +#begin Animations/fireball.png /importer:TextureImporter /processor:TextureProcessor /processorParam:ColorKeyColor=255,0,255,255 @@ -46,7 +41,41 @@ /processorParam:ResizeToPowerOfTwo=False /processorParam:MakeSquare=False /processorParam:TextureFormat=Color -/build:small-font_0.png +/build:Animations/fireball.png + +#begin Animations/motw.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Animations/motw.png + +#begin Animations/zombie.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Animations/zombie.png + +#begin Animations/zombie-animations.aa +/importer:AstridAnimatorImporter +/processor:AstridAnimatorProcessor +/build:Animations/zombie-animations.aa + +#begin Animations/zombie-atlas.json +/importer:JsonContentImporter +/processor:JsonContentProcessor +/build:Animations/zombie-atlas.json #begin Fonts/impact-32.fnt /importer:BitmapFontImporter @@ -82,19 +111,12 @@ /processorParam:TextureFormat=Color /build:Fonts/montserrat-32_0.png -#begin Textures/logo-square-512.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:Textures/logo-square-512.png +#begin small-font.fnt +/importer:BitmapFontImporter +/processor:BitmapFontProcessor +/build:small-font.fnt -#begin Textures/vignette.png +#begin small-font_0.png /importer:TextureImporter /processor:TextureProcessor /processorParam:ColorKeyColor=255,0,255,255 @@ -104,175 +126,7 @@ /processorParam:ResizeToPowerOfTwo=False /processorParam:MakeSquare=False /processorParam:TextureFormat=Color -/build:Textures/vignette.png - -#begin Textures/hills.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:Textures/hills.png - -#begin Textures/hills-sky.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:Textures/hills-sky.png - -#begin Textures/hills-clouds.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:Textures/hills-clouds.png - -#begin Textures/hills-4.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:Textures/hills-4.png - -#begin Textures/hills-3.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:Textures/hills-3.png - -#begin Textures/hills-2.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:Textures/hills-2.png - -#begin Textures/hills-1.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:Textures/hills-1.png - -#begin Textures/logo-square-128.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:Textures/logo-square-128.png - -#begin Textures/car-wheel.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:Textures/car-wheel.png - -#begin Textures/car-hull.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:Textures/car-hull.png - -#begin Textures/spike_ball.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:Textures/spike_ball.png - -#begin Textures/particle.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:Textures/particle.png - -#begin Textures/clipping-test.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:Textures/clipping-test.png - -#begin Textures/bg_sharbi.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:Textures/bg_sharbi.png +/build:small-font_0.png #begin Textures/axe.png /importer:TextureImporter @@ -286,7 +140,7 @@ /processorParam:TextureFormat=Color /build:Textures/axe.png -#begin Animations/fireball.png +#begin Textures/bg_sharbi.png /importer:TextureImporter /processor:TextureProcessor /processorParam:ColorKeyColor=255,0,255,255 @@ -296,9 +150,9 @@ /processorParam:ResizeToPowerOfTwo=False /processorParam:MakeSquare=False /processorParam:TextureFormat=Color -/build:Animations/fireball.png +/build:Textures/bg_sharbi.png -#begin Animations/motw.png +#begin Textures/car-hull.png /importer:TextureImporter /processor:TextureProcessor /processorParam:ColorKeyColor=255,0,255,255 @@ -308,19 +162,9 @@ /processorParam:ResizeToPowerOfTwo=False /processorParam:MakeSquare=False /processorParam:TextureFormat=Color -/build:Animations/motw.png +/build:Textures/car-hull.png -#begin Animations/zombie-animations.aa -/importer:AstridAnimatorImporter -/processor:AstridAnimatorProcessor -/build:Animations/zombie-animations.aa - -#begin Animations/zombie-atlas.json -/importer:TexturePackerJsonImporter -/processor:TexturePackerProcessor -/build:Animations/zombie-atlas.json - -#begin Animations/zombie.png +#begin Textures/car-wheel.png /importer:TextureImporter /processor:TextureProcessor /processorParam:ColorKeyColor=255,0,255,255 @@ -330,7 +174,175 @@ /processorParam:ResizeToPowerOfTwo=False /processorParam:MakeSquare=False /processorParam:TextureFormat=Color -/build:Animations/zombie.png +/build:Textures/car-wheel.png + +#begin Textures/clipping-test.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/clipping-test.png + +#begin Textures/colored_castle.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/colored_castle.png + +#begin Textures/hills.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/hills.png + +#begin Textures/hills-1.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/hills-1.png + +#begin Textures/hills-2.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/hills-2.png + +#begin Textures/hills-3.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/hills-3.png + +#begin Textures/hills-4.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/hills-4.png + +#begin Textures/hills-clouds.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/hills-clouds.png + +#begin Textures/hills-sky.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/hills-sky.png + +#begin Textures/logo-square-128.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/logo-square-128.png + +#begin Textures/logo-square-512.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/logo-square-512.png + +#begin Textures/particle.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/particle.png + +#begin Textures/spike_ball.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/spike_ball.png + +#begin Textures/vignette.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/vignette.png #begin TiledMaps/abstractTiles_sheet.png /importer:TextureImporter @@ -444,6 +456,11 @@ /processor:TiledMapProcessor /build:TiledMaps/level07.tmx +#begin TiledMaps/level08.tmx +/importer:TiledMapImporter +/processor:TiledMapProcessor +/build:TiledMaps/level08.tmx + #begin TiledMaps/non-uniform-tileset.png /importer:TextureImporter /processor:TextureProcessor @@ -492,20 +509,3 @@ /processorParam:TextureFormat=Color /build:TiledMaps/voxelTiles_sheet.png -#begin TiledMaps/level08.tmx -/importer:TiledMapImporter -/processor:TiledMapProcessor -/build:TiledMaps/level08.tmx - -#begin Textures/colored_castle.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:Textures/colored_castle.png - diff --git a/Source/Demos/Features/Content/example.xml b/Source/Demos/Features/Content/example.xml new file mode 100644 index 00000000..72d9102a --- /dev/null +++ b/Source/Demos/Features/Content/example.xml @@ -0,0 +1,9 @@ + + + + + 0.28 + 0.0 + + + \ No newline at end of file diff --git a/Source/Demos/Features/Demos/AnimationsDemo.cs b/Source/Demos/Features/Demos/AnimationsDemo.cs index f14e31b8..43690cab 100644 --- a/Source/Demos/Features/Demos/AnimationsDemo.cs +++ b/Source/Demos/Features/Demos/AnimationsDemo.cs @@ -217,7 +217,7 @@ namespace Features.Demos public void Draw(SpriteBatch spriteBatch) { - //spriteBatch.Draw(_sprite); + spriteBatch.Draw(_sprite, _transform); } public void Walk(float direction) diff --git a/Source/MonoGame.Extended.Animations/SpriteSheets/SpriteSheetAnimationFactoryReader.cs b/Source/MonoGame.Extended.Animations/SpriteSheets/SpriteSheetAnimationFactoryReader.cs index 597b1043..9b4baa67 100644 --- a/Source/MonoGame.Extended.Animations/SpriteSheets/SpriteSheetAnimationFactoryReader.cs +++ b/Source/MonoGame.Extended.Animations/SpriteSheets/SpriteSheetAnimationFactoryReader.cs @@ -9,7 +9,8 @@ namespace MonoGame.Extended.Animations.SpriteSheets { protected override SpriteSheetAnimationFactory Read(ContentReader reader, SpriteSheetAnimationFactory existingInstance) { - var textureAtlasAssetName = reader.GetRelativeAssetName(reader.ReadString()); + var relativeName = reader.ReadString(); + var textureAtlasAssetName = reader.GetRelativeAssetName(relativeName); var textureAtlas = reader.ContentManager.Load(textureAtlasAssetName); var frameCount = reader.ReadInt32(); var regions = new List(); diff --git a/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentImporter.cs b/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentImporter.cs new file mode 100644 index 00000000..437d7eb1 --- /dev/null +++ b/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentImporter.cs @@ -0,0 +1,15 @@ +using System.IO; +using Microsoft.Xna.Framework.Content.Pipeline; + +namespace MonoGame.Extended.Content.Pipeline.Json +{ + [ContentImporter(".json", DefaultProcessor = nameof(JsonContentProcessor), DisplayName = "JSON Importer - MonoGame.Extended")] + public class JsonContentImporter : ContentImporter> + { + public override ContentImporterResult Import(string filename, ContentImporterContext context) + { + var json = File.ReadAllText(filename); + return new ContentImporterResult(filename, json); + } + } +} diff --git a/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentProcessor.cs b/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentProcessor.cs new file mode 100644 index 00000000..ea4d2126 --- /dev/null +++ b/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentProcessor.cs @@ -0,0 +1,23 @@ +using System; +using Microsoft.Xna.Framework.Content.Pipeline; + +namespace MonoGame.Extended.Content.Pipeline.Json +{ + [ContentProcessor(DisplayName = "JSON Processor - MonoGame.Extended")] + public class JsonContentProcessor : ContentProcessor, JsonContentProcessorResult> + { + public override JsonContentProcessorResult Process(ContentImporterResult input, ContentProcessorContext context) + { + try + { + var output = new JsonContentProcessorResult { Json = input.Data }; + return output; + } + catch (Exception ex) + { + context.Logger.LogMessage("Error {0}", ex); + throw; + } + } + } +} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentProcessorResult.cs b/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentProcessorResult.cs new file mode 100644 index 00000000..cd073cbc --- /dev/null +++ b/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentProcessorResult.cs @@ -0,0 +1,7 @@ +namespace MonoGame.Extended.Content.Pipeline.Json +{ + public class JsonContentProcessorResult + { + public string Json { get; set; } + } +} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentTypeWriter.cs b/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentTypeWriter.cs new file mode 100644 index 00000000..eea12719 --- /dev/null +++ b/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentTypeWriter.cs @@ -0,0 +1,29 @@ +using Microsoft.Xna.Framework.Content.Pipeline; +using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler; +using MonoGame.Extended.Sprites; + +namespace MonoGame.Extended.Content.Pipeline.Json +{ + [ContentTypeWriter] + public class JsonContentTypeWriter : ContentTypeWriter + { + protected override void Write(ContentWriter writer, JsonContentProcessorResult result) + { + writer.Write(result.Json); + } + + public override string GetRuntimeReader(TargetPlatform targetPlatform) + { + return "MonoGame.Extended.Serialization.JsonContentTypeReader, MonoGame.Extended"; + } + + public override string GetRuntimeType(TargetPlatform targetPlatform) + { + var type = typeof(Sprite); + var readerType = type.Namespace + ".JsonContentTypeReader, " + type.AssemblyQualifiedName; + return "GetRuntimeType"; + + //return typeof(object).AssemblyQualifiedName;// "MonoGame.Extended.Serialization.JsonContentTypeReader, MonoGame.Extended"; + } + } +} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerJsonImporter.cs b/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerJsonImporter.cs index ed2157bb..31fa9466 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerJsonImporter.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerJsonImporter.cs @@ -1,5 +1,6 @@ using System.IO; using Microsoft.Xna.Framework.Content.Pipeline; +using MonoGame.Extended.TextureAtlases; using Newtonsoft.Json; namespace MonoGame.Extended.Content.Pipeline.TextureAtlases diff --git a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerProcessor.cs b/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerProcessor.cs index 7c3be8d8..1f14ee77 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerProcessor.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerProcessor.cs @@ -1,5 +1,6 @@ using System; using Microsoft.Xna.Framework.Content.Pipeline; +using MonoGame.Extended.TextureAtlases; namespace MonoGame.Extended.Content.Pipeline.TextureAtlases { diff --git a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerProcessorResult.cs b/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerProcessorResult.cs index 399662ea..a996259d 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerProcessorResult.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerProcessorResult.cs @@ -1,4 +1,6 @@ -namespace MonoGame.Extended.Content.Pipeline.TextureAtlases +using MonoGame.Extended.TextureAtlases; + +namespace MonoGame.Extended.Content.Pipeline.TextureAtlases { public class TexturePackerProcessorResult { diff --git a/Source/MonoGame.Extended/Content/ContentReaderExtensions.cs b/Source/MonoGame.Extended/Content/ContentReaderExtensions.cs index ef33841f..f4c51a4f 100644 --- a/Source/MonoGame.Extended/Content/ContentReaderExtensions.cs +++ b/Source/MonoGame.Extended/Content/ContentReaderExtensions.cs @@ -15,10 +15,15 @@ namespace MonoGame.Extended.Content return (GraphicsDevice)_contentReaderGraphicsDeviceFieldInfo.GetValue(contentReader); } + public static string RemoveExtension(string path) + { + return Path.ChangeExtension(path, null).TrimEnd('.'); + } + public static string GetRelativeAssetName(this ContentReader contentReader, string relativeName) { var assetDirectory = Path.GetDirectoryName(contentReader.AssetName); - var assetName = Path.Combine(assetDirectory, relativeName).Replace('\\', '/'); + var assetName = RemoveExtension(Path.Combine(assetDirectory, relativeName).Replace('\\', '/')); return ShortenRelativePath(assetName); } diff --git a/Source/MonoGame.Extended/Serialization/JsonContentTypeReader.cs b/Source/MonoGame.Extended/Serialization/JsonContentTypeReader.cs new file mode 100644 index 00000000..8182c800 --- /dev/null +++ b/Source/MonoGame.Extended/Serialization/JsonContentTypeReader.cs @@ -0,0 +1,59 @@ +using System; +using System.IO; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended.Content; +using MonoGame.Extended.TextureAtlases; +using Newtonsoft.Json; + +namespace MonoGame.Extended.Serialization +{ + public class JsonContentTypeReader : ContentTypeReader + { + //protected override object Read(ContentReader input, object existingInstance) + //{ + // var json = input.ReadString(); + // return null; + //} + + public JsonContentTypeReader() : base(typeof(TextureAtlas)) + { + } + + protected override object Read(ContentReader reader, object existingInstance) + { + var json = reader.ReadString(); + + using (var stringReader = new StringReader(json)) + using (var jsonReader = new JsonTextReader(stringReader)) + { + var serializer = new JsonSerializer(); + var texturePackerFile = serializer.Deserialize(jsonReader); + + + var assetName = reader.GetRelativeAssetName(texturePackerFile.Metadata.Image); + var texture = reader.ContentManager.Load(assetName); + var atlas = new TextureAtlas(assetName, texture); + + var regionCount = texturePackerFile.Regions.Count; + + for (var i = 0; i < regionCount; i++) + { + atlas.CreateRegion( + ContentReaderExtensions.RemoveExtension(texturePackerFile.Regions[i].Filename), + texturePackerFile.Regions[i].Frame.X, + texturePackerFile.Regions[i].Frame.Y, + texturePackerFile.Regions[i].Frame.Width, + texturePackerFile.Regions[i].Frame.Height); + } + + return atlas; + + + + + return texturePackerFile; + } + } + } +} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerFile.cs b/Source/MonoGame.Extended/TextureAtlases/TexturePackerFile.cs similarity index 83% rename from Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerFile.cs rename to Source/MonoGame.Extended/TextureAtlases/TexturePackerFile.cs index e9c461f4..69935842 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerFile.cs +++ b/Source/MonoGame.Extended/TextureAtlases/TexturePackerFile.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace MonoGame.Extended.Content.Pipeline.TextureAtlases +namespace MonoGame.Extended.TextureAtlases { public class TexturePackerFile { diff --git a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerMeta.cs b/Source/MonoGame.Extended/TextureAtlases/TexturePackerMeta.cs similarity index 92% rename from Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerMeta.cs rename to Source/MonoGame.Extended/TextureAtlases/TexturePackerMeta.cs index 96064190..9ac6939b 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerMeta.cs +++ b/Source/MonoGame.Extended/TextureAtlases/TexturePackerMeta.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace MonoGame.Extended.Content.Pipeline.TextureAtlases +namespace MonoGame.Extended.TextureAtlases { public class TexturePackerMeta { diff --git a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerPoint.cs b/Source/MonoGame.Extended/TextureAtlases/TexturePackerPoint.cs similarity index 84% rename from Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerPoint.cs rename to Source/MonoGame.Extended/TextureAtlases/TexturePackerPoint.cs index 15379c5f..c4444f5c 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerPoint.cs +++ b/Source/MonoGame.Extended/TextureAtlases/TexturePackerPoint.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace MonoGame.Extended.Content.Pipeline.TextureAtlases +namespace MonoGame.Extended.TextureAtlases { public class TexturePackerPoint { diff --git a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerRectangle.cs b/Source/MonoGame.Extended/TextureAtlases/TexturePackerRectangle.cs similarity index 88% rename from Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerRectangle.cs rename to Source/MonoGame.Extended/TextureAtlases/TexturePackerRectangle.cs index ec5c2695..3af4ee05 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerRectangle.cs +++ b/Source/MonoGame.Extended/TextureAtlases/TexturePackerRectangle.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace MonoGame.Extended.Content.Pipeline.TextureAtlases +namespace MonoGame.Extended.TextureAtlases { public class TexturePackerRectangle { diff --git a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerRegion.cs b/Source/MonoGame.Extended/TextureAtlases/TexturePackerRegion.cs similarity index 86% rename from Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerRegion.cs rename to Source/MonoGame.Extended/TextureAtlases/TexturePackerRegion.cs index f109bdb6..b38d4ebb 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerRegion.cs +++ b/Source/MonoGame.Extended/TextureAtlases/TexturePackerRegion.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace MonoGame.Extended.Content.Pipeline.TextureAtlases +namespace MonoGame.Extended.TextureAtlases { public class TexturePackerRegion { @@ -27,7 +27,7 @@ namespace MonoGame.Extended.Content.Pipeline.TextureAtlases public override string ToString() { - return string.Format("{0} {1}", Filename, Frame); + return $"{Filename} {Frame}"; } } } \ No newline at end of file diff --git a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerSize.cs b/Source/MonoGame.Extended/TextureAtlases/TexturePackerSize.cs similarity index 83% rename from Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerSize.cs rename to Source/MonoGame.Extended/TextureAtlases/TexturePackerSize.cs index 7e3fce8d..6a0c8f73 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/TextureAtlases/TexturePackerSize.cs +++ b/Source/MonoGame.Extended/TextureAtlases/TexturePackerSize.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace MonoGame.Extended.Content.Pipeline.TextureAtlases +namespace MonoGame.Extended.TextureAtlases { public class TexturePackerSize { From 321977ff8a1d300db3aba5e5690be73785ce9b8f Mon Sep 17 00:00:00 2001 From: Dylan Wilson Date: Wed, 26 Jun 2019 23:01:38 +1000 Subject: [PATCH 02/15] very nearly fully working json content reader --- Source/Demos/Features/Content/Content.mgcb | 1 + Source/Demos/Features/Demos/AnimationsDemo.cs | 4 + .../Json/JsonContentProcessor.cs | 10 +- .../Json/JsonContentProcessorResult.cs | 1 + .../Json/JsonContentTypeWriter.cs | 12 +- .../Serialization/JsonContentTypeReader.cs | 136 +++++++++++++----- 6 files changed, 119 insertions(+), 45 deletions(-) diff --git a/Source/Demos/Features/Content/Content.mgcb b/Source/Demos/Features/Content/Content.mgcb index 0f748aca..2ef3dafd 100644 --- a/Source/Demos/Features/Content/Content.mgcb +++ b/Source/Demos/Features/Content/Content.mgcb @@ -75,6 +75,7 @@ #begin Animations/zombie-atlas.json /importer:JsonContentImporter /processor:JsonContentProcessor +/processorParam:ContentType=TextureAtlas /build:Animations/zombie-atlas.json #begin Fonts/impact-32.fnt diff --git a/Source/Demos/Features/Demos/AnimationsDemo.cs b/Source/Demos/Features/Demos/AnimationsDemo.cs index 43690cab..7b5a7344 100644 --- a/Source/Demos/Features/Demos/AnimationsDemo.cs +++ b/Source/Demos/Features/Demos/AnimationsDemo.cs @@ -1,11 +1,13 @@ using System; using System.Linq; using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using MonoGame.Extended; using MonoGame.Extended.Animations; using MonoGame.Extended.Animations.SpriteSheets; +using MonoGame.Extended.Serialization; using MonoGame.Extended.Sprites; using MonoGame.Extended.TextureAtlases; @@ -23,6 +25,8 @@ namespace Features.Demos public AnimationsDemo(GameMain game) : base(game) { + ContentTypeReaderManager.AddTypeCreator("TextureAtlas", () => new TextureAtlasJsonContentTypeReader()); + ContentTypeReaderManager.AddTypeCreator("Default", () => new JsonContentTypeReader()); } protected override void Initialize() diff --git a/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentProcessor.cs b/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentProcessor.cs index ea4d2126..6be4ac36 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentProcessor.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentProcessor.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using Microsoft.Xna.Framework.Content.Pipeline; namespace MonoGame.Extended.Content.Pipeline.Json @@ -6,11 +7,18 @@ namespace MonoGame.Extended.Content.Pipeline.Json [ContentProcessor(DisplayName = "JSON Processor - MonoGame.Extended")] public class JsonContentProcessor : ContentProcessor, JsonContentProcessorResult> { + [DefaultValue(typeof(Type), "System.Object")] + public string ContentType { get; set; } + public override JsonContentProcessorResult Process(ContentImporterResult input, ContentProcessorContext context) { try { - var output = new JsonContentProcessorResult { Json = input.Data }; + var output = new JsonContentProcessorResult + { + ContentType = ContentType, + Json = input.Data + }; return output; } catch (Exception ex) diff --git a/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentProcessorResult.cs b/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentProcessorResult.cs index cd073cbc..eaef99eb 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentProcessorResult.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentProcessorResult.cs @@ -2,6 +2,7 @@ { public class JsonContentProcessorResult { + public string ContentType { get; set; } public string Json { get; set; } } } \ No newline at end of file diff --git a/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentTypeWriter.cs b/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentTypeWriter.cs index eea12719..c221922b 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentTypeWriter.cs +++ b/Source/MonoGame.Extended.Content.Pipeline/Json/JsonContentTypeWriter.cs @@ -1,29 +1,27 @@ using Microsoft.Xna.Framework.Content.Pipeline; using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler; -using MonoGame.Extended.Sprites; namespace MonoGame.Extended.Content.Pipeline.Json { [ContentTypeWriter] public class JsonContentTypeWriter : ContentTypeWriter { + private string _runtimeType; + protected override void Write(ContentWriter writer, JsonContentProcessorResult result) { + _runtimeType = result.ContentType; writer.Write(result.Json); } public override string GetRuntimeReader(TargetPlatform targetPlatform) { - return "MonoGame.Extended.Serialization.JsonContentTypeReader, MonoGame.Extended"; + return _runtimeType;// "MonoGame.Extended.Serialization.JsonContentTypeReader, MonoGame.Extended"; } public override string GetRuntimeType(TargetPlatform targetPlatform) { - var type = typeof(Sprite); - var readerType = type.Namespace + ".JsonContentTypeReader, " + type.AssemblyQualifiedName; - return "GetRuntimeType"; - - //return typeof(object).AssemblyQualifiedName;// "MonoGame.Extended.Serialization.JsonContentTypeReader, MonoGame.Extended"; + return _runtimeType;// "MonoGame.Extended.Serialization.JsonContentTypeReader, MonoGame.Extended"; } } } \ No newline at end of file diff --git a/Source/MonoGame.Extended/Serialization/JsonContentTypeReader.cs b/Source/MonoGame.Extended/Serialization/JsonContentTypeReader.cs index 8182c800..c97829b9 100644 --- a/Source/MonoGame.Extended/Serialization/JsonContentTypeReader.cs +++ b/Source/MonoGame.Extended/Serialization/JsonContentTypeReader.cs @@ -8,19 +8,9 @@ using Newtonsoft.Json; namespace MonoGame.Extended.Serialization { - public class JsonContentTypeReader : ContentTypeReader + public class JsonContentTypeReader : ContentTypeReader { - //protected override object Read(ContentReader input, object existingInstance) - //{ - // var json = input.ReadString(); - // return null; - //} - - public JsonContentTypeReader() : base(typeof(TextureAtlas)) - { - } - - protected override object Read(ContentReader reader, object existingInstance) + protected override T Read(ContentReader reader, T existingInstance) { var json = reader.ReadString(); @@ -28,32 +18,104 @@ namespace MonoGame.Extended.Serialization using (var jsonReader = new JsonTextReader(stringReader)) { var serializer = new JsonSerializer(); - var texturePackerFile = serializer.Deserialize(jsonReader); - - - var assetName = reader.GetRelativeAssetName(texturePackerFile.Metadata.Image); - var texture = reader.ContentManager.Load(assetName); - var atlas = new TextureAtlas(assetName, texture); - - var regionCount = texturePackerFile.Regions.Count; - - for (var i = 0; i < regionCount; i++) - { - atlas.CreateRegion( - ContentReaderExtensions.RemoveExtension(texturePackerFile.Regions[i].Filename), - texturePackerFile.Regions[i].Frame.X, - texturePackerFile.Regions[i].Frame.Y, - texturePackerFile.Regions[i].Frame.Width, - texturePackerFile.Regions[i].Frame.Height); - } - - return atlas; - - - - - return texturePackerFile; + return serializer.Deserialize(jsonReader); } } } + + public class TextureAtlasJsonContentTypeReader : JsonContentTypeReader + { + private TexturePackerFile Load(ContentReader reader) + { + var json = reader.ReadString(); + + using (var stringReader = new StringReader(json)) + using (var jsonReader = new JsonTextReader(stringReader)) + { + var serializer = new JsonSerializer(); + return serializer.Deserialize(jsonReader); + } + } + + protected override TextureAtlas Read(ContentReader reader, TextureAtlas existingInstance) + { + var texturePackerFile = Load(reader); + var assetName = reader.GetRelativeAssetName(texturePackerFile.Metadata.Image); + var texture = reader.ContentManager.Load(assetName); + var atlas = new TextureAtlas(assetName, texture); + + var regionCount = texturePackerFile.Regions.Count; + + for (var i = 0; i < regionCount; i++) + { + atlas.CreateRegion( + ContentReaderExtensions.RemoveExtension(texturePackerFile.Regions[i].Filename), + texturePackerFile.Regions[i].Frame.X, + texturePackerFile.Regions[i].Frame.Y, + texturePackerFile.Regions[i].Frame.Width, + texturePackerFile.Regions[i].Frame.Height); + } + + return atlas; + } + } + + //public abstract class JsonContentTypeReader : ContentTypeReader + //{ + // protected abstract TOutput OnDeserialize(ContentReader reader, TInput texturePackerFile); + + // protected override TOutput Read(ContentReader reader, TOutput existingInstance) + // { + // var json = reader.ReadString(); + + // using (var stringReader = new StringReader(json)) + // using (var jsonReader = new JsonTextReader(stringReader)) + // { + // var serializer = new JsonSerializer(); + // var input = serializer.Deserialize(jsonReader); + // return OnDeserialize(reader, input); + // } + // } + //} + + //public class JsonContentTypeReader : ContentTypeReader + //{ + // public JsonContentTypeReader(string blah) : base(typeof(object)) + // { + // } + + // protected override void Initialize(ContentTypeReaderManager manager) + // { + // base.Initialize(manager); + // } + + // protected override object Read(ContentReader input, object existingInstance) + // { + // return null; + // } + //} + + //public class TexturePackerJsonContentTypeReader : JsonContentTypeReader + //{ + // protected override TextureAtlas OnDeserialize(ContentReader reader, TexturePackerFile texturePackerFile) + // { + // var assetName = reader.GetRelativeAssetName(texturePackerFile.Metadata.Image); + // var texture = reader.ContentManager.Load(assetName); + // var atlas = new TextureAtlas(assetName, texture); + + // var regionCount = texturePackerFile.Regions.Count; + + // for (var i = 0; i < regionCount; i++) + // { + // atlas.CreateRegion( + // ContentReaderExtensions.RemoveExtension(texturePackerFile.Regions[i].Filename), + // texturePackerFile.Regions[i].Frame.X, + // texturePackerFile.Regions[i].Frame.Y, + // texturePackerFile.Regions[i].Frame.Width, + // texturePackerFile.Regions[i].Frame.Height); + // } + + // return atlas; + // } + //} } \ No newline at end of file From 54ee97a8bb2bce663c82af95e03315efdd2bbf4d Mon Sep 17 00:00:00 2001 From: Jon Seaman Date: Sun, 30 Jun 2019 00:35:42 -0700 Subject: [PATCH 03/15] Create function to draw an ellipse. (#613) --- .../MonoGame.Extended/Math/ShapeExtensions.cs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/Source/MonoGame.Extended/Math/ShapeExtensions.cs b/Source/MonoGame.Extended/Math/ShapeExtensions.cs index 51ea932e..30a0b59b 100644 --- a/Source/MonoGame.Extended/Math/ShapeExtensions.cs +++ b/Source/MonoGame.Extended/Math/ShapeExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Net.NetworkInformation; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using MonoGame.Extended.Shapes; @@ -276,6 +277,21 @@ namespace MonoGame.Extended DrawPolygon(spriteBatch, new Vector2(x, y), CreateCircle(radius, sides), color, thickness); } + /// + /// Draw an ellipse. + /// + /// The destination drawing surface + /// Center of the ellipse + /// Radius of the ellipse + /// The number of sides to generate. + /// The color of the ellipse. + /// The thickness of the line around the ellipse. + public static void DrawEllipse(this SpriteBatch spriteBatch, Vector2 center, Vector2 radius, int sides, + Color color, float thickness = 1f) + { + DrawPolygon(spriteBatch, center, CreateEllipse(radius.X, radius.Y, sides), color, thickness); + } + private static Vector2[] CreateCircle(double radius, int sides) { const double max = 2.0*Math.PI; @@ -291,5 +307,20 @@ namespace MonoGame.Extended return points; } + + private static Vector2[] CreateEllipse(float rx, float ry, int sides) + { + var vertices = new Vector2[sides]; + + var t = 0.0; + var dt = 2.0 * Math.PI / sides; + for (var i = 0; i < sides; i++, t += dt) + { + var x = (float)(rx * Math.Cos(t)); + var y = (float)(ry * Math.Sin(t)); + vertices[i] = new Vector2(x, y); + } + return vertices; + } } } \ No newline at end of file From 2144ca871e667e806511bd826641cb5807e65c1f Mon Sep 17 00:00:00 2001 From: Marco Ferragina Date: Mon, 1 Jul 2019 06:44:06 +0200 Subject: [PATCH 04/15] ensure systems cleanup on world dispose (#611) --- Source/MonoGame.Extended.Entities/World.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/MonoGame.Extended.Entities/World.cs b/Source/MonoGame.Extended.Entities/World.cs index a4f34d47..022d4b8c 100644 --- a/Source/MonoGame.Extended.Entities/World.cs +++ b/Source/MonoGame.Extended.Entities/World.cs @@ -26,6 +26,9 @@ namespace MonoGame.Extended.Entities foreach (var drawSystem in _drawSystems) drawSystem.Dispose(); + _updateSystems.Clear(); + _drawSystems.Clear(); + base.Dispose(); } From 31b77e5689775899618285700a2bb93d5be9eda4 Mon Sep 17 00:00:00 2001 From: Jon Seaman Date: Sun, 30 Jun 2019 21:52:17 -0700 Subject: [PATCH 05/15] Improve collision demo (#612) * Replace square in center of level with stationary ball * Improve collision demo - Collisions between balls are smoother. - Fixed an issue with collision bounds not being set properly. (This is what made the collision appear unsmooth) --- Source/Demos/Features/Demos/CollisionDemo.cs | 89 +++++++++++++------ .../QuadTree/CollisionComponent.cs | 20 ++--- 2 files changed, 73 insertions(+), 36 deletions(-) diff --git a/Source/Demos/Features/Demos/CollisionDemo.cs b/Source/Demos/Features/Demos/CollisionDemo.cs index 77977625..dcc448b9 100644 --- a/Source/Demos/Features/Demos/CollisionDemo.cs +++ b/Source/Demos/Features/Demos/CollisionDemo.cs @@ -36,21 +36,21 @@ namespace Features.Demos _blankTexture = new Texture2D(GraphicsDevice, 1, 1); _blankTexture.SetData(new[] { Color.WhiteSmoke }); - var demoBall1 = new DemoBall(new Sprite(_spikeyBallTexture)) + var spikyBallLeft = new DemoBall(new Sprite(_spikeyBallTexture)) { Position = new Vector2(200, 240), Velocity = new Vector2(0, -120) }; - _actors.Add(demoBall1); + _actors.Add(spikyBallLeft); - var demoBall2 = new DemoBall(new Sprite(_spikeyBallTexture)) + var spikeyBallRight = new DemoBall(new Sprite(_spikeyBallTexture)) { Position = new Vector2(600, 240), Velocity = new Vector2(0, 120) }; - _actors.Add(demoBall2); + _actors.Add(spikeyBallRight); - var controllableBall = new DemoBall(new Sprite(_spikeyBallTexture)) + var controllableBall = new ControllableBall(new Sprite(_spikeyBallTexture)) { Position = new Vector2(400, 240), Velocity = new Vector2(0, 0) @@ -58,26 +58,26 @@ namespace Features.Demos _actors.Add(controllableBall); _controllableBall = controllableBall; - var wall1 = new DemoWall(new Sprite(_blankTexture)) + var topWall = new DemoWall(new Sprite(_blankTexture)) { Bounds = new RectangleF(0, 0, 800, 20), Position = new Vector2(0, 0) }; - _actors.Add(wall1); + _actors.Add(topWall); - var wall2 = new DemoWall(new Sprite(_blankTexture)) + var bottomWall = new DemoWall(new Sprite(_blankTexture)) { Position = new Vector2(0, 460), Bounds = new RectangleF(0, 0, 800, 20) }; - _actors.Add(wall2); + _actors.Add(bottomWall); - var centerWall = new DemoWall(new Sprite(_blankTexture)) + var spikeyBallCenter = new StationaryBall(new Sprite(_spikeyBallTexture)) { - Bounds = new RectangleF(0, 0, 50, 50), - Position = new Vector2(400, 200) + Position = new Vector2(400, 240), + Velocity = Vector2.Zero, }; - _actors.Add(centerWall); + _actors.Add(spikeyBallCenter); foreach (var actor in _actors) { @@ -126,13 +126,6 @@ namespace Features.Demos foreach (var actor in _actors) { actor.Draw(_spriteBatch); - if (actor.Bounds is RectangleF rect) - { - _spriteBatch.Draw(_blankTexture, rect.ToRectangle(), Color.WhiteSmoke); - } else if (actor.Bounds is CircleF circle) - { - _spriteBatch.Draw(_blankTexture, circle.Position, Color.WhiteSmoke); - } } _spriteBatch.End(); @@ -153,9 +146,10 @@ namespace Features.Demos Bounds = sprite.GetBoundingRectangle(new Transform2()); } - - public Vector2 Offset { get; set; } - + /// + /// Gets or sets the actor's position and updates teh actor's bounds + /// position. + /// public Vector2 Position { get { return _position; } @@ -166,8 +160,20 @@ namespace Features.Demos } } + /// + /// Gets or sets the actor's collision bounds. + /// public IShapeF Bounds { get; set; } + /// + /// Gets or sets how far the actor's collision bounds are offset from + /// the actor's position. + /// + public Vector2 Offset { get; set; } + + /// + /// Gets or sets the actor's velocity. + /// public Vector2 Velocity { get; set; } public virtual void OnCollision(CollisionEventArgs collisionInfo) @@ -201,14 +207,12 @@ namespace Features.Demos { public DemoBall(Sprite sprite) : base(sprite) { - Offset = new Vector2(75, 75); Bounds = new CircleF(Position + Offset, 60); } public override void Update(GameTime gameTime) { base.Update(gameTime); - Bounds.Position = Position; } public override void OnCollision(CollisionEventArgs collisionInfo) @@ -220,5 +224,40 @@ namespace Features.Demos } } + /// + /// Ball that doesn't move when collided with. + /// + class StationaryBall : DemoBall + { + public StationaryBall(Sprite sprite) : base(sprite) + { + } + + public override void OnCollision(CollisionEventArgs collisionInfo) + { + } + } + + /// + /// Player controlled ball. + /// + class ControllableBall : DemoBall + { + public ControllableBall(Sprite sprite) : base(sprite) + { + Bounds = new CircleF(Position + Offset, 60); + } + + public override void Update(GameTime gameTime) + { + base.Update(gameTime); + } + + public override void OnCollision(CollisionEventArgs collisionInfo) + { + Position -= collisionInfo.PenetrationVector; + } + } + #endregion } \ No newline at end of file diff --git a/Source/MonoGame.Extended.Collisions/QuadTree/CollisionComponent.cs b/Source/MonoGame.Extended.Collisions/QuadTree/CollisionComponent.cs index c8e009d3..7d4b9b2f 100644 --- a/Source/MonoGame.Extended.Collisions/QuadTree/CollisionComponent.cs +++ b/Source/MonoGame.Extended.Collisions/QuadTree/CollisionComponent.cs @@ -36,20 +36,13 @@ namespace MonoGame.Extended.Collisions /// public override void Update(GameTime gameTime) { - // Update bounding box locations. - foreach (var value in _targetDataDictionary.Values) - { - _collisionTree.Remove(value); - value.Bounds = value.Target.Bounds; - _collisionTree.Insert(value); - } - // Detect collisions foreach (var value in _targetDataDictionary.Values) { + _collisionTree.Remove(value); + var target = value.Target; - var collisions =_collisionTree.Query(target.Bounds) - .Where(data => data.Target != target); + var collisions =_collisionTree.Query(target.Bounds); // Generate list of collision Infos foreach (var other in collisions) @@ -61,7 +54,9 @@ namespace MonoGame.Extended.Collisions }; target.OnCollision(collisionInfo); + value.Bounds = value.Target.Bounds; } + _collisionTree.Insert(value); } } @@ -156,7 +151,10 @@ namespace MonoGame.Extended.Collisions private static Vector2 PenetrationVector(CircleF circ1, CircleF circ2) { - Debug.Assert(circ1.Intersects(circ2)); + if (!circ1.Intersects(circ2)) + { + return Vector2.Zero; + } var displacement = Point2.Displacement(circ1.Center, circ2.Center); From 130daf3e5e7dc02e1b2abc6244553314fd147eac Mon Sep 17 00:00:00 2001 From: rumkuhgel Date: Tue, 2 Jul 2019 02:38:14 +0200 Subject: [PATCH 06/15] Fix Clear method (#614) Make sure to clear the array before setting count to zero. --- Source/MonoGame.Extended/Collections/Bag.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/MonoGame.Extended/Collections/Bag.cs b/Source/MonoGame.Extended/Collections/Bag.cs index cfa59689..292c1d19 100644 --- a/Source/MonoGame.Extended/Collections/Bag.cs +++ b/Source/MonoGame.Extended/Collections/Bag.cs @@ -85,11 +85,11 @@ namespace MonoGame.Extended.Collections if(Count == 0) return; - Count = 0; - // non-primitive types are cleared so the garbage collector can release them if (!_isPrimitive) Array.Clear(_items, 0, Count); + + Count = 0; } public bool Contains(T element) @@ -191,4 +191,4 @@ namespace MonoGame.Extended.Collections } } } -} \ No newline at end of file +} From 26cfd55ef9d918d10a9e3aae057b27be73da46da Mon Sep 17 00:00:00 2001 From: Christopher Whitley Date: Tue, 16 Jul 2019 07:18:15 -0400 Subject: [PATCH 07/15] Check for existing layer name (#618) * Check for existing layer name Added check for an existing layer by name before adding new layer. If layer name already exists, a descriptive exception is thrown instead of the generic ArgumentException. * Update TiledMap.cs --- Source/MonoGame.Extended.Tiled/TiledMap.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/MonoGame.Extended.Tiled/TiledMap.cs b/Source/MonoGame.Extended.Tiled/TiledMap.cs index e2328b7c..d9b1d14b 100644 --- a/Source/MonoGame.Extended.Tiled/TiledMap.cs +++ b/Source/MonoGame.Extended.Tiled/TiledMap.cs @@ -69,6 +69,10 @@ namespace MonoGame.Extended.Tiled private void AddLayer(TiledMapLayer layer, bool root) { if (root) _layers.Add(layer); + + if (_layersByName.ContainsKey(layer.Name)) + throw new ArgumentException($"The TiledMap '{Name}' contains two or more layers named '{layer.Name}'. Please ensure all layers have unique names."); + _layersByName.Add(layer.Name, layer); switch(layer) From c2111d96536ef427bb0fc1ce9cace80d4d3e6bbf Mon Sep 17 00:00:00 2001 From: Dylan Wilson Date: Thu, 18 Jul 2019 20:19:17 +1000 Subject: [PATCH 08/15] Create FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..2fe98d26 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +patreon: craftworkgames From 340201efdf5ed60e1969891f3be7eb3ecb6adc65 Mon Sep 17 00:00:00 2001 From: Dylan Wilson Date: Thu, 18 Jul 2019 21:01:27 +1000 Subject: [PATCH 09/15] added github social media --- Logos/github-social-media-large.png | Bin 0 -> 33961 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Logos/github-social-media-large.png diff --git a/Logos/github-social-media-large.png b/Logos/github-social-media-large.png new file mode 100644 index 0000000000000000000000000000000000000000..70c5594ddb7ae1878d9c831c7006cf940bf0ccd3 GIT binary patch literal 33961 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 V*x!A7bjY*F%P33dN literal 0 HcmV?d00001 From 202ff98a3cfd3f5759639ac72c9d7cc821a921ad Mon Sep 17 00:00:00 2001 From: reidbhuntley Date: Sat, 27 Jul 2019 07:37:29 -0400 Subject: [PATCH 10/15] Implemented Transform3 class (#598) --- Source/MonoGame.Extended/Transform.cs | 130 ++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/Source/MonoGame.Extended/Transform.cs b/Source/MonoGame.Extended/Transform.cs index c178883a..53e81848 100644 --- a/Source/MonoGame.Extended/Transform.cs +++ b/Source/MonoGame.Extended/Transform.cs @@ -323,4 +323,134 @@ namespace MonoGame.Extended return $"Position: {Position}, Rotation: {Rotation}, Scale: {Scale}"; } } + + + ///

+ /// Represents the position, rotation, and scale of a three-dimensional game object. + /// + /// + /// + /// + /// Every game object has a transform which is used to store and manipulate the position, rotation and scale + /// of the object. Every transform can have a parent, which allows to apply position, rotation and scale to game + /// objects hierarchically. + /// + /// + class Transform3 : BaseTransform { + private Vector3 _position; + private Quaternion _rotation; + private Vector3 _scale = Vector3.One; + + public Transform3(Vector3? position = null, Quaternion? rotation = null, Vector3? scale = null) { + Position = position ?? Vector3.Zero; + Rotation = rotation ?? Quaternion.Identity; + Scale = scale ?? Vector3.One; + } + + /// + /// Gets the world position. + /// + /// + /// The world position. + /// + public Vector3 WorldPosition => WorldMatrix.Translation; + + /// + /// Gets the world scale. + /// + /// + /// The world scale. + /// + public Vector3 WorldScale { + get { + Vector3 scale = Vector3.Zero; + Quaternion rotation = Quaternion.Identity; + Vector3 translation = Vector3.Zero; + WorldMatrix.Decompose(out scale, out rotation, out translation); + return scale; + } + } + + + /// + /// Gets the world rotation quaternion in radians. + /// + /// + /// The world rotation quaternion in radians. + /// + public Quaternion WorldRotation { + get { + Vector3 scale = Vector3.Zero; + Quaternion rotation = Quaternion.Identity; + Vector3 translation = Vector3.Zero; + WorldMatrix.Decompose(out scale, out rotation, out translation); + return rotation; + } + } + + /// + /// Gets or sets the local position. + /// + /// + /// The local position. + /// + public Vector3 Position { + get { return _position; } + set { + _position = value; + LocalMatrixBecameDirty(); + WorldMatrixBecameDirty(); + } + } + + /// + /// Gets or sets the local rotation quaternion in radians. + /// + /// + /// The local rotation quaternion in radians. + /// + public Quaternion Rotation { + get { return _rotation; } + set { + _rotation = value; + LocalMatrixBecameDirty(); + WorldMatrixBecameDirty(); + } + } + + /// + /// Gets or sets the local scale. + /// + /// + /// The local scale. + /// + public Vector3 Scale { + get { return _scale; } + set { + _scale = value; + LocalMatrixBecameDirty(); + WorldMatrixBecameDirty(); + } + } + + protected internal override void RecalculateWorldMatrix(ref Matrix localMatrix, out Matrix matrix) { + if (Parent != null) { + Parent.GetWorldMatrix(out matrix); + Matrix.Multiply(ref localMatrix, ref matrix, out matrix); + } + else { + matrix = localMatrix; + } + } + + protected internal override void RecalculateLocalMatrix(out Matrix matrix) { + matrix = Matrix.CreateScale(_scale) * + Matrix.CreateFromQuaternion(_rotation) * + Matrix.CreateTranslation(_position); + } + + public override string ToString() { + return $"Position: {Position}, Rotation: {Rotation}, Scale: {Scale}"; + } + } } \ No newline at end of file From b2b90832a0eca227fcd1b6fb61cce1af4f01833e Mon Sep 17 00:00:00 2001 From: Dylan Wilson Date: Fri, 9 Aug 2019 21:15:26 +1000 Subject: [PATCH 11/15] exposed layer depth on the shape extensions to implement #623 --- Source/Demos/Features/Demos/ShapesDemo.cs | 53 ++++++ Source/Demos/Features/GameMain.cs | 1 + .../MonoGame.Extended/Math/ShapeExtensions.cs | 156 +++++++++--------- 3 files changed, 135 insertions(+), 75 deletions(-) create mode 100644 Source/Demos/Features/Demos/ShapesDemo.cs diff --git a/Source/Demos/Features/Demos/ShapesDemo.cs b/Source/Demos/Features/Demos/ShapesDemo.cs new file mode 100644 index 00000000..70a976dc --- /dev/null +++ b/Source/Demos/Features/Demos/ShapesDemo.cs @@ -0,0 +1,53 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended; +using MonoGame.Extended.Shapes; + +namespace Features.Demos +{ + public class ShapesDemo : DemoBase + { + private SpriteBatch _spriteBatch; + + public ShapesDemo(GameMain game) + : base(game) + { + } + + public override string Name => "Shapes"; + + private readonly Polygon _polygon = new Polygon(new[] + { + new Vector2(0, 0), + new Vector2(40, 0), + new Vector2(40, 40), + new Vector2(60, 40), + new Vector2(60, 60), + new Vector2(0, 60), + }); + + protected override void LoadContent() + { + _spriteBatch = new SpriteBatch(GraphicsDevice); + } + + protected override void Draw(GameTime gameTime) + { + _spriteBatch.Begin(samplerState: SamplerState.PointClamp, blendState: BlendState.AlphaBlend); + + _spriteBatch.FillRectangle(10, 10, 50, 50, Color.DarkRed); + _spriteBatch.DrawRectangle(10, 10, 50, 50, Color.Red, 2); + + _spriteBatch.DrawCircle(100, 100, 32, 32, Color.Green, 4); + _spriteBatch.DrawEllipse(new Vector2(200, 200), new Vector2(50, 25), 32, Color.Orange, 8); + + _spriteBatch.DrawLine(300, 300, 400, 100, Color.White, 6); + + _spriteBatch.DrawPoint(500, 300, Color.Brown, 64); + + _spriteBatch.DrawPolygon(new Vector2(600, 200), _polygon, Color.Aqua); + + _spriteBatch.End(); + } + } +} \ No newline at end of file diff --git a/Source/Demos/Features/GameMain.cs b/Source/Demos/Features/GameMain.cs index 8f5b1bf6..a527bdef 100644 --- a/Source/Demos/Features/GameMain.cs +++ b/Source/Demos/Features/GameMain.cs @@ -45,6 +45,7 @@ namespace Features //new GuiLayoutDemo(this), //new GuiDemo(this), //new ScreensDemo(this), + new ShapesDemo(this), new ViewportAdaptersDemo(this), new CollisionDemo(this), new TiledMapsDemo(this), diff --git a/Source/MonoGame.Extended/Math/ShapeExtensions.cs b/Source/MonoGame.Extended/Math/ShapeExtensions.cs index 30a0b59b..5424ada8 100644 --- a/Source/MonoGame.Extended/Math/ShapeExtensions.cs +++ b/Source/MonoGame.Extended/Math/ShapeExtensions.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Net.NetworkInformation; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using MonoGame.Extended.Shapes; @@ -19,7 +18,12 @@ namespace MonoGame.Extended if (_whitePixelTexture == null) { _whitePixelTexture = new Texture2D(spriteBatch.GraphicsDevice, 1, 1, false, SurfaceFormat.Color); - _whitePixelTexture.SetData(new[] {Color.White}); + _whitePixelTexture.SetData(new[] { Color.White }); + spriteBatch.Disposing += (sender, args) => + { + _whitePixelTexture?.Dispose(); + _whitePixelTexture = null; + }; } return _whitePixelTexture; @@ -34,10 +38,10 @@ namespace MonoGame.Extended /// The polygon to draw /// The color to use /// The thickness of the lines - public static void DrawPolygon(this SpriteBatch spriteBatch, Vector2 position, Polygon polygon, Color color, - float thickness = 1f) + /// /// The depth of the layer of this shape + public static void DrawPolygon(this SpriteBatch spriteBatch, Vector2 position, Polygon polygon, Color color, float thickness = 1f, int layerDepth = 0) { - DrawPolygon(spriteBatch, position, polygon.Vertices, color, thickness); + DrawPolygon(spriteBatch, position, polygon.Vertices, color, thickness, layerDepth); } /// @@ -49,61 +53,61 @@ namespace MonoGame.Extended /// The points to connect with lines /// The color to use /// The thickness of the lines - public static void DrawPolygon(this SpriteBatch spriteBatch, Vector2 offset, IReadOnlyList points, Color color, - float thickness = 1f) + /// The depth of the layer of this shape + public static void DrawPolygon(this SpriteBatch spriteBatch, Vector2 offset, IReadOnlyList points, Color color, float thickness = 1f, int layerDepth = 0) { if (points.Count == 0) return; if (points.Count == 1) { - DrawPoint(spriteBatch, points[0], color, (int) thickness); + DrawPoint(spriteBatch, points[0], color, (int)thickness); return; } var texture = GetTexture(spriteBatch); for (var i = 0; i < points.Count - 1; i++) - DrawPolygonEdge(spriteBatch, texture, points[i] + offset, points[i + 1] + offset, color, thickness); + DrawPolygonEdge(spriteBatch, texture, points[i] + offset, points[i + 1] + offset, color, thickness, layerDepth); - DrawPolygonEdge(spriteBatch, texture, points[points.Count - 1] + offset, points[0] + offset, color, - thickness); + DrawPolygonEdge(spriteBatch, texture, points[points.Count - 1] + offset, points[0] + offset, color, thickness, layerDepth); } - private static void DrawPolygonEdge(SpriteBatch spriteBatch, Texture2D texture, Vector2 point1, Vector2 point2, - Color color, float thickness) + private static void DrawPolygonEdge(SpriteBatch spriteBatch, Texture2D texture, Vector2 point1, Vector2 point2, Color color, float thickness, int layerDepth) { var length = Vector2.Distance(point1, point2); - var angle = (float) Math.Atan2(point2.Y - point1.Y, point2.X - point1.X); + var angle = (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X); var scale = new Vector2(length, thickness); - spriteBatch.Draw(texture, point1, null, color, angle, Vector2.Zero, scale, SpriteEffects.None, 0); + spriteBatch.Draw(texture, point1, null, color, angle, Vector2.Zero, scale, SpriteEffects.None, layerDepth); } /// - /// Draws a filled rectangle + /// Draws a filled rectangle /// /// The destination drawing surface /// The rectangle to draw /// The color to draw the rectangle in - public static void FillRectangle(this SpriteBatch spriteBatch, RectangleF rectangle, Color color) + /// The depth of the layer of this shape + public static void FillRectangle(this SpriteBatch spriteBatch, RectangleF rectangle, Color color, int layerDepth = 0) { - FillRectangle(spriteBatch, rectangle.Position, rectangle.Size, color); + FillRectangle(spriteBatch, rectangle.Position, rectangle.Size, color, layerDepth); } /// - /// Draws a filled rectangle + /// Draws a filled rectangle /// /// The destination drawing surface /// Where to draw /// The size of the rectangle /// The color to draw the rectangle in - public static void FillRectangle(this SpriteBatch spriteBatch, Vector2 location, Size2 size, Color color) + /// The depth of the layer of this shape + public static void FillRectangle(this SpriteBatch spriteBatch, Vector2 location, Size2 size, Color color, int layerDepth = 0) { - spriteBatch.Draw(GetTexture(spriteBatch), location, null, color, 0, Vector2.Zero, size, SpriteEffects.None, 0); + spriteBatch.Draw(GetTexture(spriteBatch), location, null, color, 0, Vector2.Zero, size, SpriteEffects.None, layerDepth); } /// - /// Draws a filled rectangle + /// Draws a filled rectangle /// /// The destination drawing surface /// The X coord of the left side @@ -111,19 +115,21 @@ namespace MonoGame.Extended /// Width /// Height /// The color to draw the rectangle in - public static void FillRectangle(this SpriteBatch spriteBatch, float x, float y, float width, float height, Color color) + /// The depth of the layer of this shape + public static void FillRectangle(this SpriteBatch spriteBatch, float x, float y, float width, float height, Color color, int layerDepth = 0) { - FillRectangle(spriteBatch, new Vector2(x, y), new Size2(width, height), color); + FillRectangle(spriteBatch, new Vector2(x, y), new Size2(width, height), color, layerDepth); } /// - /// Draws a rectangle with the thickness provided + /// Draws a rectangle with the thickness provided /// /// The destination drawing surface /// The rectangle to draw /// The color to draw the rectangle in /// The thickness of the lines - public static void DrawRectangle(this SpriteBatch spriteBatch, RectangleF rectangle, Color color, float thickness = 1f) + /// The depth of the layer of this shape + public static void DrawRectangle(this SpriteBatch spriteBatch, RectangleF rectangle, Color color, float thickness = 1f, int layerDepth = 0) { var texture = GetTexture(spriteBatch); var topLeft = new Vector2(rectangle.X, rectangle.Y); @@ -132,10 +138,10 @@ namespace MonoGame.Extended var horizontalScale = new Vector2(rectangle.Width, thickness); var verticalScale = new Vector2(thickness, rectangle.Height); - spriteBatch.Draw(texture, topLeft, null, color, 0f, Vector2.Zero, horizontalScale, SpriteEffects.None, 0); - spriteBatch.Draw(texture, topLeft, null, color, 0f, Vector2.Zero, verticalScale, SpriteEffects.None, 0); - spriteBatch.Draw(texture, topRight, null, color, 0f, Vector2.Zero, verticalScale, SpriteEffects.None, 0); - spriteBatch.Draw(texture, bottomLeft, null, color, 0f, Vector2.Zero, horizontalScale, SpriteEffects.None, 0); + spriteBatch.Draw(texture, topLeft, null, color, 0f, Vector2.Zero, horizontalScale, SpriteEffects.None, layerDepth); + spriteBatch.Draw(texture, topLeft, null, color, 0f, Vector2.Zero, verticalScale, SpriteEffects.None, layerDepth); + spriteBatch.Draw(texture, topRight, null, color, 0f, Vector2.Zero, verticalScale, SpriteEffects.None, layerDepth); + spriteBatch.Draw(texture, bottomLeft, null, color, 0f, Vector2.Zero, horizontalScale, SpriteEffects.None, layerDepth); } /// @@ -146,23 +152,23 @@ namespace MonoGame.Extended /// The size of the rectangle /// The color to draw the rectangle in /// The thickness of the line - public static void DrawRectangle(this SpriteBatch spriteBatch, Vector2 location, Size2 size, Color color, - float thickness = 1f) + /// The depth of the layer of this shape + public static void DrawRectangle(this SpriteBatch spriteBatch, Vector2 location, Size2 size, Color color, float thickness = 1f, int layerDepth = 0) { - DrawRectangle(spriteBatch, new RectangleF(location.X, location.Y, size.Width, size.Height), color, thickness); + DrawRectangle(spriteBatch, new RectangleF(location.X, location.Y, size.Width, size.Height), color, thickness, layerDepth); } /// /// Draws a rectangle outline. /// - public static void DrawRectangle(this SpriteBatch spriteBatch, float x, float y, float width, float height, Color color, float thickness = 1f) + public static void DrawRectangle(this SpriteBatch spriteBatch, float x, float y, float width, float height, Color color, float thickness = 1f, int layerDepth = 0) { - DrawRectangle(spriteBatch, new RectangleF(x, y, width, height), color, thickness); + DrawRectangle(spriteBatch, new RectangleF(x, y, width, height), color, thickness, layerDepth); } /// - /// Draws a line from point1 to point2 with an offset + /// Draws a line from point1 to point2 with an offset /// /// The destination drawing surface /// The X coord of the first point @@ -171,34 +177,34 @@ namespace MonoGame.Extended /// The Y coord of the second point /// The color to use /// The thickness of the line - public static void DrawLine(this SpriteBatch spriteBatch, float x1, float y1, float x2, float y2, Color color, - float thickness = 1f) + /// The depth of the layer of this shape + public static void DrawLine(this SpriteBatch spriteBatch, float x1, float y1, float x2, float y2, Color color, float thickness = 1f, int layerDepth = 0) { - DrawLine(spriteBatch, new Vector2(x1, y1), new Vector2(x2, y2), color, thickness); + DrawLine(spriteBatch, new Vector2(x1, y1), new Vector2(x2, y2), color, thickness, layerDepth); } /// - /// Draws a line from point1 to point2 with an offset + /// Draws a line from point1 to point2 with an offset /// /// The destination drawing surface /// The first point /// The second point /// The color to use /// The thickness of the line - public static void DrawLine(this SpriteBatch spriteBatch, Vector2 point1, Vector2 point2, Color color, - float thickness = 1f) + /// The depth of the layer of this shape + public static void DrawLine(this SpriteBatch spriteBatch, Vector2 point1, Vector2 point2, Color color, float thickness = 1f, int layerDepth = 0) { // calculate the distance between the two vectors var distance = Vector2.Distance(point1, point2); // calculate the angle between the two vectors - var angle = (float) Math.Atan2(point2.Y - point1.Y, point2.X - point1.X); + var angle = (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X); - DrawLine(spriteBatch, point1, distance, angle, color, thickness); + DrawLine(spriteBatch, point1, distance, angle, color, thickness, layerDepth); } /// - /// Draws a line from point1 to point2 with an offset + /// Draws a line from point1 to point2 with an offset /// /// The destination drawing surface /// The starting point @@ -206,48 +212,48 @@ namespace MonoGame.Extended /// The angle of this line from the starting point /// The color to use /// The thickness of the line - public static void DrawLine(this SpriteBatch spriteBatch, Vector2 point, float length, float angle, Color color, - float thickness = 1f) + /// The depth of the layer of this shape + public static void DrawLine(this SpriteBatch spriteBatch, Vector2 point, float length, float angle, Color color, float thickness = 1f, int layerDepth = 0) { var origin = new Vector2(0f, 0.5f); var scale = new Vector2(length, thickness); - spriteBatch.Draw(GetTexture(spriteBatch), point, null, color, angle, origin, scale, SpriteEffects.None, 0); + spriteBatch.Draw(GetTexture(spriteBatch), point, null, color, angle, origin, scale, SpriteEffects.None, layerDepth); } /// - /// Draws a point at the specified x, y position. The center of the point will be at the position. + /// Draws a point at the specified x, y position. The center of the point will be at the position. /// - public static void DrawPoint(this SpriteBatch spriteBatch, float x, float y, Color color, float size = 1f) + public static void DrawPoint(this SpriteBatch spriteBatch, float x, float y, Color color, float size = 1f, int layerDepth = 0) { - DrawPoint(spriteBatch, new Vector2(x, y), color, size); + DrawPoint(spriteBatch, new Vector2(x, y), color, size, layerDepth); } /// - /// Draws a point at the specified position. The center of the point will be at the position. + /// Draws a point at the specified position. The center of the point will be at the position. /// - public static void DrawPoint(this SpriteBatch spriteBatch, Vector2 position, Color color, float size = 1f) + public static void DrawPoint(this SpriteBatch spriteBatch, Vector2 position, Color color, float size = 1f, int layerDepth = 0) { - var scale = Vector2.One*size; - var offset = new Vector2(0.5f) - new Vector2(size*0.5f); - spriteBatch.Draw(GetTexture(spriteBatch), position + offset, null, color, 0f, Vector2.Zero, scale, SpriteEffects.None, 0); + var scale = Vector2.One * size; + var offset = new Vector2(0.5f) - new Vector2(size * 0.5f); + spriteBatch.Draw(GetTexture(spriteBatch), position + offset, null, color, 0f, Vector2.Zero, scale, SpriteEffects.None, layerDepth); } /// - /// Draw a circle from a shape + /// Draw a circle from a shape /// /// The destination drawing surface /// The circle shape to draw /// The number of sides to generate /// The color of the circle /// The thickness of the lines used - public static void DrawCircle(this SpriteBatch spriteBatch, CircleF circle, int sides, Color color, - float thickness = 1f) + /// The depth of the layer of this shape + public static void DrawCircle(this SpriteBatch spriteBatch, CircleF circle, int sides, Color color, float thickness = 1f, int layerDepth = 0) { - DrawCircle(spriteBatch, circle.Center, circle.Radius, sides, color, thickness); + DrawCircle(spriteBatch, circle.Center, circle.Radius, sides, color, thickness, layerDepth); } /// - /// Draw a circle + /// Draw a circle /// /// The destination drawing surface /// The center of the circle @@ -255,14 +261,14 @@ namespace MonoGame.Extended /// The number of sides to generate /// The color of the circle /// The thickness of the lines used - public static void DrawCircle(this SpriteBatch spriteBatch, Vector2 center, float radius, int sides, Color color, - float thickness = 1f) + /// The depth of the layer of this shape + public static void DrawCircle(this SpriteBatch spriteBatch, Vector2 center, float radius, int sides, Color color, float thickness = 1f, int layerDepth = 0) { - DrawPolygon(spriteBatch, center, CreateCircle(radius, sides), color, thickness); + DrawPolygon(spriteBatch, center, CreateCircle(radius, sides), color, thickness, layerDepth); } /// - /// Draw a circle + /// Draw a circle /// /// The destination drawing surface /// The center X of the circle @@ -271,14 +277,14 @@ namespace MonoGame.Extended /// The number of sides to generate /// The color of the circle /// The thickness of the line - public static void DrawCircle(this SpriteBatch spriteBatch, float x, float y, float radius, int sides, - Color color, float thickness = 1f) + /// The depth of the layer of this shape + public static void DrawCircle(this SpriteBatch spriteBatch, float x, float y, float radius, int sides, Color color, float thickness = 1f, int layerDepth = 0) { - DrawPolygon(spriteBatch, new Vector2(x, y), CreateCircle(radius, sides), color, thickness); + DrawPolygon(spriteBatch, new Vector2(x, y), CreateCircle(radius, sides), color, thickness, layerDepth); } /// - /// Draw an ellipse. + /// Draw an ellipse. /// /// The destination drawing surface /// Center of the ellipse @@ -286,22 +292,22 @@ namespace MonoGame.Extended /// The number of sides to generate. /// The color of the ellipse. /// The thickness of the line around the ellipse. - public static void DrawEllipse(this SpriteBatch spriteBatch, Vector2 center, Vector2 radius, int sides, - Color color, float thickness = 1f) + /// The depth of the layer of this shape + public static void DrawEllipse(this SpriteBatch spriteBatch, Vector2 center, Vector2 radius, int sides, Color color, float thickness = 1f, int layerDepth = 0) { - DrawPolygon(spriteBatch, center, CreateEllipse(radius.X, radius.Y, sides), color, thickness); + DrawPolygon(spriteBatch, center, CreateEllipse(radius.X, radius.Y, sides), color, thickness, layerDepth); } private static Vector2[] CreateCircle(double radius, int sides) { - const double max = 2.0*Math.PI; + const double max = 2.0 * Math.PI; var points = new Vector2[sides]; - var step = max/sides; + var step = max / sides; var theta = 0.0; for (var i = 0; i < sides; i++) { - points[i] = new Vector2((float) (radius*Math.Cos(theta)), (float) (radius*Math.Sin(theta))); + points[i] = new Vector2((float)(radius * Math.Cos(theta)), (float)(radius * Math.Sin(theta))); theta += step; } From bbd03e4d73c2d2cecdeecea3c9afd38cfbf1ad9c Mon Sep 17 00:00:00 2001 From: Dylan Wilson Date: Sun, 18 Aug 2019 18:27:48 +1000 Subject: [PATCH 12/15] fixed some long overdue bugs in the boxing viewport adapter --- .../Features/Demos/ViewportAdaptersDemo.cs | 14 +++- .../ViewportAdapters/BoxingViewportAdapter.cs | 83 +++++-------------- .../ScalingViewportAdapter.cs | 2 - .../ViewportAdapters/ViewportAdapter.cs | 9 +- 4 files changed, 35 insertions(+), 73 deletions(-) diff --git a/Source/Demos/Features/Demos/ViewportAdaptersDemo.cs b/Source/Demos/Features/Demos/ViewportAdaptersDemo.cs index 0e48ab9d..6c5ba0b0 100644 --- a/Source/Demos/Features/Demos/ViewportAdaptersDemo.cs +++ b/Source/Demos/Features/Demos/ViewportAdaptersDemo.cs @@ -40,7 +40,7 @@ namespace Features.Demos // the boxing viewport adapter uses letterboxing or pillarboxing to maintain aspect ratio // it's a little more complicated and needs to listen to the window client size changing event - _boxingViewportAdapter = new BoxingViewportAdapter(Window, GraphicsDevice, 800, 480, 88, 70); + _boxingViewportAdapter = new BoxingViewportAdapter(Window, GraphicsDevice, 800, 480);//, 88, 70); // typically you'll only ever want to use one viewport adapter for a game, but in this sample we'll be // switching between them. @@ -68,13 +68,13 @@ namespace Features.Demos Exit(); if (keyboardState.IsKeyDown(Keys.D)) - _currentViewportAdapter = _defaultViewportAdapter; + SwitchAdapter(_defaultViewportAdapter); if (keyboardState.IsKeyDown(Keys.S)) - _currentViewportAdapter = _scalingViewportAdapter; + SwitchAdapter(_scalingViewportAdapter); if (keyboardState.IsKeyDown(Keys.B)) - _currentViewportAdapter = _boxingViewportAdapter; + SwitchAdapter(_boxingViewportAdapter); // if we've changed the viewport adapter mid game we need to reset the viewport back to the window size // this wouldn't normally be required if you're only ever using one viewport adapter @@ -90,6 +90,12 @@ namespace Features.Demos base.Update(gameTime); } + private void SwitchAdapter(ViewportAdapter viewportAdapter) + { + _currentViewportAdapter?.Dispose(); + _currentViewportAdapter = viewportAdapter; + } + protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.Black); diff --git a/Source/MonoGame.Extended/ViewportAdapters/BoxingViewportAdapter.cs b/Source/MonoGame.Extended/ViewportAdapters/BoxingViewportAdapter.cs index 233bd644..ea80a5d5 100644 --- a/Source/MonoGame.Extended/ViewportAdapters/BoxingViewportAdapter.cs +++ b/Source/MonoGame.Extended/ViewportAdapters/BoxingViewportAdapter.cs @@ -15,60 +15,26 @@ namespace MonoGame.Extended.ViewportAdapters public class BoxingViewportAdapter : ScalingViewportAdapter { - private readonly GraphicsDeviceManager _graphicsDeviceManager; private readonly GameWindow _window; + private readonly GraphicsDevice _graphicsDevice; /// - /// Initializes a new instance of the . - /// Note: If you're using DirectX please use the other constructor due to a bug in MonoGame. - /// https://github.com/mono/MonoGame/issues/4018 + /// Initializes a new instance of the . /// - public BoxingViewportAdapter(GameWindow window, GraphicsDevice graphicsDevice, int virtualWidth, - int virtualHeight, int horizontalBleed, int verticalBleed) + public BoxingViewportAdapter(GameWindow window, GraphicsDevice graphicsDevice, int virtualWidth, int virtualHeight, int horizontalBleed = 0, int verticalBleed = 0) : base(graphicsDevice, virtualWidth, virtualHeight) { _window = window; + _graphicsDevice = graphicsDevice; window.ClientSizeChanged += OnClientSizeChanged; HorizontalBleed = horizontalBleed; VerticalBleed = verticalBleed; } - /// - /// Initializes a new instance of the . - /// Note: If you're using DirectX please use the other constructor due to a bug in MonoGame. - /// https://github.com/mono/MonoGame/issues/4018 - /// - public BoxingViewportAdapter(GameWindow window, GraphicsDevice graphicsDevice, int virtualWidth, - int virtualHeight) - : this(window, graphicsDevice, virtualWidth, virtualHeight, 0, 0) - { - } - - /// - /// Initializes a new instance of the . - /// Use this constructor only if you're using DirectX due to a bug in MonoGame. - /// https://github.com/mono/MonoGame/issues/4018 - /// This constructor will be made obsolete and eventually removed once the bug has been fixed. - /// - public BoxingViewportAdapter(GameWindow window, GraphicsDeviceManager graphicsDeviceManager, int virtualWidth, - int virtualHeight, int horizontalBleed, int verticalBleed) - : this( - window, graphicsDeviceManager.GraphicsDevice, virtualWidth, virtualHeight, horizontalBleed, - verticalBleed) - { - _graphicsDeviceManager = graphicsDeviceManager; - } - - /// - /// Initializes a new instance of the . - /// Use this constructor only if you're using DirectX due to a bug in MonoGame. - /// https://github.com/mono/MonoGame/issues/4018 - /// This constructor will be made obsolete and eventually removed once the bug has been fixed. - /// - public BoxingViewportAdapter(GameWindow window, GraphicsDeviceManager graphicsDeviceManager, int virtualWidth, - int virtualHeight) - : this(window, graphicsDeviceManager, virtualWidth, virtualHeight, 0, 0) + public override void Dispose() { + _window.ClientSizeChanged -= OnClientSizeChanged; + base.Dispose(); } /// @@ -85,45 +51,34 @@ namespace MonoGame.Extended.ViewportAdapters private void OnClientSizeChanged(object sender, EventArgs eventArgs) { - var viewport = GraphicsDevice.Viewport; + var clientBounds = _window.ClientBounds; - var worldScaleX = (float) viewport.Width/VirtualWidth; - var worldScaleY = (float) viewport.Height/VirtualHeight; + var worldScaleX = (float)clientBounds.Width / VirtualWidth; + var worldScaleY = (float)clientBounds.Height / VirtualHeight; - var safeScaleX = (float) viewport.Width/(VirtualWidth - HorizontalBleed); - var safeScaleY = (float) viewport.Height/(VirtualHeight - VerticalBleed); + var safeScaleX = (float)clientBounds.Width / (VirtualWidth - HorizontalBleed); + var safeScaleY = (float)clientBounds.Height / (VirtualHeight - VerticalBleed); var worldScale = MathHelper.Max(worldScaleX, worldScaleY); var safeScale = MathHelper.Min(safeScaleX, safeScaleY); var scale = MathHelper.Min(worldScale, safeScale); - var width = (int) (scale*VirtualWidth + 0.5f); - var height = (int) (scale*VirtualHeight + 0.5f); + var width = (int)(scale * VirtualWidth + 0.5f); + var height = (int)(scale * VirtualHeight + 0.5f); - if ((height >= viewport.Height) && (width < viewport.Width)) + if (height >= clientBounds.Height && width < clientBounds.Width) BoxingMode = BoxingMode.Pillarbox; else { - if ((width >= viewport.Height) && (height < viewport.Height)) + if (width >= clientBounds.Height && height <= clientBounds.Height) BoxingMode = BoxingMode.Letterbox; - else + else BoxingMode = BoxingMode.None; } - var x = viewport.Width/2 - width/2; - var y = viewport.Height/2 - height/2; + var x = clientBounds.Width / 2 - width / 2; + var y = clientBounds.Height / 2 - height / 2; GraphicsDevice.Viewport = new Viewport(x, y, width, height); - - // Needed for a DirectX bug in MonoGame 3.4. Hopefully it will be fixed in future versions - // see http://gamedev.stackexchange.com/questions/68914/issue-with-monogame-resizing - if ((_graphicsDeviceManager != null) && - ((_graphicsDeviceManager.PreferredBackBufferWidth != _window.ClientBounds.Width) || - (_graphicsDeviceManager.PreferredBackBufferHeight != _window.ClientBounds.Height))) - { - _graphicsDeviceManager.PreferredBackBufferWidth = _window.ClientBounds.Width; - _graphicsDeviceManager.PreferredBackBufferHeight = _window.ClientBounds.Height; - _graphicsDeviceManager.ApplyChanges(); - } } public override void Reset() diff --git a/Source/MonoGame.Extended/ViewportAdapters/ScalingViewportAdapter.cs b/Source/MonoGame.Extended/ViewportAdapters/ScalingViewportAdapter.cs index bbfac1a7..674a62ef 100644 --- a/Source/MonoGame.Extended/ViewportAdapters/ScalingViewportAdapter.cs +++ b/Source/MonoGame.Extended/ViewportAdapters/ScalingViewportAdapter.cs @@ -1,8 +1,6 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; -// ReSharper disable once CheckNamespace - namespace MonoGame.Extended.ViewportAdapters { public class ScalingViewportAdapter : ViewportAdapter diff --git a/Source/MonoGame.Extended/ViewportAdapters/ViewportAdapter.cs b/Source/MonoGame.Extended/ViewportAdapters/ViewportAdapter.cs index d46263d3..eb0491ee 100644 --- a/Source/MonoGame.Extended/ViewportAdapters/ViewportAdapter.cs +++ b/Source/MonoGame.Extended/ViewportAdapters/ViewportAdapter.cs @@ -1,17 +1,20 @@ +using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; -// ReSharper disable once CheckNamespace - namespace MonoGame.Extended.ViewportAdapters { - public abstract class ViewportAdapter + public abstract class ViewportAdapter : IDisposable { protected ViewportAdapter(GraphicsDevice graphicsDevice) { GraphicsDevice = graphicsDevice; } + public virtual void Dispose() + { + } + public GraphicsDevice GraphicsDevice { get; } public Viewport Viewport => GraphicsDevice.Viewport; From ce376c1386e53dfa67cbb92ef63319d65a89e93b Mon Sep 17 00:00:00 2001 From: Dylan Wilson Date: Sun, 18 Aug 2019 19:13:59 +1000 Subject: [PATCH 13/15] clean up warnings produced when generating nuget packages --- .../MonoGame.Extended.Animations.csproj | 1 - .../MonoGame.Extended.Collisions.csproj | 1 - .../MonoGame.Extended.Content.Pipeline.csproj | 1 - .../MonoGame.Extended.Entities/MonoGame.Extended.Entities.csproj | 1 - .../MonoGame.Extended.Graphics/MonoGame.Extended.Graphics.csproj | 1 - Source/MonoGame.Extended.Gui/MonoGame.Extended.Gui.csproj | 1 - Source/MonoGame.Extended.Input/MonoGame.Extended.Input.csproj | 1 - .../MonoGame.Extended.NuclexGui.csproj | 1 - .../MonoGame.Extended.Particles.csproj | 1 - .../MonoGame.Extended.SceneGraphs.csproj | 1 - Source/MonoGame.Extended.Tiled/MonoGame.Extended.Tiled.csproj | 1 - .../MonoGame.Extended.Tweening/MonoGame.Extended.Tweening.csproj | 1 - Source/MonoGame.Extended/MonoGame.Extended.csproj | 1 - 13 files changed, 13 deletions(-) diff --git a/Source/MonoGame.Extended.Animations/MonoGame.Extended.Animations.csproj b/Source/MonoGame.Extended.Animations/MonoGame.Extended.Animations.csproj index 64f02a02..3275006d 100644 --- a/Source/MonoGame.Extended.Animations/MonoGame.Extended.Animations.csproj +++ b/Source/MonoGame.Extended.Animations/MonoGame.Extended.Animations.csproj @@ -9,7 +9,6 @@ monogame animations spritesheet sprite https://github.com/craftworkgames/MonoGame.Extended https://github.com/craftworkgames/MonoGame.Extended - https://github.com/craftworkgames/MonoGame.Extended/blob/master/LICENSE https://raw.githubusercontent.com/craftworkgames/MonoGame.Extended/master/Logos/logo-nuget-128.png diff --git a/Source/MonoGame.Extended.Collisions/MonoGame.Extended.Collisions.csproj b/Source/MonoGame.Extended.Collisions/MonoGame.Extended.Collisions.csproj index 783db4f4..453366bf 100644 --- a/Source/MonoGame.Extended.Collisions/MonoGame.Extended.Collisions.csproj +++ b/Source/MonoGame.Extended.Collisions/MonoGame.Extended.Collisions.csproj @@ -9,7 +9,6 @@ monogame collisions https://github.com/craftworkgames/MonoGame.Extended https://github.com/craftworkgames/MonoGame.Extended - https://github.com/craftworkgames/MonoGame.Extended/blob/master/LICENSE https://raw.githubusercontent.com/craftworkgames/MonoGame.Extended/master/Logos/logo-nuget-128.png diff --git a/Source/MonoGame.Extended.Content.Pipeline/MonoGame.Extended.Content.Pipeline.csproj b/Source/MonoGame.Extended.Content.Pipeline/MonoGame.Extended.Content.Pipeline.csproj index 8cd82a96..bf5f6090 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/MonoGame.Extended.Content.Pipeline.csproj +++ b/Source/MonoGame.Extended.Content.Pipeline/MonoGame.Extended.Content.Pipeline.csproj @@ -9,7 +9,6 @@ monogame content importer processor reader tiled texturepacker bmfont animations https://github.com/craftworkgames/MonoGame.Extended https://github.com/craftworkgames/MonoGame.Extended - https://github.com/craftworkgames/MonoGame.Extended/blob/master/LICENSE https://raw.githubusercontent.com/craftworkgames/MonoGame.Extended/master/Logos/logo-nuget-128.png diff --git a/Source/MonoGame.Extended.Entities/MonoGame.Extended.Entities.csproj b/Source/MonoGame.Extended.Entities/MonoGame.Extended.Entities.csproj index 9745826b..b17e06f7 100644 --- a/Source/MonoGame.Extended.Entities/MonoGame.Extended.Entities.csproj +++ b/Source/MonoGame.Extended.Entities/MonoGame.Extended.Entities.csproj @@ -9,7 +9,6 @@ monogame ecs entity component system https://github.com/craftworkgames/MonoGame.Extended https://github.com/craftworkgames/MonoGame.Extended - https://github.com/craftworkgames/MonoGame.Extended/blob/master/LICENSE https://raw.githubusercontent.com/craftworkgames/MonoGame.Extended/master/Logos/logo-nuget-128.png diff --git a/Source/MonoGame.Extended.Graphics/MonoGame.Extended.Graphics.csproj b/Source/MonoGame.Extended.Graphics/MonoGame.Extended.Graphics.csproj index d5173b43..694f63d1 100644 --- a/Source/MonoGame.Extended.Graphics/MonoGame.Extended.Graphics.csproj +++ b/Source/MonoGame.Extended.Graphics/MonoGame.Extended.Graphics.csproj @@ -9,7 +9,6 @@ monogame graphics batcher effects https://github.com/craftworkgames/MonoGame.Extended https://github.com/craftworkgames/MonoGame.Extended - https://github.com/craftworkgames/MonoGame.Extended/blob/master/LICENSE https://raw.githubusercontent.com/craftworkgames/MonoGame.Extended/master/Logos/logo-nuget-128.png diff --git a/Source/MonoGame.Extended.Gui/MonoGame.Extended.Gui.csproj b/Source/MonoGame.Extended.Gui/MonoGame.Extended.Gui.csproj index ba408280..2741cea3 100644 --- a/Source/MonoGame.Extended.Gui/MonoGame.Extended.Gui.csproj +++ b/Source/MonoGame.Extended.Gui/MonoGame.Extended.Gui.csproj @@ -9,7 +9,6 @@ monogame gui https://github.com/craftworkgames/MonoGame.Extended https://github.com/craftworkgames/MonoGame.Extended - https://github.com/craftworkgames/MonoGame.Extended/blob/master/LICENSE https://raw.githubusercontent.com/craftworkgames/MonoGame.Extended/master/Logos/logo-nuget-128.png diff --git a/Source/MonoGame.Extended.Input/MonoGame.Extended.Input.csproj b/Source/MonoGame.Extended.Input/MonoGame.Extended.Input.csproj index 2c87b097..f1d90971 100644 --- a/Source/MonoGame.Extended.Input/MonoGame.Extended.Input.csproj +++ b/Source/MonoGame.Extended.Input/MonoGame.Extended.Input.csproj @@ -9,7 +9,6 @@ monogame input event based listeners https://github.com/craftworkgames/MonoGame.Extended https://github.com/craftworkgames/MonoGame.Extended - https://github.com/craftworkgames/MonoGame.Extended/blob/master/LICENSE https://raw.githubusercontent.com/craftworkgames/MonoGame.Extended/master/Logos/logo-nuget-128.png diff --git a/Source/MonoGame.Extended.NuclexGui/MonoGame.Extended.NuclexGui.csproj b/Source/MonoGame.Extended.NuclexGui/MonoGame.Extended.NuclexGui.csproj index 6dfc8e02..7ce0767e 100644 --- a/Source/MonoGame.Extended.NuclexGui/MonoGame.Extended.NuclexGui.csproj +++ b/Source/MonoGame.Extended.NuclexGui/MonoGame.Extended.NuclexGui.csproj @@ -9,7 +9,6 @@ monogame nuclex gui https://github.com/craftworkgames/MonoGame.Extended https://github.com/craftworkgames/MonoGame.Extended - https://github.com/craftworkgames/MonoGame.Extended/blob/master/LICENSE https://raw.githubusercontent.com/craftworkgames/MonoGame.Extended/master/Logos/logo-nuget-128.png diff --git a/Source/MonoGame.Extended.Particles/MonoGame.Extended.Particles.csproj b/Source/MonoGame.Extended.Particles/MonoGame.Extended.Particles.csproj index 0f8952b8..d2ceec67 100644 --- a/Source/MonoGame.Extended.Particles/MonoGame.Extended.Particles.csproj +++ b/Source/MonoGame.Extended.Particles/MonoGame.Extended.Particles.csproj @@ -9,7 +9,6 @@ monogame particle system https://github.com/craftworkgames/MonoGame.Extended https://github.com/craftworkgames/MonoGame.Extended - https://github.com/craftworkgames/MonoGame.Extended/blob/master/LICENSE https://raw.githubusercontent.com/craftworkgames/MonoGame.Extended/master/Logos/logo-nuget-128.png diff --git a/Source/MonoGame.Extended.SceneGraphs/MonoGame.Extended.SceneGraphs.csproj b/Source/MonoGame.Extended.SceneGraphs/MonoGame.Extended.SceneGraphs.csproj index dcc3bd78..37bed689 100644 --- a/Source/MonoGame.Extended.SceneGraphs/MonoGame.Extended.SceneGraphs.csproj +++ b/Source/MonoGame.Extended.SceneGraphs/MonoGame.Extended.SceneGraphs.csproj @@ -9,7 +9,6 @@ monogame scene graph node entity https://github.com/craftworkgames/MonoGame.Extended https://github.com/craftworkgames/MonoGame.Extended - https://github.com/craftworkgames/MonoGame.Extended/blob/master/LICENSE https://raw.githubusercontent.com/craftworkgames/MonoGame.Extended/master/Logos/logo-nuget-128.png diff --git a/Source/MonoGame.Extended.Tiled/MonoGame.Extended.Tiled.csproj b/Source/MonoGame.Extended.Tiled/MonoGame.Extended.Tiled.csproj index 371ee4d0..67c1e74c 100644 --- a/Source/MonoGame.Extended.Tiled/MonoGame.Extended.Tiled.csproj +++ b/Source/MonoGame.Extended.Tiled/MonoGame.Extended.Tiled.csproj @@ -9,7 +9,6 @@ monogame tiled maps orthographic isometric https://github.com/craftworkgames/MonoGame.Extended https://github.com/craftworkgames/MonoGame.Extended - https://github.com/craftworkgames/MonoGame.Extended/blob/master/LICENSE https://raw.githubusercontent.com/craftworkgames/MonoGame.Extended/master/Logos/logo-nuget-128.png diff --git a/Source/MonoGame.Extended.Tweening/MonoGame.Extended.Tweening.csproj b/Source/MonoGame.Extended.Tweening/MonoGame.Extended.Tweening.csproj index 32dc7a8d..31cb9f88 100644 --- a/Source/MonoGame.Extended.Tweening/MonoGame.Extended.Tweening.csproj +++ b/Source/MonoGame.Extended.Tweening/MonoGame.Extended.Tweening.csproj @@ -9,7 +9,6 @@ monogame animations tweening https://github.com/craftworkgames/MonoGame.Extended https://github.com/craftworkgames/MonoGame.Extended - https://github.com/craftworkgames/MonoGame.Extended/blob/master/LICENSE https://raw.githubusercontent.com/craftworkgames/MonoGame.Extended/master/Logos/logo-nuget-128.png diff --git a/Source/MonoGame.Extended/MonoGame.Extended.csproj b/Source/MonoGame.Extended/MonoGame.Extended.csproj index 43869a01..da2097ab 100644 --- a/Source/MonoGame.Extended/MonoGame.Extended.csproj +++ b/Source/MonoGame.Extended/MonoGame.Extended.csproj @@ -9,7 +9,6 @@ monogame extended pipeline bmfont tiled texture atlas input viewport fps shapes sprite https://github.com/craftworkgames/MonoGame.Extended https://github.com/craftworkgames/MonoGame.Extended - https://github.com/craftworkgames/MonoGame.Extended/blob/master/LICENSE https://raw.githubusercontent.com/craftworkgames/MonoGame.Extended/master/Logos/logo-nuget-128.png From fbe44fb9583f72665d1f6e25722be9dd2b2c8c7d Mon Sep 17 00:00:00 2001 From: Ryan Cheung Date: Tue, 20 Aug 2019 20:12:34 +0800 Subject: [PATCH 14/15] Remove garbage generated in input listners (#624) * Remove garbage generated in inpot listners * fixed coding conventions --- .../InputListeners/KeyboardListener.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Source/MonoGame.Extended.Input/InputListeners/KeyboardListener.cs b/Source/MonoGame.Extended.Input/InputListeners/KeyboardListener.cs index ceb225e3..9fc85a0f 100644 --- a/Source/MonoGame.Extended.Input/InputListeners/KeyboardListener.cs +++ b/Source/MonoGame.Extended.Input/InputListeners/KeyboardListener.cs @@ -7,6 +7,8 @@ namespace MonoGame.Extended.Input.InputListeners { public class KeyboardListener : InputListener { + private Array _keysValues = Enum.GetValues(typeof(Keys)); + private bool _isInitial; private TimeSpan _lastPressTime; @@ -50,7 +52,7 @@ namespace MonoGame.Extended.Input.InputListeners { if (!currentState.IsKeyDown(Keys.LeftAlt) && !currentState.IsKeyDown(Keys.RightAlt)) { - var pressedKeys = Enum.GetValues(typeof(Keys)) + var pressedKeys = _keysValues .Cast() .Where(key => currentState.IsKeyDown(key) && _previousState.IsKeyUp(key)); @@ -72,7 +74,7 @@ namespace MonoGame.Extended.Input.InputListeners private void RaiseReleasedEvents(KeyboardState currentState) { - var releasedKeys = Enum.GetValues(typeof(Keys)) + var releasedKeys = _keysValues .Cast() .Where(key => currentState.IsKeyUp(key) && _previousState.IsKeyDown(key)); @@ -99,4 +101,4 @@ namespace MonoGame.Extended.Input.InputListeners } } } -} \ No newline at end of file +} From 58a30106f73c532d219e8ceb35dd53f5e7f29fc3 Mon Sep 17 00:00:00 2001 From: Dylan Wilson Date: Tue, 27 Aug 2019 21:02:32 +1000 Subject: [PATCH 15/15] pack the content pipeline project as a nuget tool --- .../MonoGame.Extended.Content.Pipeline.csproj | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/MonoGame.Extended.Content.Pipeline/MonoGame.Extended.Content.Pipeline.csproj b/Source/MonoGame.Extended.Content.Pipeline/MonoGame.Extended.Content.Pipeline.csproj index bf5f6090..ef460b63 100644 --- a/Source/MonoGame.Extended.Content.Pipeline/MonoGame.Extended.Content.Pipeline.csproj +++ b/Source/MonoGame.Extended.Content.Pipeline/MonoGame.Extended.Content.Pipeline.csproj @@ -1,8 +1,13 @@  netstandard2.0 + True + + + + craftworkgames Content Pipeline importers and processors to make MonoGame more awesome.