From 189dd3c44b40e33b3b712aa7ffd27ad9d7b21ac2 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Fri, 6 Nov 2020 21:21:41 +0100 Subject: [PATCH 01/44] - changed internal system & built-in states and textures - added example canvas projekt - cleanup & ref --- Exomia.Framework.sln | 15 ++ .../Exomia.Framework.BasicSetup/MyGame.cs | 3 +- .../Exomia.Framework.Example.Canvas.csproj | 60 +++++++ .../Exomia.Framework.Example.Canvas/MyGame.cs | 107 ++++++++++++ .../Program.cs | 29 ++++ .../Components/InputComponent.cs | 18 +- .../Scenes/GameScene.cs | 32 ++-- .../Systems/CollisionSystem.cs | 8 +- .../Systems/InputSystem.cs | 14 +- .../Components/DebugComponent.cs | 14 +- .../Content/ContentReaderParameters.cs | 6 +- src/Exomia.Framework/Graphics/BlendStates.cs | 137 +++++++++++++++ .../Graphics/DefaultTextures.cs | 98 ----------- .../Graphics/DepthStencilStates.cs | 122 ++++++++++++++ .../Graphics/GraphicsDevice.cs | 114 +++++++++---- .../Graphics/IGraphicsDevice.cs | 42 ++++- .../Graphics/RasterizerStates.cs | 149 +++++++++++++++++ .../Graphics/SamplerStates.cs | 156 ++++++++++++++++++ src/Exomia.Framework/Graphics/SpriteBatch.cs | 126 ++------------ src/Exomia.Framework/Graphics/Textures.cs | 85 ++++++++++ src/Exomia.Framework/Resources/Resources.cs | 5 + .../Resources/shaders/canvas.ehlsl | 48 ++++++ .../AboutForm.cs | 2 +- .../CreateProjectForm.cs | 6 +- tools/Exomia.Framework.ContentManager/Json.cs | 6 +- .../MainForm.Build.cs | 2 +- .../MainForm.Core.cs | 3 +- .../MainForm.Events.cs | 18 +- .../MainForm.cs | 2 +- 29 files changed, 1129 insertions(+), 298 deletions(-) create mode 100644 examples/Exomia.Framework.Example.Canvas/Exomia.Framework.Example.Canvas.csproj create mode 100644 examples/Exomia.Framework.Example.Canvas/MyGame.cs create mode 100644 examples/Exomia.Framework.Example.Canvas/Program.cs create mode 100644 src/Exomia.Framework/Graphics/BlendStates.cs delete mode 100644 src/Exomia.Framework/Graphics/DefaultTextures.cs create mode 100644 src/Exomia.Framework/Graphics/DepthStencilStates.cs create mode 100644 src/Exomia.Framework/Graphics/RasterizerStates.cs create mode 100644 src/Exomia.Framework/Graphics/SamplerStates.cs create mode 100644 src/Exomia.Framework/Graphics/Textures.cs create mode 100644 src/Exomia.Framework/Resources/shaders/canvas.ehlsl diff --git a/Exomia.Framework.sln b/Exomia.Framework.sln index ec18fa6a..bebcb7c0 100644 --- a/Exomia.Framework.sln +++ b/Exomia.Framework.sln @@ -26,6 +26,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Exomia.Framework.Example.Ju EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Exomia.Framework.BasicSetup", "examples\Exomia.Framework.BasicSetup\Exomia.Framework.BasicSetup.csproj", "{8329DE95-55FA-4176-91BF-BBC793B9EBE2}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Exomia.Framework.Example.Canvas", "examples\Exomia.Framework.Example.Canvas\Exomia.Framework.Example.Canvas.csproj", "{BEB473A8-DF7F-4402-97C2-0344308EE17F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -108,6 +110,18 @@ Global {8329DE95-55FA-4176-91BF-BBC793B9EBE2}.Release|x64.Build.0 = Release|x64 {8329DE95-55FA-4176-91BF-BBC793B9EBE2}.Release|x86.ActiveCfg = Release|x86 {8329DE95-55FA-4176-91BF-BBC793B9EBE2}.Release|x86.Build.0 = Release|x86 + {BEB473A8-DF7F-4402-97C2-0344308EE17F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BEB473A8-DF7F-4402-97C2-0344308EE17F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BEB473A8-DF7F-4402-97C2-0344308EE17F}.Debug|x64.ActiveCfg = Debug|x64 + {BEB473A8-DF7F-4402-97C2-0344308EE17F}.Debug|x64.Build.0 = Debug|x64 + {BEB473A8-DF7F-4402-97C2-0344308EE17F}.Debug|x86.ActiveCfg = Debug|x86 + {BEB473A8-DF7F-4402-97C2-0344308EE17F}.Debug|x86.Build.0 = Debug|x86 + {BEB473A8-DF7F-4402-97C2-0344308EE17F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BEB473A8-DF7F-4402-97C2-0344308EE17F}.Release|Any CPU.Build.0 = Release|Any CPU + {BEB473A8-DF7F-4402-97C2-0344308EE17F}.Release|x64.ActiveCfg = Release|x64 + {BEB473A8-DF7F-4402-97C2-0344308EE17F}.Release|x64.Build.0 = Release|x64 + {BEB473A8-DF7F-4402-97C2-0344308EE17F}.Release|x86.ActiveCfg = Release|x86 + {BEB473A8-DF7F-4402-97C2-0344308EE17F}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -118,6 +132,7 @@ Global {E86DC9EB-8FC0-4C5D-95F2-206C67A069C2} = {65A2B0A0-B984-4A33-AFA5-A5E70862A10A} {22EC1807-99FD-4EC1-8A86-9553CD743498} = {9D20989E-7C37-42F4-AE05-19CED958EA7A} {8329DE95-55FA-4176-91BF-BBC793B9EBE2} = {9D20989E-7C37-42F4-AE05-19CED958EA7A} + {BEB473A8-DF7F-4402-97C2-0344308EE17F} = {9D20989E-7C37-42F4-AE05-19CED958EA7A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3E4E52C8-D1D4-488D-8700-A3E45E8968BE} diff --git a/examples/Exomia.Framework.BasicSetup/MyGame.cs b/examples/Exomia.Framework.BasicSetup/MyGame.cs index aa962c4d..d89e4868 100644 --- a/examples/Exomia.Framework.BasicSetup/MyGame.cs +++ b/examples/Exomia.Framework.BasicSetup/MyGame.cs @@ -57,6 +57,7 @@ protected override void OnInitializeGameGraphicsParameters(ref GameGraphicsParam protected override void OnInitialize() { Content.RootDirectory = "Content"; + _spriteBatch = ToDispose(new SpriteBatch(GraphicsDevice)); /* * TODO: Add your initialization logic here @@ -67,8 +68,6 @@ protected override void OnInitialize() /// OnLoadContent will be called once per game and is the place to load all of your content. protected override void OnLoadContent() { - _spriteBatch = ToDispose(new SpriteBatch(GraphicsDevice)); - /* * TODO: use base.Content to load your game content here */ diff --git a/examples/Exomia.Framework.Example.Canvas/Exomia.Framework.Example.Canvas.csproj b/examples/Exomia.Framework.Example.Canvas/Exomia.Framework.Example.Canvas.csproj new file mode 100644 index 00000000..81495bc6 --- /dev/null +++ b/examples/Exomia.Framework.Example.Canvas/Exomia.Framework.Example.Canvas.csproj @@ -0,0 +1,60 @@ + + + Exe + net48 + AnyCPU;x64;x86 + 8.0 + enable + true + + + + 1.0.0 + baetz + + Copyright © $([System.DateTime]::Now.Year) baetz + + + + portable + true + DEBUG;TRACE;x86 + DEBUG;TRACE;$(Platform) + true + + + + none + false + TRACE;x86 + TRACE;$(Platform) + + + + 1701;1702;IDE0063 + NU1605 + false + + + + $(MSBuildProjectName) + $(MSBuildProjectName) + + + + $(MSBuildProjectName).$(Platform) + $(MSBuildProjectName).$(Platform) + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/Exomia.Framework.Example.Canvas/MyGame.cs b/examples/Exomia.Framework.Example.Canvas/MyGame.cs new file mode 100644 index 00000000..b3ca4880 --- /dev/null +++ b/examples/Exomia.Framework.Example.Canvas/MyGame.cs @@ -0,0 +1,107 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using Exomia.Framework.Components; +using Exomia.Framework.Game; +using Exomia.Framework.Graphics; +using SharpDX; + +namespace Exomia.Framework.Example.Canvas +{ + /// + /// my game. This class cannot be inherited. + /// + sealed class MyGame : Game.Game + { + private SpriteBatch _spriteBatch = null!; + + /// + /// Initializes a new instance of the class. + /// + public MyGame() + : base("MyGame") + { + Add( + new DebugComponent + { + Enabled = true, + Visible = true, + UpdateOrder = 0, + DrawOrder = 0, + EnableTitleInformation = false, + }); + + IsFixedTimeStep = true; + TargetElapsedTime = 1000f / 144f; //144fps + } + + /// + protected override void OnInitializeGameGraphicsParameters(ref GameGraphicsParameters parameters) + { + parameters.IsMouseVisible = true; + parameters.Width = 1024; + parameters.Height = 786; + } + + /// + /// This is where you can query for any required services and load any non-graphic related content. + protected override void OnInitialize() + { + Content.RootDirectory = "Content"; + _spriteBatch = ToDispose(new SpriteBatch(GraphicsDevice)); + + /* + * TODO: Add your initialization logic here + */ + } + + /// + /// OnLoadContent will be called once per game and is the place to load all of your content. + protected override void OnLoadContent() + { + /* + * TODO: use base.Content to load your game content here + */ + } + + /// + /// OnUnloadContent will be called once per game and is the place to unload all content + protected override void OnUnloadContent() + { + /* + * TODO: Unload any non ContentManager content here + */ + } + + /// + /// Allows the game to run logic such as updating the world, checking for collisions, gathering input, and playing audio. + protected override void Update(GameTime gameTime) + { + /* + * TODO: Add your update logic here + */ + + base.Update(gameTime); + } + + /// + /// This is called when the game should draw itself. + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.CornflowerBlue); + + /* + * TODO: Add your drawing code here + */ + + base.Draw(gameTime); + } + } +} \ No newline at end of file diff --git a/examples/Exomia.Framework.Example.Canvas/Program.cs b/examples/Exomia.Framework.Example.Canvas/Program.cs new file mode 100644 index 00000000..cb968fc4 --- /dev/null +++ b/examples/Exomia.Framework.Example.Canvas/Program.cs @@ -0,0 +1,29 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +namespace Exomia.Framework.Example.Canvas +{ + /// + /// A program. This class cannot be inherited. + /// + sealed class Program + { + /// + /// Main entry-point for this application. + /// + private static void Main() + { + using (MyGame game = new MyGame()) + { + game.Run(); + } + } + } +} \ No newline at end of file diff --git a/examples/Exomia.Framework.Example.JumpAndRun/Components/InputComponent.cs b/examples/Exomia.Framework.Example.JumpAndRun/Components/InputComponent.cs index 38f2ca92..a0503c12 100644 --- a/examples/Exomia.Framework.Example.JumpAndRun/Components/InputComponent.cs +++ b/examples/Exomia.Framework.Example.JumpAndRun/Components/InputComponent.cs @@ -1,12 +1,22 @@ -using Exomia.ECS.Attributes; +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using Exomia.ECS.Attributes; namespace Exomia.Framework.Example.JumpAndRun.Components { [EntityComponentConfiguration(PoolSize = 8)] sealed class InputComponent { - public bool Left { get; set; } + public bool Left { get; set; } public bool Right { get; set; } - public bool Jump { get; set; } + public bool Jump { get; set; } } -} +} \ No newline at end of file diff --git a/examples/Exomia.Framework.Example.JumpAndRun/Scenes/GameScene.cs b/examples/Exomia.Framework.Example.JumpAndRun/Scenes/GameScene.cs index ab86f9d1..87007be1 100644 --- a/examples/Exomia.Framework.Example.JumpAndRun/Scenes/GameScene.cs +++ b/examples/Exomia.Framework.Example.JumpAndRun/Scenes/GameScene.cs @@ -28,7 +28,7 @@ sealed class GameScene : SceneBase, IInputHandler private EntityManager _entityManager = null!; // ReSharper disable once NotAccessedField.Local - private Entity _player = null!; + private Entity _player = null!; private InputComponent _inputComponent = null!; /// @@ -38,7 +38,21 @@ public GameScene(string key) _mapRenderer = Add( new MapRenderer("mapRenderer") { DrawOrder = 1, Visible = true }); } - + + /// + public void RegisterInput(IInputDevice device) + { + device.RegisterKeyDown(OnKeyDown); + device.RegisterKeyUp(OnKeyUp); + } + + /// + public void UnregisterInput(IInputDevice device) + { + device.UnregisterKeyUp(OnKeyDown); + device.UnregisterKeyUp(OnKeyUp); + } + /// protected override void OnInitialize(IServiceRegistry registry) { @@ -156,20 +170,6 @@ protected override void OnLoadContent(IServiceRegistry registry) }); } - /// - public void RegisterInput(IInputDevice device) - { - device.RegisterKeyDown(OnKeyDown); - device.RegisterKeyUp(OnKeyUp); - } - - /// - public void UnregisterInput(IInputDevice device) - { - device.UnregisterKeyUp(OnKeyDown); - device.UnregisterKeyUp(OnKeyUp); - } - private bool OnKeyDown(int keyValue, KeyModifier modifiers) { switch (keyValue) diff --git a/examples/Exomia.Framework.Example.JumpAndRun/Systems/CollisionSystem.cs b/examples/Exomia.Framework.Example.JumpAndRun/Systems/CollisionSystem.cs index 17061738..1a492f53 100644 --- a/examples/Exomia.Framework.Example.JumpAndRun/Systems/CollisionSystem.cs +++ b/examples/Exomia.Framework.Example.JumpAndRun/Systems/CollisionSystem.cs @@ -22,24 +22,24 @@ interface ICollisionSystem { MapRenderer MapRenderer { get; set; } } - + [EntitySystemConfiguration( nameof(CollisionSystem), EntitySystemType.Update, After = new[] { nameof(PhysicSystem) })] sealed class CollisionSystem : EntitySystemBaseR2, ICollisionSystem { private MapRenderer _mapRenderer = null!; - + /// public MapRenderer MapRenderer { get { return _mapRenderer; } set { _mapRenderer = value; } } - + /// public CollisionSystem(EntityManager manager) : base(manager) { } - + /// protected override void Tick(GameTime gameTime, Entity entity, PositionComponent c1, VelocityComponent c2) { diff --git a/examples/Exomia.Framework.Example.JumpAndRun/Systems/InputSystem.cs b/examples/Exomia.Framework.Example.JumpAndRun/Systems/InputSystem.cs index b9cb821e..4d640a44 100644 --- a/examples/Exomia.Framework.Example.JumpAndRun/Systems/InputSystem.cs +++ b/examples/Exomia.Framework.Example.JumpAndRun/Systems/InputSystem.cs @@ -1,4 +1,14 @@ -using Exomia.ECS; +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using Exomia.ECS; using Exomia.ECS.Attributes; using Exomia.ECS.Systems; using Exomia.Framework.Example.JumpAndRun.Components; @@ -19,7 +29,7 @@ protected override void Tick(GameTime gameTime, Entity entity, InputComponent c1 { if (c1.Jump) { - c1.Jump = false; + c1.Jump = false; c2.Velocity.Y -= 600; } diff --git a/src/Exomia.Framework/Components/DebugComponent.cs b/src/Exomia.Framework/Components/DebugComponent.cs index 8e67a159..a34e5c90 100644 --- a/src/Exomia.Framework/Components/DebugComponent.cs +++ b/src/Exomia.Framework/Components/DebugComponent.cs @@ -38,7 +38,6 @@ public class DebugComponent : DrawableComponent _sampleBuffer; private IGameWindow? _gameWindow; - private Vector2 _position1; private int _sampleCount, _totalFrames; private SpriteBatch? _spriteBatch; private string _title = string.Empty; @@ -71,13 +70,18 @@ public override void Draw(GameTime gameTime) if (EnableTitleInformation) { - _gameWindow!.Title = _title + " " + _fpsInfo; + _gameWindow!.Title = $"{_title} {_fpsInfo}"; } _spriteBatch!.Begin(); _spriteBatch.DrawText( - _arial12Px!, _fpsInfo, _position1, _fpsCurrent <= FRAME_DANGER_THRESHOLD ? Color.Red : Color.White, + _arial12Px!, + _fpsInfo, + Vector2.Zero, + _fpsCurrent <= FRAME_DANGER_THRESHOLD + ? Color.Red + : Color.White, 0.0f); _spriteBatch.End(); @@ -136,9 +140,7 @@ protected override void OnInitialize(IServiceRegistry registry) IGraphicsDevice graphicsDevice = registry.GetService(); _spriteBatch = new SpriteBatch(graphicsDevice); - _position1 = new Vector2(0, 0); - - _gpuName = graphicsDevice.Adapter.Desc3.Description; + _gpuName = graphicsDevice.Adapter?.Desc3.Description ?? ""; } /// diff --git a/src/Exomia.Framework/Content/ContentReaderParameters.cs b/src/Exomia.Framework/Content/ContentReaderParameters.cs index efae4863..1d73a106 100644 --- a/src/Exomia.Framework/Content/ContentReaderParameters.cs +++ b/src/Exomia.Framework/Content/ContentReaderParameters.cs @@ -19,12 +19,14 @@ namespace Exomia.Framework.Content public struct ContentReaderParameters { /// - /// Name of the asset currently loaded when using . + /// Name of the asset currently loaded when using + /// or . /// public string AssetName { get; } /// - /// Type of the asset currently loaded when using . + /// Type of the asset currently loaded when using + /// or . /// public Type AssetType { get; } diff --git a/src/Exomia.Framework/Graphics/BlendStates.cs b/src/Exomia.Framework/Graphics/BlendStates.cs new file mode 100644 index 00000000..f0a802d1 --- /dev/null +++ b/src/Exomia.Framework/Graphics/BlendStates.cs @@ -0,0 +1,137 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using SharpDX.Direct3D11; + +namespace Exomia.Framework.Graphics +{ + /// + /// The built-in blend states. This class cannot be inherited. + /// + public sealed class BlendStates : IDisposable + { + /// + /// A built-in state object with settings for additive blend, that is adding the destination data to the source data + /// without using alpha. + /// + public readonly BlendState Additive; + + /// + /// A built-in state object with settings for alpha blend, that is blending the source and destination data using + /// alpha. + /// + public readonly BlendState AlphaBlend; + + /// + /// A built-in state object with settings for blending with non-premultiplied alpha, that is blending source and + /// destination data using alpha while assuming the color data contains no alpha information. + /// + public readonly BlendState NonPremultiplied; + + /// + /// A built-in state object with settings for opaque blend, that is overwriting the source with the destination data. + /// + public readonly BlendState Opaque; + + /// + /// A built-in default state object (no blending). + /// + public readonly BlendState Default; + + /// + /// Initializes a new instance of the class. + /// + /// The graphics device. + internal BlendStates(IGraphicsDevice graphicsDevice) + { + Additive = Create(graphicsDevice.Device, nameof(Additive), BlendOption.SourceAlpha, BlendOption.One, true); + AlphaBlend = Create( + graphicsDevice.Device, nameof(AlphaBlend), BlendOption.One, BlendOption.InverseSourceAlpha, true); + NonPremultiplied = Create( + graphicsDevice.Device, nameof(NonPremultiplied), BlendOption.SourceAlpha, + BlendOption.InverseSourceAlpha, true); + Opaque = Create(graphicsDevice.Device, nameof(Opaque), BlendOption.One, BlendOption.Zero, true); + Default = Create(graphicsDevice.Device, nameof(Default), BlendStateDescription.Default()); + } + + private static BlendState Create(Device5 device, string name, BlendStateDescription description) + { + return new BlendState(device, description) { DebugName = name }; + } + + private static BlendState Create(Device5 device, + string name, + BlendOption sourceBlend, + BlendOption destinationBlend, + bool blendEnabled) + { + return Create( + device, + name, + new BlendStateDescription + { + AlphaToCoverageEnable = false, + IndependentBlendEnable = false, + RenderTarget = + { + [0] = new RenderTargetBlendDescription + { + IsBlendEnabled = blendEnabled, + SourceBlend = sourceBlend, + DestinationBlend = destinationBlend, + SourceAlphaBlend = sourceBlend, + DestinationAlphaBlend = destinationBlend, + BlendOperation = BlendOperation.Add, + AlphaBlendOperation = BlendOperation.Add, + RenderTargetWriteMask = ColorWriteMaskFlags.All + } + } + }); + } + + #region IDisposable Support + + private bool _disposed; + + private void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + Additive.Dispose(); + AlphaBlend.Dispose(); + NonPremultiplied.Dispose(); + Opaque.Dispose(); + Default.Dispose(); + } + _disposed = true; + } + } + + /// + ~BlendStates() + { + Dispose(false); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged/managed resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/DefaultTextures.cs b/src/Exomia.Framework/Graphics/DefaultTextures.cs deleted file mode 100644 index 76ea0dcb..00000000 --- a/src/Exomia.Framework/Graphics/DefaultTextures.cs +++ /dev/null @@ -1,98 +0,0 @@ -#region License - -// Copyright (c) 2018-2020, exomia -// All rights reserved. -// -// This source code is licensed under the BSD-style license found in the -// LICENSE file in the root directory of this source tree. - -#endregion - -using System; -using System.IO; -using SharpDX; -using SharpDX.Direct3D11; - -namespace Exomia.Framework.Graphics -{ - /// - /// A default textures. - /// - public static class DefaultTextures - { - private const string WHITE_TEXTURE_BASE64 = - "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII="; - - private static Texture? s_whiteTexture; - private static bool s_isInitialized; - - /// - /// Gets the white texture. - /// - /// - /// The white texture. - /// - public static Texture WhiteTexture - { - get { return s_whiteTexture!; } - } - - /// - /// Initializes the textures. - /// - /// The device. - internal static void InitializeTextures(Device5 device) - { - if (!s_isInitialized) - { - s_isInitialized = true; - s_disposedValue = false; - - using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(WHITE_TEXTURE_BASE64))) - { - s_whiteTexture = Texture.Load(device, ms) ?? - throw new NullReferenceException($"{nameof(WhiteTexture)}"); - } - } - } - - #region IDisposable Support - - /// - /// True to disposed value. - /// - private static bool s_disposedValue; - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting - /// unmanaged resources. - /// - /// - /// True to release both managed and unmanaged resources; false to - /// release only unmanaged resources. - /// - public static void Dispose(bool disposing) - { - if (!s_disposedValue) - { - if (disposing) - { - Utilities.Dispose(ref s_whiteTexture); - } - s_isInitialized = false; - s_disposedValue = true; - } - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting - /// unmanaged resources. - /// - public static void Dispose() - { - Dispose(true); - } - - #endregion - } -} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/DepthStencilStates.cs b/src/Exomia.Framework/Graphics/DepthStencilStates.cs new file mode 100644 index 00000000..93472f6c --- /dev/null +++ b/src/Exomia.Framework/Graphics/DepthStencilStates.cs @@ -0,0 +1,122 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using SharpDX.Direct3D11; + +namespace Exomia.Framework.Graphics +{ + /// + /// The built-in depth stencil states. This class cannot be inherited. + /// + public sealed class DepthStencilStates : IDisposable + { + /// + /// A built-in state object with default settings for using a depth stencil buffer. + /// + public readonly DepthStencilState Default; + + /// + /// A built-in state object with settings for enabling a read-only depth stencil buffer. + /// + public readonly DepthStencilState DepthRead; + + /// + /// A built-in state object with settings for not using a depth stencil buffer. + /// + public readonly DepthStencilState None; + + /// + /// A built-in state object with default settings for using a depth stencil buffer with stencil enabled. + /// + public readonly DepthStencilState DefaultStencilEnabled; + + /// + /// Initializes a new instance of the class. + /// + /// The graphics device. + internal DepthStencilStates(IGraphicsDevice graphicsDevice) + { + Default = Create(graphicsDevice.Device, nameof(Default), true, true, false); + DepthRead = Create(graphicsDevice.Device, nameof(DepthRead), true, false, false); + None = Create(graphicsDevice.Device, nameof(None), false, false, false); + DefaultStencilEnabled = Create(graphicsDevice.Device, nameof(DefaultStencilEnabled), true, true, true); + } + + private static DepthStencilState Create(Device5 device, + string name, + bool depthEnable, + bool depthWriteEnable, + bool stencilEnabled) + { + return new DepthStencilState( + device, + new DepthStencilStateDescription + { + IsDepthEnabled = depthEnable, + DepthWriteMask = depthWriteEnable ? DepthWriteMask.All : DepthWriteMask.Zero, + DepthComparison = Comparison.LessEqual, + IsStencilEnabled = stencilEnabled, + StencilReadMask = 0xFF, + StencilWriteMask = 0xFF, + FrontFace = new DepthStencilOperationDescription + { + FailOperation = StencilOperation.Keep, + DepthFailOperation = StencilOperation.Keep, + PassOperation = StencilOperation.Keep, + Comparison = Comparison.Always + }, + BackFace = new DepthStencilOperationDescription + { + FailOperation = StencilOperation.Keep, + DepthFailOperation = StencilOperation.Keep, + PassOperation = StencilOperation.Keep, + Comparison = Comparison.Always + } + }) { DebugName = name }; + } + + #region IDisposable Support + + private bool _disposed; + + private void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + Default.Dispose(); + DepthRead.Dispose(); + None.Dispose(); + DefaultStencilEnabled.Dispose(); + } + _disposed = true; + } + } + + /// + ~DepthStencilStates() + { + Dispose(false); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged/managed resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/GraphicsDevice.cs b/src/Exomia.Framework/Graphics/GraphicsDevice.cs index c1661523..f300dc7e 100644 --- a/src/Exomia.Framework/Graphics/GraphicsDevice.cs +++ b/src/Exomia.Framework/Graphics/GraphicsDevice.cs @@ -41,47 +41,52 @@ public sealed class GraphicsDevice : IGraphicsDevice public event EventHandler? ResizeFinished; private Adapter4? _adapter4; - private RenderTargetView1? _currentRenderView; - private Device5? _d3DDevice5; - private DeviceContext4? _d3DDeviceContext; - private DepthStencilView? _depthStencilView; - private Device4? _dxgiDevice4; - private Factory5? _dxgiFactory; - private bool _needResize; - private Output6? _output6; - private RenderTargetView1? _renderView1; + private RenderTargetView1 _currentRenderView = null!; + private Device5 _d3DDevice5 = null!; + private DeviceContext4 _d3DDeviceContext = null!; + private DepthStencilView _depthStencilView = null!; + private Device4 _dxgiDevice4 = null!; + private Factory5 _dxgiFactory = null!; + private Output6 _output6 = null!; + private RenderTargetView1 _renderView1 = null!; + private SwapChain4 _swapChain4 = null!; + private BlendStates _blendStates = null!; + private DepthStencilStates _depthStencilStates = null!; + private RasterizerStates _rasterizerStates = null!; + private SamplerStates _samplerStates = null!; + private Textures _textures = null!; private ResizeParameters _resizeParameters; - private SwapChain4? _swapChain4; + private bool _needResize; private int _vSync; /// - public Adapter4 Adapter + public Adapter4? Adapter { - get { return _adapter4!; } + get { return _adapter4; } } /// public Device5 Device { - get { return _d3DDevice5!; } + get { return _d3DDevice5; } } /// public DeviceContext4 DeviceContext { - get { return _d3DDeviceContext!; } + get { return _d3DDeviceContext; } } /// public Device4 DxgiDevice { - get { return _dxgiDevice4!; } + get { return _dxgiDevice4; } } /// public Factory5 Factory { - get { return _dxgiFactory!; } + get { return _dxgiFactory; } } /// @@ -90,13 +95,13 @@ public Factory5 Factory /// public RenderTargetView1 RenderView { - get { return _renderView1!; } + get { return _renderView1; } } /// public SwapChain4 SwapChain { - get { return _swapChain4!; } + get { return _swapChain4; } } /// @@ -109,6 +114,36 @@ public bool VSync set { _vSync = value ? 1 : 0; } } + /// + public BlendStates BlendStates + { + get { return _blendStates; } + } + + /// + public DepthStencilStates DepthStencilStates + { + get { return _depthStencilStates; } + } + + /// + public RasterizerStates RasterizerStates + { + get { return _rasterizerStates; } + } + + /// + public SamplerStates SamplerStates + { + get { return _samplerStates; } + } + + /// + public Textures Textures + { + get { return _textures; } + } + /// public void Clear() { @@ -118,9 +153,9 @@ public void Clear() /// public void Clear(Color color) { - _d3DDeviceContext!.ClearDepthStencilView( - _depthStencilView!, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1f, 0); - _d3DDeviceContext!.ClearRenderTargetView(_currentRenderView!, color); + _d3DDeviceContext.ClearDepthStencilView( + _depthStencilView, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1f, 0); + _d3DDeviceContext!.ClearRenderTargetView(_currentRenderView, color); } /// @@ -141,7 +176,7 @@ public void Resize(int width, int height) { _resizeParameters = new ResizeParameters { - BufferCount = _swapChain4!.Description1.BufferCount, + BufferCount = _swapChain4.Description1.BufferCount, Width = width, Height = height, SwapChainFlags = _swapChain4.Description1.Flags @@ -154,21 +189,21 @@ public void SetFullscreenState(bool state, Output? output = null) { if (GetFullscreenState() != state) { - _swapChain4!.SetFullscreenState(state, output); + _swapChain4.SetFullscreenState(state, output); } } /// public bool GetFullscreenState() { - return _swapChain4!.IsFullScreen; + return _swapChain4.IsFullScreen; } /// public void SetRenderTarget(RenderTargetView1? target) { _currentRenderView = target ?? _renderView1; - _d3DDeviceContext!.OutputMerger.SetRenderTargets(_depthStencilView, _currentRenderView); + _d3DDeviceContext.OutputMerger.SetRenderTargets(_depthStencilView, _currentRenderView); } /// @@ -192,7 +227,7 @@ public bool BeginFrame() /// public void EndFrame() { - _swapChain4!.Present(_vSync, PresentFlags.None, s_defaultPresentParameters); + _swapChain4.Present(_vSync, PresentFlags.None, s_defaultPresentParameters); } /// @@ -242,10 +277,10 @@ public void Initialize(ref GameGraphicsParameters parameters) featureLevel: SharpDX.Direct3D11.Device.GetSupportedFeatureLevel(a))) .GroupBy(t => t.featureLevel) .OrderByDescending(t => t.Key) - .FirstOrDefault() + .First() .Select(k => k.adapter); - _adapter4 = null!; + _adapter4 = null; foreach (Adapter adapter in adapters) { using (adapter) @@ -299,7 +334,7 @@ Device CreateDevice(in GameGraphicsParameters parameters) Console.WriteLine($"Scaling:\t\t{modeDescription.Scaling}"); Console.WriteLine($"ScanlineOrdering:\t{modeDescription.ScanlineOrdering}"); Console.WriteLine(); - Console.WriteLine($"DeviceName:\t\t{_output6!.Description.DeviceName}"); + Console.WriteLine($"DeviceName:\t\t{_output6.Description.DeviceName}"); Console.WriteLine( $"DesktopBounds:\t\t{_output6.Description.DesktopBounds.Left};{_output6.Description.DesktopBounds.Top};{_output6.Description.DesktopBounds.Right};{_output6.Description.DesktopBounds.Bottom}"); Console.WriteLine($"MonitorHandle:\t\t{_output6.Description.MonitorHandle}"); @@ -351,7 +386,7 @@ Device CreateDevice(in GameGraphicsParameters parameters) _dxgiFactory.MakeWindowAssociation(parameters.Handle, parameters.WindowAssociationFlags); - _swapChain4!.ResizeTarget(ref modeDescription); + _swapChain4.ResizeTarget(ref modeDescription); SetFullscreenState(parameters.DisplayType == DisplayType.Fullscreen); @@ -365,6 +400,12 @@ Device CreateDevice(in GameGraphicsParameters parameters) Resize(_resizeParameters); + _blendStates = new BlendStates(this); + _depthStencilStates = new DepthStencilStates(this); + _rasterizerStates = new RasterizerStates(this); + _samplerStates = new SamplerStates(this); + _textures = new Textures(this); + IsInitialized = true; } @@ -373,9 +414,9 @@ private void Resize(ResizeParameters args) Utilities.Dispose(ref _renderView1); Utilities.Dispose(ref _depthStencilView); - _d3DDeviceContext!.ClearState(); + _d3DDeviceContext.ClearState(); - _swapChain4!.ResizeBuffers( + _swapChain4.ResizeBuffers( args.BufferCount, args.Width, args.Height, Format.Unknown, args.SwapChainFlags); using (Texture2D backBuffer = _swapChain4.GetBackBuffer(0)) @@ -410,7 +451,7 @@ private void Resize(ResizeParameters args) }); } - _d3DDeviceContext!.Rasterizer.SetViewport(Viewport = new Viewport(0, 0, args.Width, args.Height)); + _d3DDeviceContext.Rasterizer.SetViewport(Viewport = new Viewport(0, 0, args.Width, args.Height)); SetRenderTarget(null); @@ -453,6 +494,13 @@ private void Dispose(bool disposing) { if (disposing) { + _blendStates.Dispose(); + _depthStencilStates.Dispose(); + _rasterizerStates.Dispose(); + _samplerStates.Dispose(); + + _textures.Dispose(); + Utilities.Dispose(ref _depthStencilView); Utilities.Dispose(ref _renderView1); Utilities.Dispose(ref _dxgiDevice4); diff --git a/src/Exomia.Framework/Graphics/IGraphicsDevice.cs b/src/Exomia.Framework/Graphics/IGraphicsDevice.cs index 0b71c9b5..618f274d 100644 --- a/src/Exomia.Framework/Graphics/IGraphicsDevice.cs +++ b/src/Exomia.Framework/Graphics/IGraphicsDevice.cs @@ -41,7 +41,7 @@ public interface IGraphicsDevice : IDisposable /// /// The adapter. /// - Adapter4 Adapter { get; } + Adapter4? Adapter { get; } /// /// Gets the device. @@ -107,6 +107,46 @@ public interface IGraphicsDevice : IDisposable /// bool VSync { get; set; } + /// + /// Gets the for this graphics device. + /// + /// + /// The blend states. + /// + BlendStates BlendStates { get; } + + /// + /// Gets the for this graphics device. + /// + /// + /// The depth stencil states. + /// + DepthStencilStates DepthStencilStates { get; } + + /// + /// Gets the for this graphics device. + /// + /// + /// The rasterizer states. + /// + RasterizerStates RasterizerStates { get; } + + /// + /// Gets the for this graphics device. + /// + /// + /// The sample states. + /// + SamplerStates SamplerStates { get; } + + /// + /// Gets the for this graphics device. + /// + /// + /// The textures. + /// + Textures Textures { get; } + /// /// Clears this object to its blank/initial state. /// diff --git a/src/Exomia.Framework/Graphics/RasterizerStates.cs b/src/Exomia.Framework/Graphics/RasterizerStates.cs new file mode 100644 index 00000000..05e93ce9 --- /dev/null +++ b/src/Exomia.Framework/Graphics/RasterizerStates.cs @@ -0,0 +1,149 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using SharpDX.Direct3D11; + +namespace Exomia.Framework.Graphics +{ + /// + /// The built-in rasterizer states. This class cannot be inherited. + /// + public sealed class RasterizerStates : IDisposable + { + /// + /// Built-in rasterizer state object with settings for wireframe rendering. + /// + public readonly RasterizerState WireFrame; + + /// + /// Built-in rasterizer state object with settings for wireframe rendering. + /// + public readonly RasterizerState WireFrameCullNone; + + /// + /// Built-in rasterizer state object with settings for culling primitives with clockwise winding order (front facing). + /// + public readonly RasterizerState CullFront; + + /// + /// Built-in rasterizer state object with settings for culling primitives with counter-clockwise winding order (back + /// facing). + /// + public readonly RasterizerState CullBack; + + /// + /// Built-in rasterizer state object with settings for not culling any primitives. + /// + public readonly RasterizerState CullNone; + + /// + /// Built-in rasterizer state object with settings and depth clip off. + /// + public readonly RasterizerState CullBackDepthClipOff; + + /// + /// Built-in rasterizer state object with settings and scissor enabled. + /// + public readonly RasterizerState CullBackScissorEnabled; + + /// + /// Built-in rasterizer state object with settings and + /// . + /// + public readonly RasterizerState CullBackDepthClipOffScissorEnabled; + + /// + /// Initializes a new instance of the class. + /// + /// The graphics device. + internal RasterizerStates(IGraphicsDevice graphicsDevice) + { + WireFrame = Create( + graphicsDevice.Device, nameof(WireFrame), FillMode.Wireframe, CullMode.Back, true, false); + WireFrameCullNone = Create( + graphicsDevice.Device, nameof(WireFrameCullNone), FillMode.Wireframe, CullMode.None, true, false); + CullFront = Create(graphicsDevice.Device, nameof(CullFront), FillMode.Solid, CullMode.Front, true, false); + CullBack = Create(graphicsDevice.Device, nameof(CullBack), FillMode.Solid, CullMode.Back, true, false); + CullNone = Create(graphicsDevice.Device, nameof(CullNone), FillMode.Solid, CullMode.None, true, false); + CullBackDepthClipOff = Create( + graphicsDevice.Device, nameof(CullBack), FillMode.Solid, CullMode.Back, false, false); + CullBackScissorEnabled = Create( + graphicsDevice.Device, nameof(CullBack), FillMode.Solid, CullMode.Back, true, true); + CullBackDepthClipOffScissorEnabled = Create( + graphicsDevice.Device, nameof(CullBack), FillMode.Solid, CullMode.Back, true, true); + } + + private static RasterizerState Create(Device5 device, + string name, + FillMode fillMode, + CullMode cullMode, + bool depthClipEnabled, + bool scissorEnabled) + { + return new RasterizerState( + device, + new RasterizerStateDescription + { + FillMode = fillMode, + CullMode = cullMode, + IsFrontCounterClockwise = false, + DepthBias = 0, + DepthBiasClamp = 0, + SlopeScaledDepthBias = 0, + IsDepthClipEnabled = depthClipEnabled, + IsScissorEnabled = scissorEnabled, + IsMultisampleEnabled = false, + IsAntialiasedLineEnabled = false + }) { DebugName = name }; + } + + #region IDisposable Support + + private bool _disposed; + + private void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + WireFrame.Dispose(); + WireFrameCullNone.Dispose(); + CullFront.Dispose(); + CullBack.Dispose(); + CullNone.Dispose(); + CullBackDepthClipOff.Dispose(); + CullBackScissorEnabled.Dispose(); + CullBackDepthClipOffScissorEnabled.Dispose(); + } + + _disposed = true; + } + } + + /// + ~RasterizerStates() + { + Dispose(false); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged/managed resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SamplerStates.cs b/src/Exomia.Framework/Graphics/SamplerStates.cs new file mode 100644 index 00000000..b4bb3763 --- /dev/null +++ b/src/Exomia.Framework/Graphics/SamplerStates.cs @@ -0,0 +1,156 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using SharpDX; +using SharpDX.Direct3D11; + +namespace Exomia.Framework.Graphics +{ + /// + /// The built-in sampler states. This class cannot be inherited. + /// + public sealed class SamplerStates : IDisposable + { + /// + /// Point filtering with texture coordinate wrapping. + /// + public readonly SamplerState PointWrap; + + /// + /// Point filtering with texture coordinate clamping. + /// + public readonly SamplerState PointClamp; + + /// + /// Point filtering with texture coordinate mirroring. + /// + public readonly SamplerState PointMirror; + + /// + /// Linear filtering with texture coordinate wrapping. + /// + public readonly SamplerState LinearWrap; + + /// + /// Linear filtering with texture coordinate clamping. + /// + public readonly SamplerState LinearClamp; + + /// + /// Linear filtering with texture coordinate mirroring. + /// + public readonly SamplerState LinearMirror; + + /// + /// Anisotropic filtering with texture coordinate wrapping. + /// + public readonly SamplerState AnisotropicWrap; + + /// + /// Anisotropic filtering with texture coordinate clamping. + /// + public readonly SamplerState AnisotropicClamp; + + /// + /// Anisotropic filtering with texture coordinate mirroring. + /// + public readonly SamplerState AnisotropicMirror; + + /// + /// Initializes a new instance of the class. + /// + /// The graphics device. + internal SamplerStates(IGraphicsDevice graphicsDevice) + { + PointWrap = Create( + graphicsDevice.Device, nameof(PointWrap), Filter.MinMagMipPoint, TextureAddressMode.Wrap); + PointClamp = Create( + graphicsDevice.Device, nameof(PointClamp), Filter.MinMagMipPoint, TextureAddressMode.Clamp); + PointMirror = Create( + graphicsDevice.Device, nameof(PointMirror), Filter.MinMagMipPoint, TextureAddressMode.Mirror); + LinearWrap = Create( + graphicsDevice.Device, nameof(LinearWrap), Filter.MinMagMipLinear, TextureAddressMode.Wrap); + LinearClamp = Create( + graphicsDevice.Device, nameof(LinearClamp), Filter.MinMagMipLinear, TextureAddressMode.Clamp); + LinearMirror = Create( + graphicsDevice.Device, nameof(LinearMirror), Filter.MinMagMipLinear, TextureAddressMode.Mirror); + AnisotropicWrap = Create( + graphicsDevice.Device, nameof(AnisotropicWrap), Filter.Anisotropic, TextureAddressMode.Wrap); + AnisotropicClamp = Create( + graphicsDevice.Device, nameof(AnisotropicClamp), Filter.Anisotropic, TextureAddressMode.Clamp); + AnisotropicMirror = Create( + graphicsDevice.Device, nameof(AnisotropicMirror), Filter.Anisotropic, TextureAddressMode.Mirror); + } + + private static SamplerState Create(Device5 device, + string name, + Filter filter, + TextureAddressMode textureAddressMode) + { + return new SamplerState( + device, + new SamplerStateDescription + { + AddressU = textureAddressMode, + AddressV = textureAddressMode, + AddressW = textureAddressMode, + BorderColor = Color.White, + ComparisonFunction = Comparison.Never, + Filter = filter, + MaximumAnisotropy = 16, + MaximumLod = float.MaxValue, + MinimumLod = float.MinValue, + MipLodBias = 0.0f + }) { DebugName = name }; + } + + #region IDisposable Support + + private bool _disposed; + + private void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + PointWrap.Dispose(); + PointClamp.Dispose(); + PointMirror.Dispose(); + LinearWrap.Dispose(); + LinearClamp.Dispose(); + LinearMirror.Dispose(); + AnisotropicWrap.Dispose(); + AnisotropicClamp.Dispose(); + AnisotropicMirror.Dispose(); + } + _disposed = true; + } + } + + /// + ~SamplerStates() + { + Dispose(false); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged/managed resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.cs b/src/Exomia.Framework/Graphics/SpriteBatch.cs index 1b95f6cc..298bc672 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.cs @@ -83,6 +83,7 @@ private static readonly Vector2[] private int _spriteQueueCount; private TextureInfo[] _spriteTextures; private Matrix _projectionMatrix, _viewMatrix, _transformMatrix; + private Texture _whiteTexture; private SpinLock _spinLock = new SpinLock(Debugger.IsAttached); @@ -134,15 +135,21 @@ public SpriteBatch(IGraphicsDevice iDevice, SpriteSortAlgorithm sortAlgorithm = _ => throw new ArgumentException($"invalid sort algorithm ({sortAlgorithm})", nameof(sortAlgorithm)) }; - InitializeStates(iDevice.Device); - DefaultTextures.InitializeTextures(iDevice.Device); + _defaultBlendState = iDevice.BlendStates.AlphaBlend; + _defaultSamplerState = iDevice.SamplerStates.LinearWrap; + _defaultDepthStencilState = iDevice.DepthStencilStates.None; + _defaultRasterizerState = iDevice.RasterizerStates.CullBackDepthClipOff; + _defaultRasterizerScissorEnabledState = iDevice.RasterizerStates.CullBackDepthClipOffScissorEnabled; + + _whiteTexture = iDevice.Textures.WhiteTexture; _indexBuffer = Buffer.Create( _device, BindFlags.IndexBuffer, s_indices, 0, ResourceUsage.Immutable); Assembly assembly = Assembly.GetExecutingAssembly(); - using (Stream stream = assembly.GetManifestResourceStream( - $"{assembly.GetName().Name}.{Shaders.POSITION_COLOR_TEXTURE}")) + using (Stream stream = + assembly.GetManifestResourceStream($"{assembly.GetName().Name}.{Shaders.POSITION_COLOR_TEXTURE}") ?? + throw new NullReferenceException($"{assembly.GetName().Name}.{Shaders.POSITION_COLOR_TEXTURE}")) { Shader.Shader.Technique technique = (_shader = ShaderFileLoader.FromStream(iDevice, stream) ?? @@ -519,109 +526,6 @@ private void IDevice_onResizeFinished(ViewportF viewport) Resize(viewport); } - /// - /// Initializes the states. - /// - /// The device. - private void InitializeStates(Device5 device) - { - _defaultSamplerState = new SamplerState( - device, - new SamplerStateDescription - { - AddressU = TextureAddressMode.Wrap, - AddressV = TextureAddressMode.Wrap, - AddressW = TextureAddressMode.Wrap, - BorderColor = Color.White, - ComparisonFunction = Comparison.Always, - Filter = Filter.ComparisonMinMagMipLinear, - MaximumAnisotropy = 16, - MaximumLod = float.MaxValue, - MinimumLod = 0, - MipLodBias = 0.0f - }); - - _defaultBlendState = new BlendState( - device, - new BlendStateDescription - { - AlphaToCoverageEnable = false, - IndependentBlendEnable = false, - RenderTarget = - { - [0] = new RenderTargetBlendDescription - { - IsBlendEnabled = true, - SourceBlend = BlendOption.One, - DestinationBlend = BlendOption.InverseSourceAlpha, - BlendOperation = BlendOperation.Add, - SourceAlphaBlend = BlendOption.Zero, - DestinationAlphaBlend = BlendOption.Zero, - AlphaBlendOperation = BlendOperation.Add, - RenderTargetWriteMask = ColorWriteMaskFlags.All - } - } - }) { DebugName = "AlphaBlend" }; - - _defaultDepthStencilState = new DepthStencilState( - device, - new DepthStencilStateDescription - { - IsDepthEnabled = false, - DepthWriteMask = DepthWriteMask.All, - DepthComparison = Comparison.LessEqual, - IsStencilEnabled = false, - StencilReadMask = 0xFF, - StencilWriteMask = 0xFF, - FrontFace = new DepthStencilOperationDescription - { - FailOperation = StencilOperation.Keep, - DepthFailOperation = StencilOperation.Increment, - PassOperation = StencilOperation.Keep, - Comparison = Comparison.Always - }, - BackFace = new DepthStencilOperationDescription - { - FailOperation = StencilOperation.Keep, - DepthFailOperation = StencilOperation.Decrement, - PassOperation = StencilOperation.Keep, - Comparison = Comparison.Always - } - }); - - _defaultRasterizerState = new RasterizerState( - device, - new RasterizerStateDescription - { - FillMode = FillMode.Solid, - CullMode = CullMode.Back, - IsFrontCounterClockwise = false, - DepthBias = 0, - DepthBiasClamp = 0, - SlopeScaledDepthBias = 0, - IsDepthClipEnabled = false, - IsScissorEnabled = false, - IsMultisampleEnabled = true, - IsAntialiasedLineEnabled = true - }); - - _defaultRasterizerScissorEnabledState = new RasterizerState( - device, - new RasterizerStateDescription - { - FillMode = FillMode.Solid, - CullMode = CullMode.Back, - IsFrontCounterClockwise = false, - DepthBias = 0, - DepthBiasClamp = 0, - SlopeScaledDepthBias = 0, - IsDepthClipEnabled = false, - IsScissorEnabled = true, - IsMultisampleEnabled = true, - IsAntialiasedLineEnabled = true - }); - } - /// /// Prepare for rendering. /// @@ -817,7 +721,7 @@ public void DrawRectangle(in RectangleF destinationRectangle, public void DrawFillRectangle(in RectangleF destinationRectangle, in Color color, float layerDepth) { DrawSprite( - DefaultTextures.WhiteTexture, destinationRectangle, false, s_nullRectangle, + _whiteTexture, destinationRectangle, false, s_nullRectangle, color, 0.0f, s_vector2Zero, 1.0f, SpriteEffects.None, layerDepth); } @@ -834,7 +738,7 @@ public void DrawFillRectangle(in RectangleF destinationRectangle, float layerDepth) { DrawSprite( - DefaultTextures.WhiteTexture, destinationRectangle, false, s_nullRectangle, + _whiteTexture, destinationRectangle, false, s_nullRectangle, color, 0.0f, s_vector2Zero, opacity, SpriteEffects.None, layerDepth); } @@ -855,7 +759,7 @@ public void DrawFillRectangle(in RectangleF destinationRectangle, float layerDepth) { DrawSprite( - DefaultTextures.WhiteTexture, destinationRectangle, false, s_nullRectangle, + _whiteTexture, destinationRectangle, false, s_nullRectangle, color, rotation, origin, opacity, SpriteEffects.None, layerDepth); } @@ -897,7 +801,7 @@ public void DrawLine(in Vector2 point1, float layerDepth) { DrawSprite( - DefaultTextures.WhiteTexture, new RectangleF( + _whiteTexture, new RectangleF( point1.X, point1.Y, Vector2.Distance(point1, point2) * lengthFactor, lineWidth), false, s_nullRectangle, color, (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X), s_vector2Zero, opacity, SpriteEffects.None, layerDepth); diff --git a/src/Exomia.Framework/Graphics/Textures.cs b/src/Exomia.Framework/Graphics/Textures.cs new file mode 100644 index 00000000..5967a0f2 --- /dev/null +++ b/src/Exomia.Framework/Graphics/Textures.cs @@ -0,0 +1,85 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using System.IO; + +namespace Exomia.Framework.Graphics +{ + /// + /// The built-in textures. This class cannot be inherited. + /// + public class Textures : IDisposable + { + private const string WHITE_TEXTURE_BASE64 = + "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII="; + + private readonly Texture _whiteTexture; + + /// + /// Built-in white texture object with size of 1x1 px. + /// + /// + /// The white texture. + /// + public Texture WhiteTexture + { + get { return _whiteTexture!; } + } + + /// + /// Initializes a new instance of the class. + /// + /// The graphics device. + /// Thrown when a value was unexpectedly null. + internal Textures(IGraphicsDevice graphicsDevice) + { + using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(WHITE_TEXTURE_BASE64))) + { + _whiteTexture = Texture.Load(graphicsDevice.Device, ms) ?? + throw new NullReferenceException($"{nameof(WhiteTexture)}"); + } + } + + #region IDisposable Support + + private bool _disposed; + + private void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + _whiteTexture.Dispose(); + } + + _disposed = true; + } + } + + /// + ~Textures() + { + Dispose(false); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged/managed resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Resources/Resources.cs b/src/Exomia.Framework/Resources/Resources.cs index c352b662..a8774b97 100644 --- a/src/Exomia.Framework/Resources/Resources.cs +++ b/src/Exomia.Framework/Resources/Resources.cs @@ -105,5 +105,10 @@ public static class Shaders /// The position color texture2 shader resource path. /// public const string POSITION_NORMAL_TEXTURE = "Resources.shaders.position_normal_texture.ehlsl"; + + /// + /// The canvas shader resource path. + /// + public const string CANVAS = "Resources.shaders.canvas.ehlsl"; } } \ No newline at end of file diff --git a/src/Exomia.Framework/Resources/shaders/canvas.ehlsl b/src/Exomia.Framework/Resources/shaders/canvas.ehlsl new file mode 100644 index 00000000..1fb7c445 --- /dev/null +++ b/src/Exomia.Framework/Resources/shaders/canvas.ehlsl @@ -0,0 +1,48 @@ +/** Shaderdefinition + * + * technique DEFAULT + * vs VSMain vs_5_0 OptimizationLevel3 + * ps PSMain ps_5_0 OptimizationLevel3 + */ + +Texture2D g_Texture : register(t0); +SamplerState g_Sampler : register(s0); + +cbuffer PerFrame : register(b0) +{ + float4x4 g_WorldMatrix; + float4x4 g_ViewMatrix; + float4x4 g_ProjectionMatrix; + float4x4 g_WorldViewProjectionMatrix; +}; + +struct VS_INPUT +{ + float4 p : SV_POSITION0; + float4 c : COLOR0; + float2 uv : TEXCOORD0; +}; + +struct PS_INPUT +{ + float4 p : SV_POSITION0; + float4 c : COLOR0; + float2 uv : TEXCOORD0; +}; + +PS_INPUT VSMain(VS_INPUT input) +{ + PS_INPUT output = (PS_INPUT)0; + output.p = mul(input.p, g_WorldViewProjectionMatrix); + output.c = input.c / 255; + output.uv = input.uv; + return output; +} + +float4 PSMain(PS_INPUT input) : SV_TARGET +{ + //discard; + //clip(-1); + return g_Texture.Sample(g_Sampler, input.uv) * input.c; +} + diff --git a/tools/Exomia.Framework.ContentManager/AboutForm.cs b/tools/Exomia.Framework.ContentManager/AboutForm.cs index 092f05f8..38f9fdb0 100644 --- a/tools/Exomia.Framework.ContentManager/AboutForm.cs +++ b/tools/Exomia.Framework.ContentManager/AboutForm.cs @@ -24,7 +24,7 @@ public AboutForm() private void OnLoad(object sender, EventArgs e) { - var assembly = Assembly.GetExecutingAssembly(); + Assembly? assembly = Assembly.GetExecutingAssembly(); Text = $"About {assembly.GetCustomAttribute().Title}"; productNameLbl.Text = assembly.GetCustomAttribute().Product; versionLbl.Text = $"Version {assembly.GetName().Version}"; diff --git a/tools/Exomia.Framework.ContentManager/CreateProjectForm.cs b/tools/Exomia.Framework.ContentManager/CreateProjectForm.cs index 32ec1325..f634f7ad 100644 --- a/tools/Exomia.Framework.ContentManager/CreateProjectForm.cs +++ b/tools/Exomia.Framework.ContentManager/CreateProjectForm.cs @@ -37,13 +37,13 @@ public CreateProjectForm() /// public ProjectFile CreateProjectFile() { - var directoryInfo = new DirectoryInfo(Path.Combine(locationTb.Text, nameTb.Text)); + DirectoryInfo? directoryInfo = new DirectoryInfo(Path.Combine(locationTb.Text, nameTb.Text)); if (!directoryInfo.Exists) { directoryInfo.Create(); } - var projectFile = new ProjectFile(nameTb.Text, directoryInfo.FullName) + ProjectFile? projectFile = new ProjectFile(nameTb.Text, directoryInfo.FullName) { Content = new ContentPropertyGridItem { @@ -73,7 +73,7 @@ private void button1_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(locationTb.Text) || string.IsNullOrEmpty(nameTb.Text)) { return; } - var fileInfo = new FileInfo(Path.Combine(locationTb.Text, nameTb.Text, $"{nameTb.Text}.ecp")); + FileInfo? fileInfo = new FileInfo(Path.Combine(locationTb.Text, nameTb.Text, $"{nameTb.Text}.ecp")); if (fileInfo.Exists) { // ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault diff --git a/tools/Exomia.Framework.ContentManager/Json.cs b/tools/Exomia.Framework.ContentManager/Json.cs index 880e6580..9b12e199 100644 --- a/tools/Exomia.Framework.ContentManager/Json.cs +++ b/tools/Exomia.Framework.ContentManager/Json.cs @@ -42,8 +42,8 @@ public static void Serialize(string filePath, object value) public static T? Deserialize(Stream s) where T : class { - using (var sr = new StreamReader(s)) - using (var jr = new JsonTextReader(sr)) + using (StreamReader? sr = new StreamReader(s)) + using (JsonTextReader? jr = new JsonTextReader(sr)) { return s_jsonSerializer.Deserialize(jr); } @@ -51,7 +51,7 @@ public static void Serialize(string filePath, object value) public static T? Deserialize(string filePath) where T : class { - using (var sr = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None)) + using (FileStream? sr = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None)) { return Deserialize(sr); } diff --git a/tools/Exomia.Framework.ContentManager/MainForm.Build.cs b/tools/Exomia.Framework.ContentManager/MainForm.Build.cs index 8c54a466..588747a9 100644 --- a/tools/Exomia.Framework.ContentManager/MainForm.Build.cs +++ b/tools/Exomia.Framework.ContentManager/MainForm.Build.cs @@ -48,7 +48,7 @@ private void CancelBuild() int skipped = 0; int failed = 0; - var rootNode = treeView1.Nodes[ROOT_KEY_PREFIX]; + TreeNode? rootNode = treeView1.Nodes[ROOT_KEY_PREFIX]; async Task ForTreeNode(TreeNode node, ContentPropertyGridItem contentPropertyGridItem) { diff --git a/tools/Exomia.Framework.ContentManager/MainForm.Core.cs b/tools/Exomia.Framework.ContentManager/MainForm.Core.cs index 405bf453..885c5b82 100644 --- a/tools/Exomia.Framework.ContentManager/MainForm.Core.cs +++ b/tools/Exomia.Framework.ContentManager/MainForm.Core.cs @@ -104,7 +104,8 @@ private void EditItem(TreeNode node) Path.Combine(_projectFile!.Location, item.VirtualPath, item.Name)); if (description == null) { return; } - using (var jsonEditorForm = new JsonEditorForm(description) { Text = $"Edit font '{item.Name}'" }) + using (JsonEditorForm? jsonEditorForm = + new JsonEditorForm(description) { Text = $"Edit font '{item.Name}'" }) { if (jsonEditorForm.ShowDialog() != DialogResult.OK) { diff --git a/tools/Exomia.Framework.ContentManager/MainForm.Events.cs b/tools/Exomia.Framework.ContentManager/MainForm.Events.cs index 28f46fcb..ff339abd 100644 --- a/tools/Exomia.Framework.ContentManager/MainForm.Events.cs +++ b/tools/Exomia.Framework.ContentManager/MainForm.Events.cs @@ -116,8 +116,8 @@ private void openToolStripMenuItem_Click(object sender, EventArgs e) .OfType() .OrderBy(p => p.VirtualPath!.Length)) { - var n = GetNodeFromPath(node, f.VirtualPath!) - ?? throw new InvalidDataException("The project file is corrupt!"); + TreeNode? n = GetNodeFromPath(node, f.VirtualPath!) + ?? throw new InvalidDataException("The project file is corrupt!"); int nodeCount = n.GetNodeCount(false); n = n.Nodes.Add( $"{FOLDER_KEY_PREFIX}{nodeCount}", f.Name, 1, 1); @@ -129,8 +129,8 @@ private void openToolStripMenuItem_Click(object sender, EventArgs e) .Resources .OfType()) { - var n = GetNodeFromPath(node, i.VirtualPath!) - ?? throw new InvalidDataException("The project file is corrupt!"); + TreeNode? n = GetNodeFromPath(node, i.VirtualPath!) + ?? throw new InvalidDataException("The project file is corrupt!"); int nodeCount = n.GetNodeCount(false); n = n.Nodes.Add( $"{FONT_KEY_PREFIX}{nodeCount}", i.Name, 4, 4); @@ -364,7 +364,7 @@ private void addFolderToolStripMenuItem_Click(object sender, EventArgs e) treeView1.InvokeIfRequired( x => { - var selectedNode = x.SelectedNode ?? x.TopNode; + TreeNode? selectedNode = x.SelectedNode ?? x.TopNode; if (selectedNode == null) { return; } int selectedNodeCount = selectedNode.GetNodeCount(false); @@ -375,7 +375,7 @@ private void addFolderToolStripMenuItem_Click(object sender, EventArgs e) di.Create(); } - var node = selectedNode.Nodes.Add($"{FOLDER_KEY_PREFIX}{selectedNodeCount}", di.Name, 1, 1); + TreeNode? node = selectedNode.Nodes.Add($"{FOLDER_KEY_PREFIX}{selectedNodeCount}", di.Name, 1, 1); node.Tag = _projectFile.AddResource( new FolderPropertyGridItem { @@ -409,11 +409,11 @@ private void addFontToolStripMenuItem_Click(object sender, EventArgs e) treeView1.InvokeIfRequired( x => { - var selectedNode = x.SelectedNode ?? x.TopNode; + TreeNode? selectedNode = x.SelectedNode ?? x.TopNode; if (selectedNode == null) { return; } int selectedNodeCount = selectedNode.GetNodeCount(false); - using (var jsonEditorForm = new JsonEditorForm( + using (JsonEditorForm? jsonEditorForm = new JsonEditorForm( new FontDescription { Name = "Arial", @@ -442,7 +442,7 @@ private void addFontToolStripMenuItem_Click(object sender, EventArgs e) jsonEditorForm.Save(fntFilePath); - var node = selectedNode.Nodes.Add( + TreeNode? node = selectedNode.Nodes.Add( $"{FONT_KEY_PREFIX}{selectedNodeCount}", Path.GetFileName(fntFilePath), 4, 4); node.Tag = _projectFile.AddResource( diff --git a/tools/Exomia.Framework.ContentManager/MainForm.cs b/tools/Exomia.Framework.ContentManager/MainForm.cs index 90896190..138b3293 100644 --- a/tools/Exomia.Framework.ContentManager/MainForm.cs +++ b/tools/Exomia.Framework.ContentManager/MainForm.cs @@ -112,7 +112,7 @@ private void WriteLine(string text, params object?[] args) richTextBox1.InvokeIfRequired( x => { - var matches = Regex.Matches(text, "\\{([0-9]+)(?:\\:([A-Za-z]+))?\\}"); + MatchCollection? matches = Regex.Matches(text, "\\{([0-9]+)(?:\\:([A-Za-z]+))?\\}"); if (matches.Count <= 0) { From 6e0d35804766af91650bab0e96a1bfb501fef8dd Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Fri, 6 Nov 2020 21:43:40 +0100 Subject: [PATCH 02/44] updated wiki --- framework.wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework.wiki b/framework.wiki index ed40697d..f37f26df 160000 --- a/framework.wiki +++ b/framework.wiki @@ -1 +1 @@ -Subproject commit ed40697d3ea5107efe55efd3599d2f5749ea0838 +Subproject commit f37f26df0a1331cf901c06c160e1aac02075f082 From 8114f2cbf4ff248104d8e3babba6dc23678152c4 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Sat, 7 Nov 2020 00:21:24 +0100 Subject: [PATCH 03/44] internal changes --- .../Game/Desktop/GamePlatformWindows.cs | 29 ++++++ .../GameWindowWindows.cs} | 81 ++++++---------- src/Exomia.Framework/Game/Game.cs | 69 +++++++------- src/Exomia.Framework/Game/GamePlatform.cs | 93 +++++++++++++++++++ src/Exomia.Framework/Game/IGameWindow.cs | 52 +++++------ .../Game/IWinFormsGameWindow.cs | 26 ------ .../Game/RenderForm.Events.cs | 6 ++ .../Graphics/GraphicsDevice.cs | 2 +- 8 files changed, 215 insertions(+), 143 deletions(-) create mode 100644 src/Exomia.Framework/Game/Desktop/GamePlatformWindows.cs rename src/Exomia.Framework/Game/{WinFormsGameWindow.cs => Desktop/GameWindowWindows.cs} (73%) create mode 100644 src/Exomia.Framework/Game/GamePlatform.cs delete mode 100644 src/Exomia.Framework/Game/IWinFormsGameWindow.cs diff --git a/src/Exomia.Framework/Game/Desktop/GamePlatformWindows.cs b/src/Exomia.Framework/Game/Desktop/GamePlatformWindows.cs new file mode 100644 index 00000000..15d6cd4c --- /dev/null +++ b/src/Exomia.Framework/Game/Desktop/GamePlatformWindows.cs @@ -0,0 +1,29 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using Exomia.Framework.Input; + +namespace Exomia.Framework.Game.Desktop +{ + sealed class GamePlatformWindows : GamePlatform + { + /// + public GamePlatformWindows(Game game, string title) + : base(game, title) { } + + /// + private protected override IGameWindow CreateGameWindow(Game game, string title) + { + GameWindowWindows gameWindow = new GameWindowWindows(title); + game.Services.AddService(gameWindow.RenderForm); + return gameWindow; + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Game/WinFormsGameWindow.cs b/src/Exomia.Framework/Game/Desktop/GameWindowWindows.cs similarity index 73% rename from src/Exomia.Framework/Game/WinFormsGameWindow.cs rename to src/Exomia.Framework/Game/Desktop/GameWindowWindows.cs index dd8f6145..2cf08ae5 100644 --- a/src/Exomia.Framework/Game/WinFormsGameWindow.cs +++ b/src/Exomia.Framework/Game/Desktop/GameWindowWindows.cs @@ -11,59 +11,44 @@ using System; using Exomia.Framework.Win32; -namespace Exomia.Framework.Game +namespace Exomia.Framework.Game.Desktop { /// /// Form for viewing the window forms game. This class cannot be inherited. /// - sealed class WinFormsGameWindow : IWinFormsGameWindow, IGameWindowInitialize + sealed class GameWindowWindows : IGameWindow { - /// - /// Occurs when the form is about to close. - /// + /// public event RefEventHandler FormClosing { add { _renderForm.FormClosing += value; } remove { _renderForm.FormClosing -= value; } } + /// + public event EventHandler FormClosed + { + add { _renderForm.FormClosed += value; } + remove { _renderForm.FormClosed -= value; } + } + private readonly RenderForm _renderForm; private bool _isInitialized; - /// - /// Gets the width. - /// - /// - /// The width. - /// + + /// public int Width { get { return _renderForm.Size.X; } } - - /// - /// Gets the height. - /// - /// - /// The height. - /// + + /// public int Height { get { return _renderForm.Size.Y; } } /// - public RenderForm RenderForm - { - get { return _renderForm; } - } - - /// - /// Gets or sets the title. - /// - /// - /// The title. - /// public string Title { get { return _renderForm.WindowTitle; } @@ -71,40 +56,33 @@ public string Title } /// - /// Gets a value indicating whether this object is initialized. + /// Gets the render form. /// /// - /// True if this object is initialized, false if not. + /// The render form. /// - bool IGameWindowInitialize.IsInitialized + public RenderForm RenderForm { - get { return _isInitialized; } + get { return _renderForm; } } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The title. - public WinFormsGameWindow(string title) + public GameWindowWindows(string title) { _renderForm = new RenderForm(title); } - - /// - /// Resizes. - /// - /// The width. - /// The height. + + /// public void Resize(int width, int height) { _renderForm.Resize(width, height); } - /// - /// Initializes this object. - /// - /// [in,out] Options for controlling the operation. - void IGameWindowInitialize.Initialize(ref GameGraphicsParameters parameters) + /// + public void Initialize(ref GameGraphicsParameters parameters) { if (_isInitialized) { return; } @@ -166,16 +144,13 @@ void IGameWindowInitialize.Initialize(ref GameGraphicsParameters parameters) _isInitialized = true; } - void IGameWindowInitialize.Show() + /// + public void Show() { _renderForm.Show(); } #region IDisposable Support - - /// - /// True if disposed. - /// private bool _disposed; /// @@ -199,9 +174,9 @@ private void Dispose(bool disposing) } /// - /// Finalizes an instance of the class. + /// Finalizes an instance of the class. /// - ~WinFormsGameWindow() + ~GameWindowWindows() { Dispose(false); } diff --git a/src/Exomia.Framework/Game/Game.cs b/src/Exomia.Framework/Game/Game.cs index dcd3270e..0e92de8d 100644 --- a/src/Exomia.Framework/Game/Game.cs +++ b/src/Exomia.Framework/Game/Game.cs @@ -44,10 +44,9 @@ public abstract class Game : IRunnable private readonly List _updateableComponent; private readonly IServiceRegistry _serviceRegistry; private readonly DisposeCollector _collector; - private readonly IGameWindowInitialize _gameWindowInitialize; private readonly IInputDevice _inputDevice; private readonly IContentManager _contentManager; - private readonly IGameWindow _gameWindow; + private readonly GamePlatform _platform; private readonly GraphicsDevice _graphicsDevice; private bool _isRunning, _isInitialized, _isContentLoaded, _shutdown; @@ -81,7 +80,7 @@ public IContentManager Content /// public IGameWindow GameWindow { - get { return _gameWindow; } + get { return _platform.MainWindow; } } /// @@ -126,10 +125,10 @@ public bool IsRunning } /// - /// Gets or sets the target elapsed time. + /// Gets or sets the target elapsed time in ms. /// /// - /// The target elapsed time. + /// The target elapsed time in ms. /// public double TargetElapsedTime { get; set; } = 1000.0 / 60.0; @@ -157,16 +156,14 @@ protected Game(string title = "Exomia.Framework", _collector = new DisposeCollector(); _serviceRegistry = new ServiceRegistry(); - // TODO: use a factory? - WinFormsGameWindow gameWindow = new WinFormsGameWindow(title); - gameWindow.FormClosing += (ref bool cancel) => { Shutdown(); }; - - _gameWindowInitialize = gameWindow; - _serviceRegistry.AddService(_gameWindow = gameWindow); - _serviceRegistry.AddService(_graphicsDevice = new GraphicsDevice()); _serviceRegistry.AddService(_contentManager = new ContentManager(_serviceRegistry)); - _serviceRegistry.AddService(_inputDevice = gameWindow.RenderForm); + + _platform = GamePlatform.Create(this, title); + _serviceRegistry.AddService(_platform.MainWindow); + + // NOTE: The input device should be registered during the platform creation! + _inputDevice = _serviceRegistry.GetService(); } /// @@ -178,12 +175,12 @@ protected Game(string title = "Exomia.Framework", } /// - /// add a new game system. + /// Adds an item to the game. /// /// T. /// item. /// - /// true if successfully added; false otherwise. + /// The item. /// public T Add(T item) { @@ -281,12 +278,12 @@ public T Add(T item) } /// - /// add a new game system. + /// Remove an item from the game. /// - /// T. + /// Generic type parameter. /// item. /// - /// true if successfully added; false otherwise. + /// The item. /// public T Remove(T item) { @@ -343,7 +340,7 @@ public T Remove(T item) } /// - /// get a game system by name. + /// Get a game component by its name. /// /// the game system name. /// [out] out found game system. @@ -364,7 +361,7 @@ public void Run() { if (_isRunning) { - throw new InvalidOperationException("Can't run this instance while it is already running."); + throw new InvalidOperationException("The instance is already running!"); } _isRunning = true; @@ -373,6 +370,9 @@ public void Run() { Initialize(); LoadContent(); + + _platform.ShowMainWindow(); + Renderloop(); UnloadContent(); } @@ -425,6 +425,7 @@ void OnIsRunningChanged(Game s, bool v) } Update(gameTime); + if (BeginFrame()) { Draw(gameTime); @@ -434,11 +435,11 @@ void OnIsRunningChanged(Game s, bool v) if (IsFixedTimeStep) { //SLEEP - while (TargetElapsedTime - stopwatch.Elapsed.TotalMilliseconds > FIXED_TIMESTAMP_THRESHOLD) + while (TargetElapsedTime - FIXED_TIMESTAMP_THRESHOLD > stopwatch.Elapsed.TotalMilliseconds) { - Thread.Sleep(1); + Thread.Yield(); } - + //IDLE while (stopwatch.Elapsed.TotalMilliseconds < TargetElapsedTime) { } } @@ -514,7 +515,7 @@ private void InitializeGameGraphicsParameters() OnInitializeGameGraphicsParameters(ref parameters); - _gameWindowInitialize.Initialize(ref parameters); + _platform.Initialize(ref parameters); _graphicsDevice.Initialize(ref parameters); GameGraphicsParameters = parameters; @@ -544,8 +545,8 @@ private void Initialize() OnInitialize(); InitializePendingInitializations(); _isInitialized = true; + OnAfterInitialize(); - _gameWindowInitialize.Show(); } } @@ -570,7 +571,6 @@ private void LoadContent() { if (!_isContentLoaded) { - _isContentLoaded = true; OnLoadContent(); lock (_contentableComponent) @@ -584,6 +584,8 @@ private void LoadContent() } _currentlyContentableComponent.Clear(); + + _isContentLoaded = true; } } @@ -607,11 +609,12 @@ private void UnloadContent() _currentlyContentableComponent.Clear(); OnUnloadContent(); + _isContentLoaded = false; } } - #endregion Content + #endregion #region Update @@ -789,10 +792,10 @@ public Timer2 AddTimer(float tick, #region IDisposable Support /// - /// adds a IDisposable object to the dispose collector. + /// Adds a object to the dispose collector. /// - /// . - /// . + /// Generic type parameter. + /// The object. /// /// Obj as a T. /// @@ -801,9 +804,6 @@ public T ToDispose(T obj) where T : IDisposable return _collector.Collect(obj); } - /// - /// True if disposed. - /// private bool _disposed; /// @@ -845,9 +845,10 @@ private void Dispose(bool disposing) _gameComponents.Clear(); _pendingInitializables.Clear(); + _platform.Dispose(); + _contentManager.Dispose(); _graphicsDevice.Dispose(); - _gameWindow.Dispose(); } _collector.DisposeAndClear(disposing); diff --git a/src/Exomia.Framework/Game/GamePlatform.cs b/src/Exomia.Framework/Game/GamePlatform.cs new file mode 100644 index 00000000..37fff279 --- /dev/null +++ b/src/Exomia.Framework/Game/GamePlatform.cs @@ -0,0 +1,93 @@ +using System; +using Exomia.Framework.Game.Desktop; + +namespace Exomia.Framework.Game +{ + abstract class GamePlatform : IDisposable + { + private readonly IGameWindow _mainWindow; + + public IGameWindow MainWindow + { + get { return _mainWindow; } + } + + protected GamePlatform(Game game, string title) + { + // ReSharper disable once VirtualMemberCallInConstructor + _mainWindow = CreateGameWindow(game, title); + _mainWindow.FormClosed += game.Shutdown; + } + + private protected abstract IGameWindow CreateGameWindow(Game game, string title); + + /// + /// Creates a new . + /// + /// The game. + /// The title. + /// + /// A . + /// + public static GamePlatform Create(Game game, string title) + { + return new GamePlatformWindows(game, title); + } + + #region IDisposable Support + private bool _disposed = false; + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged/managed resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (!_disposed) + { + OnDispose(disposing); + if (disposing) + { + _mainWindow.Dispose(); + } + _disposed = true; + } + } + + /// + ~GamePlatform() + { + Dispose(false); + } + + /// + /// called then the instance is disposing + /// + /// true if user code; false called by finalizer + protected virtual void OnDispose(bool disposing) { } + + #endregion + + /// + /// Initializes the . + /// + /// [in,out] Options for controlling the operation. + public void Initialize(ref GameGraphicsParameters parameters) + { + _mainWindow.Initialize(ref parameters); + } + + /// + /// Shows the main window. + /// + public void ShowMainWindow() + { + _mainWindow.Show(); + } + } +} diff --git a/src/Exomia.Framework/Game/IGameWindow.cs b/src/Exomia.Framework/Game/IGameWindow.cs index 95ef3a4e..bad7fcb8 100644 --- a/src/Exomia.Framework/Game/IGameWindow.cs +++ b/src/Exomia.Framework/Game/IGameWindow.cs @@ -12,30 +12,8 @@ namespace Exomia.Framework.Game { - interface IGameWindowInitialize - { - /// - /// Gets a value indicating whether this object is initialized. - /// - /// - /// True if this object is initialized, false if not. - /// - bool IsInitialized { get; } - - /// - /// Initializes this object. - /// - /// [in,out] Options for controlling the operation. - void Initialize(ref GameGraphicsParameters parameters); - - /// - /// Shows this object. - /// - void Show(); - } - /// - /// IGameWindow interface. + /// Interface for game window. /// public interface IGameWindow : IDisposable { @@ -45,12 +23,9 @@ public interface IGameWindow : IDisposable event RefEventHandler FormClosing; /// - /// Gets the height. + /// Occurs when the form is closed. /// - /// - /// The height. - /// - int Height { get; } + event EventHandler FormClosed; /// /// Gets or sets the title. @@ -60,6 +35,14 @@ public interface IGameWindow : IDisposable /// string Title { get; set; } + /// + /// Gets the height. + /// + /// + /// The height. + /// + int Height { get; } + /// /// Gets the width. /// @@ -69,10 +52,21 @@ public interface IGameWindow : IDisposable int Width { get; } /// - /// Resizes. + /// Resizes the game window. /// /// The width. /// The height. void Resize(int width, int height); + + /// + /// Initializes this object. + /// + /// [in,out] Options for controlling the operation. + void Initialize(ref GameGraphicsParameters parameters); + + /// + /// Shows the game window. + /// + void Show(); } } \ No newline at end of file diff --git a/src/Exomia.Framework/Game/IWinFormsGameWindow.cs b/src/Exomia.Framework/Game/IWinFormsGameWindow.cs deleted file mode 100644 index 1e61703b..00000000 --- a/src/Exomia.Framework/Game/IWinFormsGameWindow.cs +++ /dev/null @@ -1,26 +0,0 @@ -#region License - -// Copyright (c) 2018-2020, exomia -// All rights reserved. -// -// This source code is licensed under the BSD-style license found in the -// LICENSE file in the root directory of this source tree. - -#endregion - -namespace Exomia.Framework.Game -{ - /// - /// IWinFormsGameWindow interface. - /// - public interface IWinFormsGameWindow : IGameWindow - { - /// - /// Gets the render form. - /// - /// - /// The render form. - /// - RenderForm RenderForm { get; } - } -} \ No newline at end of file diff --git a/src/Exomia.Framework/Game/RenderForm.Events.cs b/src/Exomia.Framework/Game/RenderForm.Events.cs index 7ddcbd5c..6387752a 100644 --- a/src/Exomia.Framework/Game/RenderForm.Events.cs +++ b/src/Exomia.Framework/Game/RenderForm.Events.cs @@ -46,6 +46,11 @@ sealed partial class RenderForm /// public event RefEventHandler? FormClosing; + /// + /// Occurs when the form is closed. + /// + public event EventHandler? FormClosed; + private unsafe IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) { Message m; @@ -96,6 +101,7 @@ private unsafe IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lPara FormClosing?.Invoke(ref cancel); if (!cancel) { + FormClosed?.Invoke(); User32.DestroyWindow(_hWnd); } return IntPtr.Zero; diff --git a/src/Exomia.Framework/Graphics/GraphicsDevice.cs b/src/Exomia.Framework/Graphics/GraphicsDevice.cs index f300dc7e..b8ae410f 100644 --- a/src/Exomia.Framework/Graphics/GraphicsDevice.cs +++ b/src/Exomia.Framework/Graphics/GraphicsDevice.cs @@ -231,7 +231,7 @@ public void EndFrame() } /// - /// Initializes this object. + /// Initializes the . /// /// [in,out] Options for controlling the operation. public void Initialize(ref GameGraphicsParameters parameters) From 299e001dc0af42f5bd7ba2110d401c90f3acc034 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Sat, 7 Nov 2020 00:21:49 +0100 Subject: [PATCH 04/44] updated wiki --- framework.wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework.wiki b/framework.wiki index f37f26df..fe71e576 160000 --- a/framework.wiki +++ b/framework.wiki @@ -1 +1 @@ -Subproject commit f37f26df0a1331cf901c06c160e1aac02075f082 +Subproject commit fe71e576d303aeb21822dec7a3a2939b5c039d7c From 2bdc552c41c7bffe53a633f48c295c3fd74d2047 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Sat, 7 Nov 2020 00:36:46 +0100 Subject: [PATCH 05/44] moved camera to other namespace --- src/Exomia.Framework/{Graphics => Game}/Camera/Camera3D.cs | 3 +-- .../Camera/Controller/RotationController.cs | 3 +-- .../Camera/Controller/TranslationKeyboardController.cs | 3 +-- src/Exomia.Framework/{Graphics => Game}/Camera/ICamera.cs | 2 +- .../{Graphics => Game}/Camera/ICameraComponent.cs | 2 +- .../{Graphics => Game}/Camera/IDisposableCameraComponent.cs | 2 +- .../Camera/IInitializableCameraComponent.cs | 2 +- .../{Graphics => Game}/Camera/IUpdateableCameraComponent.cs | 4 +--- 8 files changed, 8 insertions(+), 13 deletions(-) rename src/Exomia.Framework/{Graphics => Game}/Camera/Camera3D.cs (99%) rename src/Exomia.Framework/{Graphics => Game}/Camera/Controller/RotationController.cs (97%) rename src/Exomia.Framework/{Graphics => Game}/Camera/Controller/TranslationKeyboardController.cs (97%) rename src/Exomia.Framework/{Graphics => Game}/Camera/ICamera.cs (98%) rename src/Exomia.Framework/{Graphics => Game}/Camera/ICameraComponent.cs (92%) rename src/Exomia.Framework/{Graphics => Game}/Camera/IDisposableCameraComponent.cs (93%) rename src/Exomia.Framework/{Graphics => Game}/Camera/IInitializableCameraComponent.cs (93%) rename src/Exomia.Framework/{Graphics => Game}/Camera/IUpdateableCameraComponent.cs (89%) diff --git a/src/Exomia.Framework/Graphics/Camera/Camera3D.cs b/src/Exomia.Framework/Game/Camera/Camera3D.cs similarity index 99% rename from src/Exomia.Framework/Graphics/Camera/Camera3D.cs rename to src/Exomia.Framework/Game/Camera/Camera3D.cs index 198c97c1..86abbc5b 100644 --- a/src/Exomia.Framework/Graphics/Camera/Camera3D.cs +++ b/src/Exomia.Framework/Game/Camera/Camera3D.cs @@ -10,11 +10,10 @@ using System; using System.Collections.Generic; -using Exomia.Framework.Game; using Exomia.Framework.Input; using SharpDX; -namespace Exomia.Framework.Graphics.Camera +namespace Exomia.Framework.Game.Camera { /// /// A camera base. diff --git a/src/Exomia.Framework/Graphics/Camera/Controller/RotationController.cs b/src/Exomia.Framework/Game/Camera/Controller/RotationController.cs similarity index 97% rename from src/Exomia.Framework/Graphics/Camera/Controller/RotationController.cs rename to src/Exomia.Framework/Game/Camera/Controller/RotationController.cs index fd40f04b..c18c3252 100644 --- a/src/Exomia.Framework/Graphics/Camera/Controller/RotationController.cs +++ b/src/Exomia.Framework/Game/Camera/Controller/RotationController.cs @@ -10,12 +10,11 @@ using System; using System.Threading; -using Exomia.Framework.Game; using Exomia.Framework.Input; using Exomia.Framework.Mathematics; using SharpDX; -namespace Exomia.Framework.Graphics.Camera.Controller +namespace Exomia.Framework.Game.Camera.Controller { /// /// A controller for handling rotations. This class cannot be inherited. diff --git a/src/Exomia.Framework/Graphics/Camera/Controller/TranslationKeyboardController.cs b/src/Exomia.Framework/Game/Camera/Controller/TranslationKeyboardController.cs similarity index 97% rename from src/Exomia.Framework/Graphics/Camera/Controller/TranslationKeyboardController.cs rename to src/Exomia.Framework/Game/Camera/Controller/TranslationKeyboardController.cs index 1731984a..80fa5507 100644 --- a/src/Exomia.Framework/Graphics/Camera/Controller/TranslationKeyboardController.cs +++ b/src/Exomia.Framework/Game/Camera/Controller/TranslationKeyboardController.cs @@ -9,11 +9,10 @@ #endregion using System.Collections.Generic; -using Exomia.Framework.Game; using Exomia.Framework.Input; using SharpDX; -namespace Exomia.Framework.Graphics.Camera.Controller +namespace Exomia.Framework.Game.Camera.Controller { /// /// A controller for handling translation keyboards. This class cannot be inherited. diff --git a/src/Exomia.Framework/Graphics/Camera/ICamera.cs b/src/Exomia.Framework/Game/Camera/ICamera.cs similarity index 98% rename from src/Exomia.Framework/Graphics/Camera/ICamera.cs rename to src/Exomia.Framework/Game/Camera/ICamera.cs index af4ce15f..c3c0ca4f 100644 --- a/src/Exomia.Framework/Graphics/Camera/ICamera.cs +++ b/src/Exomia.Framework/Game/Camera/ICamera.cs @@ -11,7 +11,7 @@ using Exomia.Framework.Input; using SharpDX; -namespace Exomia.Framework.Graphics.Camera +namespace Exomia.Framework.Game.Camera { /// /// Interface for a camera. diff --git a/src/Exomia.Framework/Graphics/Camera/ICameraComponent.cs b/src/Exomia.Framework/Game/Camera/ICameraComponent.cs similarity index 92% rename from src/Exomia.Framework/Graphics/Camera/ICameraComponent.cs rename to src/Exomia.Framework/Game/Camera/ICameraComponent.cs index fc38f35d..9df7560a 100644 --- a/src/Exomia.Framework/Graphics/Camera/ICameraComponent.cs +++ b/src/Exomia.Framework/Game/Camera/ICameraComponent.cs @@ -8,7 +8,7 @@ #endregion -namespace Exomia.Framework.Graphics.Camera +namespace Exomia.Framework.Game.Camera { /// /// Interface for camera component. diff --git a/src/Exomia.Framework/Graphics/Camera/IDisposableCameraComponent.cs b/src/Exomia.Framework/Game/Camera/IDisposableCameraComponent.cs similarity index 93% rename from src/Exomia.Framework/Graphics/Camera/IDisposableCameraComponent.cs rename to src/Exomia.Framework/Game/Camera/IDisposableCameraComponent.cs index ba602ef3..af411193 100644 --- a/src/Exomia.Framework/Graphics/Camera/IDisposableCameraComponent.cs +++ b/src/Exomia.Framework/Game/Camera/IDisposableCameraComponent.cs @@ -6,7 +6,7 @@ // LICENSE file in the root directory of this source tree. #endregion -namespace Exomia.Framework.Graphics.Camera { +namespace Exomia.Framework.Game.Camera { /// /// Interface for disposable camera component. /// diff --git a/src/Exomia.Framework/Graphics/Camera/IInitializableCameraComponent.cs b/src/Exomia.Framework/Game/Camera/IInitializableCameraComponent.cs similarity index 93% rename from src/Exomia.Framework/Graphics/Camera/IInitializableCameraComponent.cs rename to src/Exomia.Framework/Game/Camera/IInitializableCameraComponent.cs index 4298dba2..6f513c98 100644 --- a/src/Exomia.Framework/Graphics/Camera/IInitializableCameraComponent.cs +++ b/src/Exomia.Framework/Game/Camera/IInitializableCameraComponent.cs @@ -8,7 +8,7 @@ #endregion -namespace Exomia.Framework.Graphics.Camera +namespace Exomia.Framework.Game.Camera { /// /// Interface for initializable camera component. diff --git a/src/Exomia.Framework/Graphics/Camera/IUpdateableCameraComponent.cs b/src/Exomia.Framework/Game/Camera/IUpdateableCameraComponent.cs similarity index 89% rename from src/Exomia.Framework/Graphics/Camera/IUpdateableCameraComponent.cs rename to src/Exomia.Framework/Game/Camera/IUpdateableCameraComponent.cs index d811f666..ad71bbdf 100644 --- a/src/Exomia.Framework/Graphics/Camera/IUpdateableCameraComponent.cs +++ b/src/Exomia.Framework/Game/Camera/IUpdateableCameraComponent.cs @@ -8,9 +8,7 @@ #endregion -using Exomia.Framework.Game; - -namespace Exomia.Framework.Graphics.Camera +namespace Exomia.Framework.Game.Camera { /// /// Interface for updateable camera component. From 8f1ecb5e537f684671cb00c64700e29939d8e517 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Sun, 8 Nov 2020 01:29:53 +0100 Subject: [PATCH 06/44] removed fileinfo support for content loading/unloading --- .../Content/ContentManager.cs | 37 +++--------------- .../Content/ContentReaderParameters.cs | 6 +-- .../Content/IContentManager.cs | 39 ------------------- 3 files changed, 8 insertions(+), 74 deletions(-) diff --git a/src/Exomia.Framework/Content/ContentManager.cs b/src/Exomia.Framework/Content/ContentManager.cs index 0d7c156e..d12d6c75 100644 --- a/src/Exomia.Framework/Content/ContentManager.cs +++ b/src/Exomia.Framework/Content/ContentManager.cs @@ -257,24 +257,12 @@ public object Load(Type assetType, string assetName, bool fromEmbeddedResource = } } - /// - public object Load(Type assetType, FileInfo assetFileInfo) - { - return Load(assetType, assetFileInfo.FullName); - } - /// public T Load(string assetName, bool fromEmbeddedResource = false) { return (T)Load(typeof(T), assetName, fromEmbeddedResource); } - /// - public T Load(FileInfo assetFileInfo) - { - return (T)Load(typeof(T), assetFileInfo.FullName); - } - /// public void Unload() { @@ -344,12 +332,6 @@ public bool Unload(string assetName) return Unload(typeof(T), assetName); } - /// - public bool Unload(FileInfo assetFileInfo) - { - return Unload(typeof(T), assetFileInfo.FullName); - } - /// /// Resolve stream. /// @@ -479,6 +461,7 @@ private object LoadAssetWithDynamicContentReader(Type assetType, string assetNam { lock (_registeredContentReaderFactories) { + // ReSharper disable once ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator foreach (IContentReaderFactory factory in _registeredContentReaderFactories) { if (factory.TryCreate(assetType, out contentReader)) @@ -511,11 +494,8 @@ private object LoadAssetWithDynamicContentReader(Type assetType, string assetNam } } } - - /// - /// An asset key. - /// - private struct AssetKey : IEquatable + + private readonly struct AssetKey : IEquatable { /// /// Initializes a new instance of the class. @@ -527,15 +507,8 @@ public AssetKey(Type assetType, string assetName) _assetType = assetType; _assetName = assetName; } - - /// - /// Type of the asset. - /// - private readonly Type _assetType; - - /// - /// Name of the asset. - /// + + private readonly Type _assetType; private readonly string _assetName; /// diff --git a/src/Exomia.Framework/Content/ContentReaderParameters.cs b/src/Exomia.Framework/Content/ContentReaderParameters.cs index 1d73a106..bfb41fb2 100644 --- a/src/Exomia.Framework/Content/ContentReaderParameters.cs +++ b/src/Exomia.Framework/Content/ContentReaderParameters.cs @@ -14,19 +14,19 @@ namespace Exomia.Framework.Content { /// - /// A content reader parameters. + /// The content reader parameters. /// public struct ContentReaderParameters { /// /// Name of the asset currently loaded when using - /// or . + /// . /// public string AssetName { get; } /// /// Type of the asset currently loaded when using - /// or . + /// . /// public Type AssetType { get; } diff --git a/src/Exomia.Framework/Content/IContentManager.cs b/src/Exomia.Framework/Content/IContentManager.cs index ab73c456..a514cf85 100644 --- a/src/Exomia.Framework/Content/IContentManager.cs +++ b/src/Exomia.Framework/Content/IContentManager.cs @@ -9,7 +9,6 @@ #endregion using System; -using System.IO; using Exomia.Framework.Content.Resolver; using Exomia.Framework.Content.Resolver.EmbeddedResource; @@ -107,24 +106,6 @@ public interface IContentManager : IDisposable /// T Load(string assetName, bool fromEmbeddedResource = false); - /// - /// Loads an asset that has been processed by the content pipeline. - /// - /// Generic type parameter. - /// Information describing the asset file. - /// - /// A asset of type . - /// - /// - /// If the asset was not found from all - /// . - /// - /// - /// If no content reader was suitable to - /// decode the asset. - /// - T Load(FileInfo assetFileInfo); - /// /// Loads an asset that has been processed by the Content Pipeline. /// @@ -149,16 +130,6 @@ public interface IContentManager : IDisposable /// object Load(Type assetType, string assetName, bool fromEmbeddedResource = false); - /// - /// Loads an asset that has been processed by the Content Pipeline. - /// - /// Asset Type. - /// Information describing the asset file. - /// - /// An asset of type . - /// - object Load(Type assetType, FileInfo assetFileInfo); - /// /// Unloads all data that was loaded by this ContentManager. All data will be disposed. /// @@ -178,16 +149,6 @@ public interface IContentManager : IDisposable /// bool Unload(string assetName); - /// - /// Unloads and disposes an asset. - /// - /// Generic type parameter. - /// Information describing the asset file. - /// - /// true if the asset exists and was unloaded, false otherwise. - /// - bool Unload(FileInfo assetFileInfo); - /// /// Unloads and disposes an asset. /// From 264977ac6b638d01644bf2f5e0eccabedc1fc7c4 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Sun, 8 Nov 2020 02:24:05 +0100 Subject: [PATCH 07/44] cleanup & ref --- .../Content/ContentManager.cs | 4 +- .../Game/Desktop/GameWindowWindows.cs | 6 +- src/Exomia.Framework/Game/Game.cs | 37 +--------- .../Game/GameGraphicsParameters.cs | 49 +++++++++++++ src/Exomia.Framework/Game/GamePlatform.cs | 69 +++++++++++-------- .../Graphics/GraphicsDevice.cs | 4 +- src/Exomia.Framework/Graphics/SpriteBatch.cs | 20 +++--- src/Exomia.Framework/Graphics/Textures.cs | 2 +- 8 files changed, 110 insertions(+), 81 deletions(-) diff --git a/src/Exomia.Framework/Content/ContentManager.cs b/src/Exomia.Framework/Content/ContentManager.cs index d12d6c75..07e3799e 100644 --- a/src/Exomia.Framework/Content/ContentManager.cs +++ b/src/Exomia.Framework/Content/ContentManager.cs @@ -494,7 +494,7 @@ private object LoadAssetWithDynamicContentReader(Type assetType, string assetNam } } } - + private readonly struct AssetKey : IEquatable { /// @@ -507,7 +507,7 @@ public AssetKey(Type assetType, string assetName) _assetType = assetType; _assetName = assetName; } - + private readonly Type _assetType; private readonly string _assetName; diff --git a/src/Exomia.Framework/Game/Desktop/GameWindowWindows.cs b/src/Exomia.Framework/Game/Desktop/GameWindowWindows.cs index 2cf08ae5..8b989a2e 100644 --- a/src/Exomia.Framework/Game/Desktop/GameWindowWindows.cs +++ b/src/Exomia.Framework/Game/Desktop/GameWindowWindows.cs @@ -35,13 +35,12 @@ public event EventHandler FormClosed private readonly RenderForm _renderForm; private bool _isInitialized; - /// public int Width { get { return _renderForm.Size.X; } } - + /// public int Height { @@ -74,7 +73,7 @@ public GameWindowWindows(string title) { _renderForm = new RenderForm(title); } - + /// public void Resize(int width, int height) { @@ -151,6 +150,7 @@ public void Show() } #region IDisposable Support + private bool _disposed; /// diff --git a/src/Exomia.Framework/Game/Game.cs b/src/Exomia.Framework/Game/Game.cs index 0e92de8d..dc6d0996 100644 --- a/src/Exomia.Framework/Game/Game.cs +++ b/src/Exomia.Framework/Game/Game.cs @@ -19,9 +19,6 @@ using Exomia.Framework.Tools; using Exomia.Framework.Win32; using SharpDX; -using SharpDX.Direct3D; -using SharpDX.Direct3D11; -using SharpDX.DXGI; namespace Exomia.Framework.Game { @@ -439,7 +436,7 @@ void OnIsRunningChanged(Game s, bool v) { Thread.Yield(); } - + //IDLE while (stopwatch.Elapsed.TotalMilliseconds < TargetElapsedTime) { } } @@ -483,35 +480,7 @@ protected virtual void OnAfterInitialize() { } /// private void InitializeGameGraphicsParameters() { - GameGraphicsParameters parameters = new GameGraphicsParameters - { - BufferCount = 1, -#if DEBUG - DeviceCreationFlags = - DeviceCreationFlags.BgraSupport | - DeviceCreationFlags.Debug, -#else - DeviceCreationFlags = - DeviceCreationFlags.BgraSupport, -#endif - DriverType = DriverType.Hardware, - Format = Format.B8G8R8A8_UNorm, - Width = 1024, - Height = 768, - DisplayType = DisplayType.Window, - IsMouseVisible = false, - Rational = new Rational(60, 1), - SwapChainFlags = SwapChainFlags.AllowModeSwitch, - SwapEffect = SwapEffect.Discard, - Usage = Usage.RenderTargetOutput, - UseVSync = false, - WindowAssociationFlags = WindowAssociationFlags.IgnoreAll, - EnableMultiSampling = false, - MultiSampleCount = MultiSampleCount.None, - AdapterLuid = -1, - OutputIndex = -1, - ClipCursor = false - }; + GameGraphicsParameters parameters = GameGraphicsParameters.Create(IntPtr.Zero); OnInitializeGameGraphicsParameters(ref parameters); @@ -792,7 +761,7 @@ public Timer2 AddTimer(float tick, #region IDisposable Support /// - /// Adds a object to the dispose collector. + /// Adds a object to the dispose collector. /// /// Generic type parameter. /// The object. diff --git a/src/Exomia.Framework/Game/GameGraphicsParameters.cs b/src/Exomia.Framework/Game/GameGraphicsParameters.cs index 2ba51426..e0aadb7c 100644 --- a/src/Exomia.Framework/Game/GameGraphicsParameters.cs +++ b/src/Exomia.Framework/Game/GameGraphicsParameters.cs @@ -124,5 +124,54 @@ public struct GameGraphicsParameters /// The output index. /// public int OutputIndex; + + /// + /// Creates a new object with default settings. + /// + /// The handle. + /// + /// (Optional) + /// Define the width of the . + /// + /// + /// (Optional) + /// Define the height of the . + /// + /// + /// The . + /// + public static GameGraphicsParameters Create(IntPtr handle, int width = 1024, int height = 768) + { + return new GameGraphicsParameters + { + Handle = handle, + BufferCount = 1, +#if DEBUG + DeviceCreationFlags = + DeviceCreationFlags.BgraSupport | + DeviceCreationFlags.Debug, +#else + DeviceCreationFlags = + DeviceCreationFlags.BgraSupport, +#endif + DriverType = DriverType.Hardware, + Format = Format.B8G8R8A8_UNorm, + Width = width, + Height = height, + DisplayType = DisplayType.Window, + IsMouseVisible = false, + Rational = new Rational(60, 1), + SwapChainFlags = SwapChainFlags.AllowModeSwitch, + SwapEffect = SwapEffect.Discard, + Usage = Usage.RenderTargetOutput, + UseVSync = false, + WindowAssociationFlags = WindowAssociationFlags.IgnoreAll, + EnableMultiSampling = false, + MultiSampleCount = MultiSampleCount.None, + AdapterLuid = -1, + OutputIndex = -1, + ClipCursor = false + }; + } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Game/GamePlatform.cs b/src/Exomia.Framework/Game/GamePlatform.cs index 37fff279..6204f4fd 100644 --- a/src/Exomia.Framework/Game/GamePlatform.cs +++ b/src/Exomia.Framework/Game/GamePlatform.cs @@ -1,17 +1,27 @@ -using System; +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; using Exomia.Framework.Game.Desktop; namespace Exomia.Framework.Game { abstract class GamePlatform : IDisposable { - private readonly IGameWindow _mainWindow; + private readonly IGameWindow _mainWindow; public IGameWindow MainWindow { get { return _mainWindow; } } - + protected GamePlatform(Game game, string title) { // ReSharper disable once VirtualMemberCallInConstructor @@ -19,26 +29,44 @@ protected GamePlatform(Game game, string title) _mainWindow.FormClosed += game.Shutdown; } - private protected abstract IGameWindow CreateGameWindow(Game game, string title); - /// - /// Creates a new . + /// Creates a new . /// /// The game. /// The title. /// - /// A . + /// A . /// public static GamePlatform Create(Game game, string title) { return new GamePlatformWindows(game, title); } + /// + /// Initializes the . + /// + /// [in,out] Options for controlling the operation. + public void Initialize(ref GameGraphicsParameters parameters) + { + _mainWindow.Initialize(ref parameters); + } + + /// + /// Shows the main window. + /// + public void ShowMainWindow() + { + _mainWindow.Show(); + } + + private protected abstract IGameWindow CreateGameWindow(Game game, string title); + #region IDisposable Support - private bool _disposed = false; + + private bool _disposed; /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged/managed resources. + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged/managed resources. /// public void Dispose() { @@ -53,7 +81,7 @@ private void Dispose(bool disposing) OnDispose(disposing); if (disposing) { - _mainWindow.Dispose(); + _mainWindow.Dispose(); } _disposed = true; } @@ -66,28 +94,11 @@ private void Dispose(bool disposing) } /// - /// called then the instance is disposing + /// called then the instance is disposing /// /// true if user code; false called by finalizer protected virtual void OnDispose(bool disposing) { } #endregion - - /// - /// Initializes the . - /// - /// [in,out] Options for controlling the operation. - public void Initialize(ref GameGraphicsParameters parameters) - { - _mainWindow.Initialize(ref parameters); - } - - /// - /// Shows the main window. - /// - public void ShowMainWindow() - { - _mainWindow.Show(); - } } -} +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/GraphicsDevice.cs b/src/Exomia.Framework/Graphics/GraphicsDevice.cs index b8ae410f..63d721c0 100644 --- a/src/Exomia.Framework/Graphics/GraphicsDevice.cs +++ b/src/Exomia.Framework/Graphics/GraphicsDevice.cs @@ -231,7 +231,7 @@ public void EndFrame() } /// - /// Initializes the . + /// Initializes the . /// /// [in,out] Options for controlling the operation. public void Initialize(ref GameGraphicsParameters parameters) @@ -498,7 +498,7 @@ private void Dispose(bool disposing) _depthStencilStates.Dispose(); _rasterizerStates.Dispose(); _samplerStates.Dispose(); - + _textures.Dispose(); Utilities.Dispose(ref _depthStencilView); diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.cs b/src/Exomia.Framework/Graphics/SpriteBatch.cs index 298bc672..65b4b8ac 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.cs @@ -74,16 +74,16 @@ private static readonly Vector2[] _defaultRasterizerScissorEnabledState, _rasterizerState; - private SamplerState? _defaultSamplerState, _samplerState; - private bool _isBeginCalled, _isScissorEnabled; - private Rectangle _scissorRectangle; - private SpriteSortMode _spriteSortMode; - private int[] _sortIndices; - private SpriteInfo[] _spriteQueue, _sortedSprites; - private int _spriteQueueCount; - private TextureInfo[] _spriteTextures; - private Matrix _projectionMatrix, _viewMatrix, _transformMatrix; - private Texture _whiteTexture; + private SamplerState? _defaultSamplerState, _samplerState; + private bool _isBeginCalled, _isScissorEnabled; + private Rectangle _scissorRectangle; + private SpriteSortMode _spriteSortMode; + private int[] _sortIndices; + private SpriteInfo[] _spriteQueue, _sortedSprites; + private int _spriteQueueCount; + private TextureInfo[] _spriteTextures; + private Matrix _projectionMatrix, _viewMatrix, _transformMatrix; + private readonly Texture _whiteTexture; private SpinLock _spinLock = new SpinLock(Debugger.IsAttached); diff --git a/src/Exomia.Framework/Graphics/Textures.cs b/src/Exomia.Framework/Graphics/Textures.cs index 5967a0f2..57cc9727 100644 --- a/src/Exomia.Framework/Graphics/Textures.cs +++ b/src/Exomia.Framework/Graphics/Textures.cs @@ -35,7 +35,7 @@ public Texture WhiteTexture } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The graphics device. /// Thrown when a value was unexpectedly null. From 885f45b10ba4e1abbe29e783a37f7be71800dd4c Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Sun, 8 Nov 2020 02:25:13 +0100 Subject: [PATCH 08/44] renaming --- src/Exomia.Framework/Graphics/SpriteBatch.cs | 2 +- src/Exomia.Framework/Graphics/Textures.cs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.cs b/src/Exomia.Framework/Graphics/SpriteBatch.cs index 65b4b8ac..705d272c 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.cs @@ -141,7 +141,7 @@ public SpriteBatch(IGraphicsDevice iDevice, SpriteSortAlgorithm sortAlgorithm = _defaultRasterizerState = iDevice.RasterizerStates.CullBackDepthClipOff; _defaultRasterizerScissorEnabledState = iDevice.RasterizerStates.CullBackDepthClipOffScissorEnabled; - _whiteTexture = iDevice.Textures.WhiteTexture; + _whiteTexture = iDevice.Textures.White; _indexBuffer = Buffer.Create( _device, BindFlags.IndexBuffer, s_indices, 0, ResourceUsage.Immutable); diff --git a/src/Exomia.Framework/Graphics/Textures.cs b/src/Exomia.Framework/Graphics/Textures.cs index 57cc9727..a195731d 100644 --- a/src/Exomia.Framework/Graphics/Textures.cs +++ b/src/Exomia.Framework/Graphics/Textures.cs @@ -21,7 +21,7 @@ public class Textures : IDisposable private const string WHITE_TEXTURE_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII="; - private readonly Texture _whiteTexture; + private readonly Texture _white; /// /// Built-in white texture object with size of 1x1 px. @@ -29,9 +29,9 @@ public class Textures : IDisposable /// /// The white texture. /// - public Texture WhiteTexture + public Texture White { - get { return _whiteTexture!; } + get { return _white!; } } /// @@ -43,8 +43,8 @@ internal Textures(IGraphicsDevice graphicsDevice) { using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(WHITE_TEXTURE_BASE64))) { - _whiteTexture = Texture.Load(graphicsDevice.Device, ms) ?? - throw new NullReferenceException($"{nameof(WhiteTexture)}"); + _white = Texture.Load(graphicsDevice.Device, ms) ?? + throw new NullReferenceException($"{nameof(White)}"); } } @@ -58,7 +58,7 @@ private void Dispose(bool disposing) { if (disposing) { - _whiteTexture.Dispose(); + _white.Dispose(); } _disposed = true; From ab7555a408947626fb5c6287e33d93f59584e870 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Sun, 8 Nov 2020 17:12:36 +0100 Subject: [PATCH 09/44] wip --- .../Content/Loader/ObjFileLoader.cs | 2 +- .../Graphics/Shader/Shader.cs | 106 ++++++++++++++++-- .../Graphics/Shader/ShaderFileLoader.cs | 18 ++- src/Exomia.Framework/Graphics/SpriteBatch.cs | 13 +-- .../shaders/position_normal_texture.ehlsl | 28 ++--- 5 files changed, 127 insertions(+), 40 deletions(-) diff --git a/src/Exomia.Framework/Content/Loader/ObjFileLoader.cs b/src/Exomia.Framework/Content/Loader/ObjFileLoader.cs index bc698a4e..7ec110b2 100644 --- a/src/Exomia.Framework/Content/Loader/ObjFileLoader.cs +++ b/src/Exomia.Framework/Content/Loader/ObjFileLoader.cs @@ -49,7 +49,7 @@ public Obj Load(Stream stream) { while (!sr.EndOfStream) { - string currentLine = sr.ReadLine(); + string? currentLine = sr.ReadLine(); if (string.IsNullOrWhiteSpace(currentLine) || currentLine[0] == '#') { diff --git a/src/Exomia.Framework/Graphics/Shader/Shader.cs b/src/Exomia.Framework/Graphics/Shader/Shader.cs index 09a7c58d..5475b944 100644 --- a/src/Exomia.Framework/Graphics/Shader/Shader.cs +++ b/src/Exomia.Framework/Graphics/Shader/Shader.cs @@ -13,9 +13,11 @@ using System.Linq; using System.Runtime.CompilerServices; using Exomia.Framework.Content; +using Exomia.Framework.Mathematics; using SharpDX; using SharpDX.D3DCompiler; using SharpDX.Direct3D11; +using SharpDX.DXGI; namespace Exomia.Framework.Graphics.Shader { @@ -81,10 +83,12 @@ public Technique this[string name] /// /// The techniques. internal Shader( - IEnumerable<(string technique, IEnumerable<(Type, ComObject, ShaderSignature)> passes)> techniques) + IEnumerable<(string technique, IEnumerable<(Type, ComObject, ShaderSignature, ShaderReflection)> passes)> + techniques) { _techniques = new Dictionary(StringComparer.InvariantCultureIgnoreCase); - foreach ((string technique, IEnumerable<(Type, ComObject, ShaderSignature)> passes) in techniques) + foreach ((string technique, + IEnumerable<(Type, ComObject, ShaderSignature, ShaderReflection)> passes) in techniques) { _techniques.Add(technique, new Technique(passes)); } @@ -134,18 +138,20 @@ public Technique GetTechnique(string name) /// public sealed class Technique { - private readonly Dictionary _passes; + private readonly + Dictionary _passes; /// /// Initializes a new instance of the class. /// - /// The passes. - internal Technique(IEnumerable<(Type type, ComObject comObject, ShaderSignature signature)> passes) + /// The passes. + internal Technique(IEnumerable<(Type, ComObject, ShaderSignature, ShaderReflection)> passes) { - _passes = new Dictionary(); - foreach ((Type type, ComObject comObject, ShaderSignature signature) in passes) + _passes = new Dictionary(); + foreach ((Type type, ComObject comObject, ShaderSignature signature, + ShaderReflection reflection) in passes) { - _passes.Add(type, (comObject, signature)); + _passes.Add(type, (comObject, signature, reflection)); } } @@ -311,6 +317,83 @@ public ShaderSignature GetShaderSignature(Type type) return _passes[type].signature; } + /// s + /// Gets the . + /// + /// The type. + /// + /// The . + /// + public ShaderReflection GetShaderReflection(Type type) + { + return _passes[type].reflection; + } + + /// + /// Creates input elements from the specified . + /// + /// The type. + /// + /// A new array of input element. + /// + /// Thrown when one or more arguments are outside the required range. + public InputElement[] CreateInputElements(Type type) + { + ShaderReflection shaderReflection = GetShaderReflection(type); + + InputElement[] elements = new InputElement[shaderReflection.Description.InputParameters]; + for (int i = 0; i < shaderReflection.Description.InputParameters; i++) + { + ShaderParameterDescription description = shaderReflection.GetInputParameterDescription(i); + + Format format = Math2.CountOnes((int)description.UsageMask) switch + { + // ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault + 1 => description.ComponentType switch + { + RegisterComponentType.UInt32 => Format.R32_UInt, + RegisterComponentType.SInt32 => Format.R32_SInt, + RegisterComponentType.Float32 => Format.R32_Float, + _ => throw new ArgumentOutOfRangeException(nameof(description.ComponentType)) + }, + + // ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault + 2 => description.ComponentType switch + { + RegisterComponentType.UInt32 => Format.R32G32_UInt, + RegisterComponentType.SInt32 => Format.R32G32_SInt, + RegisterComponentType.Float32 => Format.R32G32_Float, + _ => throw new ArgumentOutOfRangeException(nameof(description.ComponentType)) + }, + + // ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault + 3 => description.ComponentType switch + { + RegisterComponentType.UInt32 => Format.R32G32B32_UInt, + RegisterComponentType.SInt32 => Format.R32G32B32_SInt, + RegisterComponentType.Float32 => Format.R32G32B32_Float, + _ => throw new ArgumentOutOfRangeException(nameof(description.ComponentType)) + }, + + // ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault + 4 => description.ComponentType switch + { + RegisterComponentType.UInt32 => Format.R32G32B32A32_UInt, + RegisterComponentType.SInt32 => Format.R32G32B32A32_SInt, + RegisterComponentType.Float32 => Format.R32G32B32A32_Float, + _ => throw new ArgumentOutOfRangeException(nameof(description.ComponentType)) + }, + _ => throw new ArgumentOutOfRangeException(nameof(description.UsageMask)) + }; + + elements[i] = new InputElement( + description.SemanticName, description.SemanticIndex, format, + InputElement.AppendAligned, description.Register, InputClassification.PerVertexData, 0); + } + + return elements; + } + #region IDisposable Support private bool _disposed; @@ -319,10 +402,13 @@ private void Dispose(bool disposing) { if (!_disposed) { - foreach (KeyValuePair keyValuePair in _passes) + // ReSharper disable once UseDeconstruction + foreach (KeyValuePair keyValuePair in _passes) { - keyValuePair.Value.shader.Dispose(); + keyValuePair.Value.reflection.Dispose(); keyValuePair.Value.signature.Dispose(); + keyValuePair.Value.shader.Dispose(); } if (disposing) { diff --git a/src/Exomia.Framework/Graphics/Shader/ShaderFileLoader.cs b/src/Exomia.Framework/Graphics/Shader/ShaderFileLoader.cs index f7af2147..b89ce551 100644 --- a/src/Exomia.Framework/Graphics/Shader/ShaderFileLoader.cs +++ b/src/Exomia.Framework/Graphics/Shader/ShaderFileLoader.cs @@ -103,22 +103,28 @@ static class ShaderFileLoader { "vs" => (Shader.Type.VertexShader, (ComObject)new VertexShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr)), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), "ps" => (Shader.Type.PixelShader, (ComObject)new PixelShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr)), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), "ds" => (Shader.Type.DomainShader, (ComObject)new DomainShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr)), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), "gs" => (Shader.Type.GeometryShader, (ComObject)new GeometryShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr)), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), "hs" => (Shader.Type.HullShader, (ComObject)new HullShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr)), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), "cs" => (Shader.Type.ComputeShader, (ComObject)new ComputeShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr)), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), _ => throw new InvalidDataException( $"pass shader type '{s.Type}' doesn't exists or is unsupported.") }; diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.cs b/src/Exomia.Framework/Graphics/SpriteBatch.cs index 705d272c..27faeb41 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.cs @@ -158,15 +158,10 @@ public SpriteBatch(IGraphicsDevice iDevice, SpriteSortAlgorithm sortAlgorithm = _vertexShader = technique; _pixelShader = technique; - _vertexInputLayout = new InputLayout( - _device, technique.GetShaderSignature(Shader.Shader.Type.VertexShader), - new[] - { - new InputElement( - "SV_POSITION", 0, Format.R32G32B32A32_Float, InputElement.AppendAligned, 0), - new InputElement("COLOR", 0, Format.R32G32B32A32_Float, InputElement.AppendAligned, 0), - new InputElement("TEXCOORD", 0, Format.R32G32_Float, InputElement.AppendAligned, 0) - }); + _vertexInputLayout = new InputLayout( + _device, + technique.GetShaderSignature(Shader.Shader.Type.VertexShader), + technique.CreateInputElements(Shader.Shader.Type.VertexShader)); } _vertexBuffer = new Buffer( diff --git a/src/Exomia.Framework/Resources/shaders/position_normal_texture.ehlsl b/src/Exomia.Framework/Resources/shaders/position_normal_texture.ehlsl index dfebbd8c..f50e7f36 100644 --- a/src/Exomia.Framework/Resources/shaders/position_normal_texture.ehlsl +++ b/src/Exomia.Framework/Resources/shaders/position_normal_texture.ehlsl @@ -40,15 +40,15 @@ struct Material //-------------------------------------------------------------------------------------- cbuffer PerFrame : register(b0) { - float4x4 g_WorldMatrix; float4x4 g_ViewMatrix; float4x4 g_ProjectionMatrix; - float4x4 g_WorldViewProjectionMatrix; + float4x4 g_ViewProjectionMatrix; float3 g_EyeVector; }; cbuffer PerObject : register(b1) { + float4x4 g_TransformMatrix; Material g_Material; }; @@ -57,9 +57,9 @@ cbuffer PerObject : register(b1) //-------------------------------------------------------------------------------------- struct VS_INPUT { - float4 p : SV_POSITION0; - float3 n : NORMAL0; - float2 t : TEXCOORD0; + float4 p : SV_POSITION; + float3 n : NORMAL; + float2 t : TEXCOORD; }; //-------------------------------------------------------------------------------------- @@ -131,13 +131,13 @@ PS_INPUT_PV VS_VERTEX_LIGHTING_PHONG(VS_INPUT input) PS_INPUT_PV output; //transform position to clip space - output.p = mul(input.p, g_WorldViewProjectionMatrix); + output.p = mul(input.p, mul(g_TransformMatrix, g_ViewProjectionMatrix)); //set texture coords output.t = input.t; //calculate lighting vectors - float3 n = normalize(mul(input.n, (float3x3)g_WorldMatrix)); + float3 n = normalize(mul(input.n, (float3x3)g_TransformMatrix)); float3 v = normalize(g_EyeVector - (float3)input.p); //DONOT USE -light.dir since the reflection returns a ray from the surface float3 r = reflect(light.direction, n); @@ -156,13 +156,13 @@ PS_INPUT_PV VS_VERTEX_LIGHTING_BLINNPHONG(VS_INPUT input) PS_INPUT_PV output; //transform position to clip space - output.p = mul(input.p, g_WorldViewProjectionMatrix); + output.p = mul(input.p, mul(g_TransformMatrix, g_ViewProjectionMatrix)); //set texture coords output.t = input.t; //calculate lighting - float3 n = normalize(mul(input.n, (float3x3)g_WorldMatrix)); + float3 n = normalize(mul(input.n, (float3x3)g_TransformMatrix)); float3 v = normalize(g_EyeVector - (float3)input.p); float3 h = normalize(-light.direction + v); @@ -189,14 +189,14 @@ PS_INPUT_PP_PHONG VS_PIXEL_LIGHTING_PHONG(VS_INPUT input) PS_INPUT_PP_PHONG output; //transform position to clip space - keep worldspace position - output.wp = mul(input.p, g_WorldMatrix); - output.p = mul(input.p, g_WorldViewProjectionMatrix); + output.wp = mul(input.p, g_TransformMatrix); + output.p = mul(input.p, g_ViewProjectionMatrix); //set texture coords output.t = input.t; //set required lighting vectors for interpolation - output.n = normalize(mul(input.n, (float3x3)g_WorldMatrix)); + output.n = normalize(mul(input.n, (float3x3) g_TransformMatrix)); return output; } @@ -225,14 +225,14 @@ PS_INPUT_PP_BLINNPHONG VS_PIXEL_LIGHTING_BLINNPHONG(VS_INPUT input) PS_INPUT_PP_BLINNPHONG output; //set position into clip space - output.p = mul(input.p, g_WorldViewProjectionMatrix); + output.p = mul(input.p, g_ViewProjectionMatrix); //set texture coords output.t = input.t; //set required lighting vectors for interpolation float3 v = normalize(g_EyeVector - (float3)input.p); - output.n = normalize(mul(input.n, (float3x3)g_WorldMatrix)); + output.n = normalize(mul(input.n, (float3x3)g_TransformMatrix)); output.h = normalize(-light.direction + v); return output; From 412e1bc04315af4c88ae21d321da710b3bdf06fb Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Sun, 8 Nov 2020 23:39:31 +0100 Subject: [PATCH 10/44] - qol --- .../Graphics/Buffers/ConstantBuffer.cs | 102 +++++++++ .../Graphics/Buffers/IndexBuffer.cs | 129 +++++++++++ .../Graphics/Buffers/VertexBuffer.cs | 209 ++++++++++++++++++ .../Graphics/Shader/Shader.cs | 15 +- src/Exomia.Framework/Graphics/SpriteBatch.cs | 55 ++--- src/Exomia.Framework/Graphics/Textures.cs | 2 +- .../shaders/position_normal_texture.ehlsl | 22 +- 7 files changed, 484 insertions(+), 50 deletions(-) create mode 100644 src/Exomia.Framework/Graphics/Buffers/ConstantBuffer.cs create mode 100644 src/Exomia.Framework/Graphics/Buffers/IndexBuffer.cs create mode 100644 src/Exomia.Framework/Graphics/Buffers/VertexBuffer.cs diff --git a/src/Exomia.Framework/Graphics/Buffers/ConstantBuffer.cs b/src/Exomia.Framework/Graphics/Buffers/ConstantBuffer.cs new file mode 100644 index 00000000..687a3d56 --- /dev/null +++ b/src/Exomia.Framework/Graphics/Buffers/ConstantBuffer.cs @@ -0,0 +1,102 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using System.Runtime.CompilerServices; +using SharpDX.Direct3D11; +using Buffer = SharpDX.Direct3D11.Buffer; + +namespace Exomia.Framework.Graphics.Buffers +{ + /// + /// A constant buffer. This class cannot be inherited. + /// + public sealed class ConstantBuffer : IDisposable + { + private readonly Buffer _buffer; + + private ConstantBuffer(Buffer buffer) + { + _buffer = buffer ?? throw new ArgumentNullException(nameof(buffer)); + } + + /// + /// Implicit cast that converts the given to a . + /// + /// Buffer for constant data. + /// + /// The result of the operation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Buffer(ConstantBuffer buffer) + { + return buffer._buffer; + } + + /// + /// Creates a new . + /// + /// Generic type parameter. + /// The graphics device. + /// (Optional) The resource usage. + /// (Optional) The CPU access flags. + /// + /// A . + /// + public static unsafe ConstantBuffer Create(IGraphicsDevice graphicsDevice, + ResourceUsage resourceUsage = ResourceUsage.Default, + CpuAccessFlags cpuAccessFlags = CpuAccessFlags.None) + where T : unmanaged + { + return new ConstantBuffer( + new Buffer( + graphicsDevice.Device, + sizeof(T), + resourceUsage, + BindFlags.ConstantBuffer, + cpuAccessFlags, + ResourceOptionFlags.None, + 0)); + } + + #region IDisposable Support + + private bool _disposed; + + private void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + _buffer.Dispose(); + } + _disposed = true; + } + } + + /// + ~ConstantBuffer() + { + Dispose(false); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged/managed resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Buffers/IndexBuffer.cs b/src/Exomia.Framework/Graphics/Buffers/IndexBuffer.cs new file mode 100644 index 00000000..e8b77a76 --- /dev/null +++ b/src/Exomia.Framework/Graphics/Buffers/IndexBuffer.cs @@ -0,0 +1,129 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using System.Runtime.CompilerServices; +using SharpDX; +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using Buffer = SharpDX.Direct3D11.Buffer; + +namespace Exomia.Framework.Graphics.Buffers +{ + /// + /// A index buffer. This class cannot be inherited. + /// + public sealed class IndexBuffer : IDisposable + { + /// + /// Describes the format of the index buffer. + /// + public readonly Format Format; + + private readonly Buffer _buffer; + + private IndexBuffer(Buffer buffer, Format format) + { + _buffer = buffer ?? throw new ArgumentNullException(nameof(buffer)); + Format = format; + } + + /// + /// Implicit cast that converts the given to a . + /// + /// Buffer for index data. + /// + /// The result of the operation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Buffer(IndexBuffer buffer) + { + return buffer._buffer; + } + + /// + /// Creates a new . + /// + /// Generic type parameter. + /// The graphics device. + /// The data. + /// (Optional) The resource usage. + /// (Optional) The CPU access flags. + /// + /// A . + /// + public static unsafe IndexBuffer Create(IGraphicsDevice graphicsDevice, + in T[] data, + ResourceUsage resourceUsage = ResourceUsage.Immutable, + CpuAccessFlags cpuAccessFlags = CpuAccessFlags.None) + where T : unmanaged + + { + using (DataStream dataStream = new DataStream(sizeof(T) * data.Length, true, true)) + { + dataStream.WriteRange(data, 0, data.Length); + dataStream.Position = 0; + + Buffer buffer = new Buffer( + graphicsDevice.Device, + dataStream, + sizeof(T) * data.Length, + resourceUsage, + BindFlags.IndexBuffer, + cpuAccessFlags, + ResourceOptionFlags.None, + 0); + + return new IndexBuffer( + buffer, Type.GetTypeCode(typeof(T)) switch + { + TypeCode.Int16 => Format.R16_SInt, + TypeCode.Int32 => Format.R32_SInt, + TypeCode.UInt16 => Format.R16_UInt, + TypeCode.UInt32 => Format.R32_UInt, + _ => Format.Unknown + }); + } + } + + #region IDisposable Support + + private bool _disposed; + + private void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + _buffer.Dispose(); + } + _disposed = true; + } + } + + /// + ~IndexBuffer() + { + Dispose(false); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged/managed resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Buffers/VertexBuffer.cs b/src/Exomia.Framework/Graphics/Buffers/VertexBuffer.cs new file mode 100644 index 00000000..a778b629 --- /dev/null +++ b/src/Exomia.Framework/Graphics/Buffers/VertexBuffer.cs @@ -0,0 +1,209 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using System.Runtime.CompilerServices; +using SharpDX; +using SharpDX.Direct3D11; +using Buffer = SharpDX.Direct3D11.Buffer; + +namespace Exomia.Framework.Graphics.Buffers +{ + /// + /// A vertex buffer. This class cannot be inherited. + /// + public sealed class VertexBuffer : IDisposable + { + private readonly Buffer _buffer; + private readonly VertexBufferBinding _vertexBufferBinding; + + private VertexBuffer(Buffer buffer, int stride) + { + _buffer = buffer ?? throw new ArgumentNullException(nameof(buffer)); + _vertexBufferBinding = new VertexBufferBinding(_buffer, stride, 0); + } + + /// + /// Implicit cast that converts the given to a . + /// + /// Buffer for vertex data. + /// + /// The result of the operation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Buffer(VertexBuffer buffer) + { + return buffer._buffer; + } + + /// + /// Implicit cast that converts the given to a . + /// + /// Buffer for vertex data. + /// + /// The result of the operation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator VertexBufferBinding(VertexBuffer buffer) + { + return buffer._vertexBufferBinding; + } + + /// + /// Creates a new . + /// + /// Generic type parameter. + /// The graphics device. + /// The count of the vertices to store in this vertex buffer. + /// (Optional) The resource usage. + /// (Optional) The CPU access flags. + /// + /// A . + /// + public static unsafe VertexBuffer Create(IGraphicsDevice graphicsDevice, + int vertices, + ResourceUsage resourceUsage = ResourceUsage.Dynamic, + CpuAccessFlags cpuAccessFlags = CpuAccessFlags.Write) + where T : unmanaged + { + return new VertexBuffer( + new Buffer( + graphicsDevice.Device, + sizeof(T) * vertices, + resourceUsage, + BindFlags.VertexBuffer, + cpuAccessFlags, + ResourceOptionFlags.None, + 0), + sizeof(T)); + } + + /// + /// Map the data. + /// + /// Generic type parameter. + /// The context4. + /// The data. + /// (Optional) The map mode. + /// (Optional) The map flags. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Map(DeviceContext4 context4, + T[] data, + MapMode mapMode = MapMode.WriteDiscard, + MapFlags mapFlags = MapFlags.None) + where T : unmanaged + { + Map(context4, 0, data, 0, data.Length, mapMode, mapFlags); + } + + /// + /// Map the data. + /// + /// Generic type parameter. + /// The context4. + /// The offset. + /// The data. + /// (Optional) The map mode. + /// (Optional) The map flags. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Map(DeviceContext4 context4, + int offset, + T[] data, + MapMode mapMode = MapMode.WriteDiscard, + MapFlags mapFlags = MapFlags.None) + where T : unmanaged + { + Map(context4, offset, data, 0, data.Length, mapMode, mapFlags); + } + + /// + /// Map the data. + /// + /// Generic type parameter. + /// The context4. + /// The data. + /// The data offset. + /// The data length. + /// (Optional) The map mode. + /// (Optional) The map flags. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Map(DeviceContext4 context4, + T[] data, + int dataOffset, + int dataLength, + MapMode mapMode = MapMode.WriteDiscard, + MapFlags mapFlags = MapFlags.None) + where T : unmanaged + { + Map(context4, 0, data, dataOffset, dataLength, mapMode, mapFlags); + } + + /// + /// Map the data. + /// + /// Generic type parameter. + /// The context4. + /// The offset. + /// The data. + /// The data offset. + /// The data length. + /// (Optional) The map mode. + /// (Optional) The map flags. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public unsafe void Map(DeviceContext4 context4, + int offset, + T[] data, + int dataOffset, + int dataLength, + MapMode mapMode = MapMode.WriteDiscard, + MapFlags mapFlags = MapFlags.None) + where T : unmanaged + { + DataBox box = context4.MapSubresource(_buffer, 0, mapMode, mapFlags); + T* vpctPtr = (T*)box.DataPointer; + for (int i = 0; i < dataLength; i++) + { + *(vpctPtr + offset + i) = data[i + dataOffset]; + } + context4.UnmapSubresource(_buffer, 0); + } + + #region IDisposable Support + + private bool _disposed; + + private void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + _buffer.Dispose(); + } + _disposed = true; + } + } + + /// + ~VertexBuffer() + { + Dispose(false); + } + + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Shader/Shader.cs b/src/Exomia.Framework/Graphics/Shader/Shader.cs index 5475b944..deaa202e 100644 --- a/src/Exomia.Framework/Graphics/Shader/Shader.cs +++ b/src/Exomia.Framework/Graphics/Shader/Shader.cs @@ -317,7 +317,8 @@ public ShaderSignature GetShaderSignature(Type type) return _passes[type].signature; } - /// s + /// + /// s /// Gets the . /// /// The type. @@ -330,7 +331,7 @@ public ShaderReflection GetShaderReflection(Type type) } /// - /// Creates input elements from the specified . + /// Creates input elements from the specified . /// /// The type. /// @@ -340,7 +341,7 @@ public ShaderReflection GetShaderReflection(Type type) public InputElement[] CreateInputElements(Type type) { ShaderReflection shaderReflection = GetShaderReflection(type); - + InputElement[] elements = new InputElement[shaderReflection.Description.InputParameters]; for (int i = 0; i < shaderReflection.Description.InputParameters; i++) { @@ -385,12 +386,12 @@ public InputElement[] CreateInputElements(Type type) }, _ => throw new ArgumentOutOfRangeException(nameof(description.UsageMask)) }; - + elements[i] = new InputElement( - description.SemanticName, description.SemanticIndex, format, - InputElement.AppendAligned, description.Register, InputClassification.PerVertexData, 0); + description.SemanticName, description.SemanticIndex, format, + InputElement.AppendAligned, 0, InputClassification.PerVertexData, 0); } - + return elements; } diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.cs b/src/Exomia.Framework/Graphics/SpriteBatch.cs index 27faeb41..73b1a397 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.cs @@ -18,6 +18,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using Exomia.Framework.Graphics.Buffers; using Exomia.Framework.Graphics.Shader; using Exomia.Framework.Graphics.SpriteSort; using Exomia.Framework.Resources; @@ -58,14 +59,16 @@ private static readonly Vector2[] private readonly Dictionary _textureInfos = new Dictionary(INITIAL_QUEUE_SIZE); - private readonly VertexBufferBinding _vertexBufferBinding; - private readonly InputLayout _vertexInputLayout; + private readonly InputLayout _vertexInputLayout; - private readonly Buffer _vertexBuffer, _indexBuffer, _perFrameBuffer; + private readonly IndexBuffer _indexBuffer; + private readonly VertexBuffer _vertexBuffer; + private readonly ConstantBuffer _perFrameBuffer; private readonly Shader.Shader _shader; private readonly PixelShader _pixelShader; private readonly VertexShader _vertexShader; + private readonly Texture _whiteTexture; private BlendState? _defaultBlendState, _blendState; private DepthStencilState? _defaultDepthStencilState, _depthStencilState; @@ -74,16 +77,15 @@ private static readonly Vector2[] _defaultRasterizerScissorEnabledState, _rasterizerState; - private SamplerState? _defaultSamplerState, _samplerState; - private bool _isBeginCalled, _isScissorEnabled; - private Rectangle _scissorRectangle; - private SpriteSortMode _spriteSortMode; - private int[] _sortIndices; - private SpriteInfo[] _spriteQueue, _sortedSprites; - private int _spriteQueueCount; - private TextureInfo[] _spriteTextures; - private Matrix _projectionMatrix, _viewMatrix, _transformMatrix; - private readonly Texture _whiteTexture; + private SamplerState? _defaultSamplerState, _samplerState; + private bool _isBeginCalled, _isScissorEnabled; + private Rectangle _scissorRectangle; + private SpriteSortMode _spriteSortMode; + private int[] _sortIndices; + private SpriteInfo[] _spriteQueue, _sortedSprites; + private int _spriteQueueCount; + private TextureInfo[] _spriteTextures; + private Matrix _projectionMatrix, _viewMatrix, _transformMatrix; private SpinLock _spinLock = new SpinLock(Debugger.IsAttached); @@ -143,8 +145,7 @@ public SpriteBatch(IGraphicsDevice iDevice, SpriteSortAlgorithm sortAlgorithm = _whiteTexture = iDevice.Textures.White; - _indexBuffer = Buffer.Create( - _device, BindFlags.IndexBuffer, s_indices, 0, ResourceUsage.Immutable); + _indexBuffer = IndexBuffer.Create(iDevice, s_indices); Assembly assembly = Assembly.GetExecutingAssembly(); using (Stream stream = @@ -158,19 +159,14 @@ public SpriteBatch(IGraphicsDevice iDevice, SpriteSortAlgorithm sortAlgorithm = _vertexShader = technique; _pixelShader = technique; - _vertexInputLayout = new InputLayout( + _vertexInputLayout = new InputLayout( _device, technique.GetShaderSignature(Shader.Shader.Type.VertexShader), technique.CreateInputElements(Shader.Shader.Type.VertexShader)); } - _vertexBuffer = new Buffer( - _device, VERTEX_STRIDE * MAX_VERTEX_COUNT, ResourceUsage.Dynamic, BindFlags.VertexBuffer, - CpuAccessFlags.Write, ResourceOptionFlags.None, 0); - _vertexBufferBinding = new VertexBufferBinding(_vertexBuffer, VERTEX_STRIDE, 0); - _perFrameBuffer = new Buffer( - _device, sizeof(float) * 4 * 4 * 1, ResourceUsage.Default, BindFlags.ConstantBuffer, - CpuAccessFlags.None, ResourceOptionFlags.None, 0); + _vertexBuffer = VertexBuffer.Create(iDevice, MAX_VERTEX_COUNT); + _perFrameBuffer = ConstantBuffer.Create(iDevice); _sortIndices = new int[MAX_BATCH_SIZE]; _sortedSprites = new SpriteInfo[MAX_BATCH_SIZE]; @@ -547,15 +543,12 @@ private void PrepareForRendering() _context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; _context.InputAssembler.InputLayout = _vertexInputLayout; + Matrix worldViewProjection = Matrix.Transpose(_transformMatrix * _viewMatrix * _projectionMatrix); + _context.UpdateSubresource(ref worldViewProjection, _perFrameBuffer); _context.VertexShader.SetConstantBuffer(0, _perFrameBuffer); - _context.InputAssembler.SetIndexBuffer(_indexBuffer, Format.R16_UInt, 0); - _context.InputAssembler.SetVertexBuffers(0, _vertexBufferBinding); - - Matrix worldViewProjection = _transformMatrix * _viewMatrix * _projectionMatrix; - worldViewProjection.Transpose(); - - _context.UpdateSubresource(ref worldViewProjection, _perFrameBuffer); + _context.InputAssembler.SetIndexBuffer(_indexBuffer, _indexBuffer.Format, 0); + _context.InputAssembler.SetVertexBuffers(0, _vertexBuffer); } internal struct SpriteInfo @@ -1496,8 +1489,8 @@ private void Dispose(bool disposing) Utilities.Dispose(ref _defaultDepthStencilState); _vertexBuffer.Dispose(); - _perFrameBuffer.Dispose(); _indexBuffer.Dispose(); + _perFrameBuffer.Dispose(); _shader.Dispose(); _vertexInputLayout.Dispose(); diff --git a/src/Exomia.Framework/Graphics/Textures.cs b/src/Exomia.Framework/Graphics/Textures.cs index a195731d..0434491c 100644 --- a/src/Exomia.Framework/Graphics/Textures.cs +++ b/src/Exomia.Framework/Graphics/Textures.cs @@ -44,7 +44,7 @@ internal Textures(IGraphicsDevice graphicsDevice) using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(WHITE_TEXTURE_BASE64))) { _white = Texture.Load(graphicsDevice.Device, ms) ?? - throw new NullReferenceException($"{nameof(White)}"); + throw new NullReferenceException($"{nameof(White)}"); } } diff --git a/src/Exomia.Framework/Resources/shaders/position_normal_texture.ehlsl b/src/Exomia.Framework/Resources/shaders/position_normal_texture.ehlsl index f50e7f36..376adad7 100644 --- a/src/Exomia.Framework/Resources/shaders/position_normal_texture.ehlsl +++ b/src/Exomia.Framework/Resources/shaders/position_normal_texture.ehlsl @@ -57,9 +57,9 @@ cbuffer PerObject : register(b1) //-------------------------------------------------------------------------------------- struct VS_INPUT { - float4 p : SV_POSITION; - float3 n : NORMAL; - float2 t : TEXCOORD; + float4 p : SV_POSITION0; + float3 n : NORMAL0; + float2 t : TEXCOORD0; }; //-------------------------------------------------------------------------------------- @@ -74,10 +74,10 @@ struct PS_INPUT_PV struct PS_INPUT_PP_PHONG { - float4 p : SV_POSITION; + float4 p : SV_POSITION; float4 wp : POSITION; - float2 t : TEXCOORD; - float3 n : TEXCOORD1; + float2 t : TEXCOORD; + float3 n : TEXCOORD1; }; struct PS_INPUT_PP_BLINNPHONG @@ -160,10 +160,10 @@ PS_INPUT_PV VS_VERTEX_LIGHTING_BLINNPHONG(VS_INPUT input) //set texture coords output.t = input.t; - + //calculate lighting float3 n = normalize(mul(input.n, (float3x3)g_TransformMatrix)); - float3 v = normalize(g_EyeVector - (float3)input.p); + float3 v = normalize(g_EyeVector - (float3)input.p); float3 h = normalize(-light.direction + v); //calculate per vertex lighting intensity and interpolate it like a color @@ -178,7 +178,7 @@ PS_INPUT_PV VS_VERTEX_LIGHTING_BLINNPHONG(VS_INPUT input) float4 PS_VERTEX_LIGHTING(PS_INPUT_PV input) : SV_Target { //with texturing - return input.i * g_Texture.Sample(g_Sampler, input.t); + return input.i * g_Texture.Sample(g_Sampler, input.t); } //-------------------------------------------------------------------------------------- @@ -190,7 +190,7 @@ PS_INPUT_PP_PHONG VS_PIXEL_LIGHTING_PHONG(VS_INPUT input) //transform position to clip space - keep worldspace position output.wp = mul(input.p, g_TransformMatrix); - output.p = mul(input.p, g_ViewProjectionMatrix); + output.p = mul(input.p, mul(g_TransformMatrix, g_ViewProjectionMatrix)); //set texture coords output.t = input.t; @@ -225,7 +225,7 @@ PS_INPUT_PP_BLINNPHONG VS_PIXEL_LIGHTING_BLINNPHONG(VS_INPUT input) PS_INPUT_PP_BLINNPHONG output; //set position into clip space - output.p = mul(input.p, g_ViewProjectionMatrix); + output.p = mul(input.p, mul(g_TransformMatrix, g_ViewProjectionMatrix)); //set texture coords output.t = input.t; From e2b190873cee401218bad1c785c072f83d95c448 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Mon, 9 Nov 2020 21:25:50 +0100 Subject: [PATCH 11/44] ref --- .../Graphics/Buffers/ConstantBuffer.cs | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/Exomia.Framework/Graphics/Buffers/ConstantBuffer.cs b/src/Exomia.Framework/Graphics/Buffers/ConstantBuffer.cs index 687a3d56..c69366b2 100644 --- a/src/Exomia.Framework/Graphics/Buffers/ConstantBuffer.cs +++ b/src/Exomia.Framework/Graphics/Buffers/ConstantBuffer.cs @@ -10,6 +10,7 @@ using System; using System.Runtime.CompilerServices; +using Exomia.Framework.Mathematics; using SharpDX.Direct3D11; using Buffer = SharpDX.Direct3D11.Buffer; @@ -54,11 +55,38 @@ public static unsafe ConstantBuffer Create(IGraphicsDevice graphicsDevice, ResourceUsage resourceUsage = ResourceUsage.Default, CpuAccessFlags cpuAccessFlags = CpuAccessFlags.None) where T : unmanaged + { + return Create(graphicsDevice, Math2.Ceiling(sizeof(T) / 16.0f) * 16, resourceUsage, cpuAccessFlags); + } + + /// + /// Creates a new with the specified size in bytes. + /// + /// The graphics device. + /// The size in bytes. + /// (Optional) The resource usage. + /// (Optional) The CPU access flags. + /// + /// A . + /// + /// + /// The must be a multiple of 16, + /// if not it will be calculated to the minimum multiple of 16 fitting it in. + /// e.g. + /// - a size in bytes of 11 will be 16. + /// - a size in bytes of 23 will be 32. + /// - a size in bytes of 80 will be 80. + /// > see https://docs.microsoft.com/de-de/windows/win32/api/d3d11/ns-d3d11-d3d11_buffer_desc#remarks + /// + public static ConstantBuffer Create(IGraphicsDevice graphicsDevice, + int sizeInBytes, + ResourceUsage resourceUsage = ResourceUsage.Default, + CpuAccessFlags cpuAccessFlags = CpuAccessFlags.None) { return new ConstantBuffer( new Buffer( graphicsDevice.Device, - sizeof(T), + Math2.Ceiling(sizeInBytes / 16.0f) * 16, resourceUsage, BindFlags.ConstantBuffer, cpuAccessFlags, From 0b6fac44150d146b9ffd51d9daf595b7c790ffb6 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Mon, 9 Nov 2020 21:26:21 +0100 Subject: [PATCH 12/44] ref --- src/Exomia.Framework/Graphics/Buffers/ConstantBuffer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Exomia.Framework/Graphics/Buffers/ConstantBuffer.cs b/src/Exomia.Framework/Graphics/Buffers/ConstantBuffer.cs index c69366b2..620b53db 100644 --- a/src/Exomia.Framework/Graphics/Buffers/ConstantBuffer.cs +++ b/src/Exomia.Framework/Graphics/Buffers/ConstantBuffer.cs @@ -56,7 +56,7 @@ public static unsafe ConstantBuffer Create(IGraphicsDevice graphicsDevice, CpuAccessFlags cpuAccessFlags = CpuAccessFlags.None) where T : unmanaged { - return Create(graphicsDevice, Math2.Ceiling(sizeof(T) / 16.0f) * 16, resourceUsage, cpuAccessFlags); + return Create(graphicsDevice, sizeof(T), resourceUsage, cpuAccessFlags); } /// From cfbe5fd15b153c1d29ae3b0c94448ba74239e39f Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Tue, 10 Nov 2020 10:46:24 +0100 Subject: [PATCH 13/44] ref --- .../Collections/LinkedList.cs | 18 +- .../Types/DictionaryType.cs | 46 ++-- .../ContentSerialization/Types/ListType.cs | 44 ++-- src/Exomia.Framework/Game/GamePlatform.cs | 26 +-- src/Exomia.Framework/Game/GameTime.cs | 22 +- .../Graphics/Buffers/ConstantBuffer.cs | 26 +-- .../Graphics/Buffers/IndexBuffer.cs | 26 +-- .../Graphics/Buffers/VertexBuffer.cs | 110 ++++----- src/Exomia.Framework/Graphics/Model/Mesh.cs | 82 +++---- src/Exomia.Framework/Graphics/Model/Obj.cs | 10 +- .../Graphics/Shader/Shader.cs | 175 ++++++++------- .../Graphics/Shader/ShaderFileLoader.cs | 192 ++++++++-------- src/Exomia.Framework/Graphics/SpriteBatch.cs | 212 +++++++++--------- .../MainForm.cs | 46 ++-- 14 files changed, 523 insertions(+), 512 deletions(-) diff --git a/src/Exomia.Framework/Collections/LinkedList.cs b/src/Exomia.Framework/Collections/LinkedList.cs index 16506264..189807be 100644 --- a/src/Exomia.Framework/Collections/LinkedList.cs +++ b/src/Exomia.Framework/Collections/LinkedList.cs @@ -276,6 +276,15 @@ internal LinkedListNode(in T value) Item = value; } + /// + /// Invalidates this object. + /// + internal void Invalidate() + { + Next = null; + Previous = null; + } + /// /// Implicit cast that converts the given LinkedListNode to a T. /// @@ -287,15 +296,6 @@ public static implicit operator T(LinkedListNode node) { return node.Item; } - - /// - /// Invalidates this object. - /// - internal void Invalidate() - { - Next = null; - Previous = null; - } } /// diff --git a/src/Exomia.Framework/ContentSerialization/Types/DictionaryType.cs b/src/Exomia.Framework/ContentSerialization/Types/DictionaryType.cs index 91cd9a7f..a04c4be7 100644 --- a/src/Exomia.Framework/ContentSerialization/Types/DictionaryType.cs +++ b/src/Exomia.Framework/ContentSerialization/Types/DictionaryType.cs @@ -142,6 +142,29 @@ public void Write(Action writeHandler, Write(writeHandler, tabSpace, key, (dynamic)content, useTypeInfo); } + /// + /// + /// + /// Type of the key. + /// Type of the value. + /// The write handler. + /// The tab space. + /// The key. + /// The content. + /// (Optional) True to use type information. + private void Write(Action writeHandler, + string tabSpace, + string key, + Dictionary content, + bool useTypeInfo = true) + { + writeHandler( + tabSpace, + $"[{key}:{(useTypeInfo ? CreateTypeInfo(content.GetType()) : string.Empty)}({content.Count})]"); + ForeachDictionaryDimension(writeHandler, tabSpace + ContentSerializer.TABSPACE, content); + writeHandler(tabSpace, $"[/{(useTypeInfo ? key : string.Empty)}]"); + } + #region WriteHelper /// @@ -179,29 +202,6 @@ private static void ForeachDictionaryDimension(Action - /// - /// - /// Type of the key. - /// Type of the value. - /// The write handler. - /// The tab space. - /// The key. - /// The content. - /// (Optional) True to use type information. - private void Write(Action writeHandler, - string tabSpace, - string key, - Dictionary content, - bool useTypeInfo = true) - { - writeHandler( - tabSpace, - $"[{key}:{(useTypeInfo ? CreateTypeInfo(content.GetType()) : string.Empty)}({content.Count})]"); - ForeachDictionaryDimension(writeHandler, tabSpace + ContentSerializer.TABSPACE, content); - writeHandler(tabSpace, $"[/{(useTypeInfo ? key : string.Empty)}]"); - } - #region ReaderHelper /// diff --git a/src/Exomia.Framework/ContentSerialization/Types/ListType.cs b/src/Exomia.Framework/ContentSerialization/Types/ListType.cs index 7d5ecc13..5e2ba99f 100644 --- a/src/Exomia.Framework/ContentSerialization/Types/ListType.cs +++ b/src/Exomia.Framework/ContentSerialization/Types/ListType.cs @@ -125,6 +125,28 @@ public void Write(Action writeHandler, Write(writeHandler, tabSpace, key, (dynamic)content, useTypeInfo); } + /// + /// Writes. + /// + /// Generic type parameter. + /// The write handler. + /// The tab space. + /// The key. + /// The content. + /// (Optional) True to use type information. + private void Write(Action writeHandler, + string tabSpace, + string key, + List content, + bool useTypeInfo = true) + { + writeHandler( + tabSpace, + $"[{key}:{(useTypeInfo ? CreateTypeInfo(content.GetType()) : string.Empty)}({content.Count})]"); + ForeachListDimension(writeHandler, tabSpace + ContentSerializer.TABSPACE, content); + writeHandler(tabSpace, $"[/{(useTypeInfo ? key : string.Empty)}]"); + } + #region WriteHelper /// @@ -155,28 +177,6 @@ private static void ForeachListDimension(Action writeHandler, #endregion - /// - /// Writes. - /// - /// Generic type parameter. - /// The write handler. - /// The tab space. - /// The key. - /// The content. - /// (Optional) True to use type information. - private void Write(Action writeHandler, - string tabSpace, - string key, - List content, - bool useTypeInfo = true) - { - writeHandler( - tabSpace, - $"[{key}:{(useTypeInfo ? CreateTypeInfo(content.GetType()) : string.Empty)}({content.Count})]"); - ForeachListDimension(writeHandler, tabSpace + ContentSerializer.TABSPACE, content); - writeHandler(tabSpace, $"[/{(useTypeInfo ? key : string.Empty)}]"); - } - #region ReaderHelper /// diff --git a/src/Exomia.Framework/Game/GamePlatform.cs b/src/Exomia.Framework/Game/GamePlatform.cs index 6204f4fd..f2331233 100644 --- a/src/Exomia.Framework/Game/GamePlatform.cs +++ b/src/Exomia.Framework/Game/GamePlatform.cs @@ -29,19 +29,6 @@ protected GamePlatform(Game game, string title) _mainWindow.FormClosed += game.Shutdown; } - /// - /// Creates a new . - /// - /// The game. - /// The title. - /// - /// A . - /// - public static GamePlatform Create(Game game, string title) - { - return new GamePlatformWindows(game, title); - } - /// /// Initializes the . /// @@ -61,6 +48,19 @@ public void ShowMainWindow() private protected abstract IGameWindow CreateGameWindow(Game game, string title); + /// + /// Creates a new . + /// + /// The game. + /// The title. + /// + /// A . + /// + public static GamePlatform Create(Game game, string title) + { + return new GamePlatformWindows(game, title); + } + #region IDisposable Support private bool _disposed; diff --git a/src/Exomia.Framework/Game/GameTime.cs b/src/Exomia.Framework/Game/GameTime.cs index 4f42fc82..fa9f7655 100644 --- a/src/Exomia.Framework/Game/GameTime.cs +++ b/src/Exomia.Framework/Game/GameTime.cs @@ -99,17 +99,6 @@ private GameTime() _prevTime = _baseTime = Stopwatch.GetTimestamp(); } - /// - /// Starts a new. - /// - /// - /// A GameTime. - /// - public static GameTime StartNew() - { - return new GameTime(); - } - /// /// reset the game time. /// @@ -172,5 +161,16 @@ public void Tick() _prevTime = _currTime; } + + /// + /// Starts a new. + /// + /// + /// A GameTime. + /// + public static GameTime StartNew() + { + return new GameTime(); + } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Buffers/ConstantBuffer.cs b/src/Exomia.Framework/Graphics/Buffers/ConstantBuffer.cs index 620b53db..7bf4a03a 100644 --- a/src/Exomia.Framework/Graphics/Buffers/ConstantBuffer.cs +++ b/src/Exomia.Framework/Graphics/Buffers/ConstantBuffer.cs @@ -28,19 +28,6 @@ private ConstantBuffer(Buffer buffer) _buffer = buffer ?? throw new ArgumentNullException(nameof(buffer)); } - /// - /// Implicit cast that converts the given to a . - /// - /// Buffer for constant data. - /// - /// The result of the operation. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator Buffer(ConstantBuffer buffer) - { - return buffer._buffer; - } - /// /// Creates a new . /// @@ -94,6 +81,19 @@ public static ConstantBuffer Create(IGraphicsDevice graphicsDevice, 0)); } + /// + /// Implicit cast that converts the given to a . + /// + /// Buffer for constant data. + /// + /// The result of the operation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Buffer(ConstantBuffer buffer) + { + return buffer._buffer; + } + #region IDisposable Support private bool _disposed; diff --git a/src/Exomia.Framework/Graphics/Buffers/IndexBuffer.cs b/src/Exomia.Framework/Graphics/Buffers/IndexBuffer.cs index e8b77a76..cef484e1 100644 --- a/src/Exomia.Framework/Graphics/Buffers/IndexBuffer.cs +++ b/src/Exomia.Framework/Graphics/Buffers/IndexBuffer.cs @@ -35,19 +35,6 @@ private IndexBuffer(Buffer buffer, Format format) Format = format; } - /// - /// Implicit cast that converts the given to a . - /// - /// Buffer for index data. - /// - /// The result of the operation. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator Buffer(IndexBuffer buffer) - { - return buffer._buffer; - } - /// /// Creates a new . /// @@ -93,6 +80,19 @@ public static unsafe IndexBuffer Create(IGraphicsDevice graphicsDevice, } } + /// + /// Implicit cast that converts the given to a . + /// + /// Buffer for index data. + /// + /// The result of the operation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Buffer(IndexBuffer buffer) + { + return buffer._buffer; + } + #region IDisposable Support private bool _disposed; diff --git a/src/Exomia.Framework/Graphics/Buffers/VertexBuffer.cs b/src/Exomia.Framework/Graphics/Buffers/VertexBuffer.cs index a778b629..60f85a4b 100644 --- a/src/Exomia.Framework/Graphics/Buffers/VertexBuffer.cs +++ b/src/Exomia.Framework/Graphics/Buffers/VertexBuffer.cs @@ -30,61 +30,6 @@ private VertexBuffer(Buffer buffer, int stride) _vertexBufferBinding = new VertexBufferBinding(_buffer, stride, 0); } - /// - /// Implicit cast that converts the given to a . - /// - /// Buffer for vertex data. - /// - /// The result of the operation. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator Buffer(VertexBuffer buffer) - { - return buffer._buffer; - } - - /// - /// Implicit cast that converts the given to a . - /// - /// Buffer for vertex data. - /// - /// The result of the operation. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator VertexBufferBinding(VertexBuffer buffer) - { - return buffer._vertexBufferBinding; - } - - /// - /// Creates a new . - /// - /// Generic type parameter. - /// The graphics device. - /// The count of the vertices to store in this vertex buffer. - /// (Optional) The resource usage. - /// (Optional) The CPU access flags. - /// - /// A . - /// - public static unsafe VertexBuffer Create(IGraphicsDevice graphicsDevice, - int vertices, - ResourceUsage resourceUsage = ResourceUsage.Dynamic, - CpuAccessFlags cpuAccessFlags = CpuAccessFlags.Write) - where T : unmanaged - { - return new VertexBuffer( - new Buffer( - graphicsDevice.Device, - sizeof(T) * vertices, - resourceUsage, - BindFlags.VertexBuffer, - cpuAccessFlags, - ResourceOptionFlags.None, - 0), - sizeof(T)); - } - /// /// Map the data. /// @@ -175,6 +120,61 @@ public unsafe void Map(DeviceContext4 context4, context4.UnmapSubresource(_buffer, 0); } + /// + /// Creates a new . + /// + /// Generic type parameter. + /// The graphics device. + /// The count of the vertices to store in this vertex buffer. + /// (Optional) The resource usage. + /// (Optional) The CPU access flags. + /// + /// A . + /// + public static unsafe VertexBuffer Create(IGraphicsDevice graphicsDevice, + int vertices, + ResourceUsage resourceUsage = ResourceUsage.Dynamic, + CpuAccessFlags cpuAccessFlags = CpuAccessFlags.Write) + where T : unmanaged + { + return new VertexBuffer( + new Buffer( + graphicsDevice.Device, + sizeof(T) * vertices, + resourceUsage, + BindFlags.VertexBuffer, + cpuAccessFlags, + ResourceOptionFlags.None, + 0), + sizeof(T)); + } + + /// + /// Implicit cast that converts the given to a . + /// + /// Buffer for vertex data. + /// + /// The result of the operation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Buffer(VertexBuffer buffer) + { + return buffer._buffer; + } + + /// + /// Implicit cast that converts the given to a . + /// + /// Buffer for vertex data. + /// + /// The result of the operation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator VertexBufferBinding(VertexBuffer buffer) + { + return buffer._vertexBufferBinding; + } + #region IDisposable Support private bool _disposed; diff --git a/src/Exomia.Framework/Graphics/Model/Mesh.cs b/src/Exomia.Framework/Graphics/Model/Mesh.cs index 1d23179c..f00f76c0 100644 --- a/src/Exomia.Framework/Graphics/Model/Mesh.cs +++ b/src/Exomia.Framework/Graphics/Model/Mesh.cs @@ -53,47 +53,6 @@ private Mesh(PositionNormalTexture2D[] vertices, uint[] indices, Texture texture Material = material; } - /// - /// Initializes a new instance from the given instance. - /// - /// The object. - /// The texture. - /// The material. - /// - /// A Mesh. - /// - public static Mesh FromObj(Obj obj, Texture texture, Material material) - { - List vertices = new List(); - List indices = new List(); - - uint index = 0; - foreach (Obj.Face face in obj.Faces) - { - PositionNormalTexture2D FromIndex(int i) - { - Obj.Vertex v = obj.Vertices[face.Vertices[i].V - 1]; - Obj.Normal n = obj.Normals[face.Vertices[i].N - 1]; - Obj.Texture t = obj.Textures[face.Vertices[i].T - 1]; - return new PositionNormalTexture2D(v.X, v.Y, v.Z, v.W, n.X, n.Y, n.Z, t.U, t.V); - } - - vertices.Add(FromIndex(0)); - vertices.Add(FromIndex(1)); - uint indexZero = index++; - for (int i = 2; i < face.Vertices.Length; i++) - { - indices.Add(indexZero); - indices.Add(index++); - indices.Add(index); - vertices.Add(FromIndex(i)); - } - index++; - } - - return new Mesh(vertices.ToArray(), indices.ToArray(), texture, material); - } - /// /// A position normal texture. /// @@ -187,5 +146,46 @@ public PositionNormalTexture2D(float x, V = v; } } + + /// + /// Initializes a new instance from the given instance. + /// + /// The object. + /// The texture. + /// The material. + /// + /// A Mesh. + /// + public static Mesh FromObj(Obj obj, Texture texture, Material material) + { + List vertices = new List(); + List indices = new List(); + + uint index = 0; + foreach (Obj.Face face in obj.Faces) + { + PositionNormalTexture2D FromIndex(int i) + { + Obj.Vertex v = obj.Vertices[face.Vertices[i].V - 1]; + Obj.Normal n = obj.Normals[face.Vertices[i].N - 1]; + Obj.Texture t = obj.Textures[face.Vertices[i].T - 1]; + return new PositionNormalTexture2D(v.X, v.Y, v.Z, v.W, n.X, n.Y, n.Z, t.U, t.V); + } + + vertices.Add(FromIndex(0)); + vertices.Add(FromIndex(1)); + uint indexZero = index++; + for (int i = 2; i < face.Vertices.Length; i++) + { + indices.Add(indexZero); + indices.Add(index++); + indices.Add(index); + vertices.Add(FromIndex(i)); + } + index++; + } + + return new Mesh(vertices.ToArray(), indices.ToArray(), texture, material); + } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Model/Obj.cs b/src/Exomia.Framework/Graphics/Model/Obj.cs index 80f08125..1e4ee821 100644 --- a/src/Exomia.Framework/Graphics/Model/Obj.cs +++ b/src/Exomia.Framework/Graphics/Model/Obj.cs @@ -59,11 +59,6 @@ private Obj(Vertex[] vertices, Normal[] normals, Texture[] textures, Face[] face Faces = faces; } - internal static Obj Create(Vertex[] vertices, Normal[] normals, Texture[] textures, Face[] faces) - { - return new Obj(vertices, normals, textures, faces); - } - /// /// A vertex. /// @@ -275,5 +270,10 @@ public override string ToString() return $"{string.Join(", ", Vertices)} [{Vertices.Length}]"; } } + + internal static Obj Create(Vertex[] vertices, Normal[] normals, Texture[] textures, Face[] faces) + { + return new Obj(vertices, normals, textures, faces); + } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Shader/Shader.cs b/src/Exomia.Framework/Graphics/Shader/Shader.cs index deaa202e..4c8132d5 100644 --- a/src/Exomia.Framework/Graphics/Shader/Shader.cs +++ b/src/Exomia.Framework/Graphics/Shader/Shader.cs @@ -155,84 +155,6 @@ internal Technique(IEnumerable<(Type, ComObject, ShaderSignature, ShaderReflecti } } - /// - /// Implicit converts the given Shader to a . - /// - /// The technique. - /// - /// The . - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator VertexShader(Technique technique) - { - return technique.GetVertexShader(); - } - - /// - /// Implicit converts the given Shader to a . - /// - /// The technique. - /// - /// The . - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator PixelShader(Technique technique) - { - return technique.GetPixelShader(); - } - - /// - /// Implicit converts the given Shader to a . - /// - /// The technique. - /// - /// The . - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator DomainShader(Technique technique) - { - return technique.GetDomainShader(); - } - - /// - /// Implicit converts the given Shader to a . - /// - /// The technique. - /// - /// The . - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator GeometryShader(Technique technique) - { - return technique.GetGeometryShader(); - } - - /// - /// Implicit converts the given Shader to a . - /// - /// The technique. - /// - /// The . - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator HullShader(Technique technique) - { - return technique.GetHullShader(); - } - - /// - /// Implicit converts the given Shader to a . - /// - /// The technique. - /// - /// The . - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator ComputeShader(Technique technique) - { - return technique.GetComputeShader(); - } - /// /// Gets a . /// @@ -331,7 +253,24 @@ public ShaderReflection GetShaderReflection(Type type) } /// - /// Creates input elements from the specified . + /// Creates input layout for the specified . + /// + /// The graphics device. + /// The type. + /// + /// The new input layout. + /// + /// Thrown when one or more required arguments are null. + public InputLayout CreateInputLayout(IGraphicsDevice graphicsDevice, Type type) + { + return new InputLayout( + (graphicsDevice ?? throw new ArgumentNullException(nameof(graphicsDevice))).Device, + GetShaderSignature(type), + CreateInputElements(type)); + } + + /// + /// Creates input elements for the specified . /// /// The type. /// @@ -395,6 +334,84 @@ public InputElement[] CreateInputElements(Type type) return elements; } + /// + /// Implicit converts the given Shader to a . + /// + /// The technique. + /// + /// The . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator VertexShader(Technique technique) + { + return technique.GetVertexShader(); + } + + /// + /// Implicit converts the given Shader to a . + /// + /// The technique. + /// + /// The . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator PixelShader(Technique technique) + { + return technique.GetPixelShader(); + } + + /// + /// Implicit converts the given Shader to a . + /// + /// The technique. + /// + /// The . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator DomainShader(Technique technique) + { + return technique.GetDomainShader(); + } + + /// + /// Implicit converts the given Shader to a . + /// + /// The technique. + /// + /// The . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator GeometryShader(Technique technique) + { + return technique.GetGeometryShader(); + } + + /// + /// Implicit converts the given Shader to a . + /// + /// The technique. + /// + /// The . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator HullShader(Technique technique) + { + return technique.GetHullShader(); + } + + /// + /// Implicit converts the given Shader to a . + /// + /// The technique. + /// + /// The . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator ComputeShader(Technique technique) + { + return technique.GetComputeShader(); + } + #region IDisposable Support private bool _disposed; diff --git a/src/Exomia.Framework/Graphics/Shader/ShaderFileLoader.cs b/src/Exomia.Framework/Graphics/Shader/ShaderFileLoader.cs index b89ce551..03fbb911 100644 --- a/src/Exomia.Framework/Graphics/Shader/ShaderFileLoader.cs +++ b/src/Exomia.Framework/Graphics/Shader/ShaderFileLoader.cs @@ -37,102 +37,6 @@ static class ShaderFileLoader "^\\s*\\*\\s*(vs|ps|ds|gs|hs|cs)\\s*([^\\s]+)\\s*([^\\s]+)\\s(.*)$", RegexOptions.Compiled | RegexOptions.Singleline); - public static Shader? FromStream(IGraphicsDevice graphicsDevice, Stream stream) - { - using StreamReader sr = new StreamReader(stream, Encoding.Default, true, 4096, true); - if (!SHADER_DEFINITION.Equals(sr.ReadLine()?.Trim(), StringComparison.InvariantCultureIgnoreCase)) - { - return null; - } - - IList techniques = new List(1); - - Technique? currentTechnique = null; - string? line; - while ((line = sr.ReadLine()?.Trim()) != null) - { - if (SHADER_DEFINITION_END.Equals(line, StringComparison.InvariantCultureIgnoreCase)) - { - break; - } - - if (!s_emptyLineRegex.IsMatch(line)) - { - Match techniqueMatch = s_techniqueRegex.Match(line); - if (techniqueMatch.Success) - { - techniques.Add(currentTechnique = new Technique(techniqueMatch.Groups[1].Value)); - continue; - } - - Match shaderInfoMatch = s_shaderInfoRegex.Match(line); - if (shaderInfoMatch.Success) - { - if (!Enum.TryParse(shaderInfoMatch.Groups[4].Value, out ShaderFlags flags)) - { - throw new InvalidDataException( - $"pass shader flags '{shaderInfoMatch.Groups[4].Value}' one or more flags are invalid or unsupported."); - } - currentTechnique?.Add( - new ShaderInfo( - shaderInfoMatch.Groups[1].Value, - shaderInfoMatch.Groups[2].Value, - shaderInfoMatch.Groups[3].Value, - flags)); - } - } - } - - string shaderSource = sr.ReadToEnd(); - - return new Shader( - techniques.Select( - t => - { - return (t.Name, - t.ShaderInfos.Select( - s => - { - using CompilationResult cr = ShaderBytecode.Compile( - shaderSource, - s.EntryPoint, - s.Profile, - s.Flags); - if (cr.HasErrors) { throw new InvalidDataException(cr.Message); } - return s.Type switch - { - "vs" => (Shader.Type.VertexShader, - (ComObject)new VertexShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr), - new ShaderReflection(cr)), - "ps" => (Shader.Type.PixelShader, - (ComObject)new PixelShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr), - new ShaderReflection(cr)), - "ds" => (Shader.Type.DomainShader, - (ComObject)new DomainShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr), - new ShaderReflection(cr)), - "gs" => (Shader.Type.GeometryShader, - (ComObject)new GeometryShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr), - new ShaderReflection(cr)), - "hs" => (Shader.Type.HullShader, - (ComObject)new HullShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr), - new ShaderReflection(cr)), - "cs" => (Shader.Type.ComputeShader, - (ComObject)new ComputeShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr), - new ShaderReflection(cr)), - _ => throw new InvalidDataException( - $"pass shader type '{s.Type}' doesn't exists or is unsupported.") - }; - }) - ); - })); - } - /// /// A technique. This class cannot be inherited. /// @@ -234,5 +138,101 @@ public override string ToString() return $"{Type} {EntryPoint} {Profile} {Flags}"; } } + + public static Shader? FromStream(IGraphicsDevice graphicsDevice, Stream stream) + { + using StreamReader sr = new StreamReader(stream, Encoding.Default, true, 4096, true); + if (!SHADER_DEFINITION.Equals(sr.ReadLine()?.Trim(), StringComparison.InvariantCultureIgnoreCase)) + { + return null; + } + + IList techniques = new List(1); + + Technique? currentTechnique = null; + string? line; + while ((line = sr.ReadLine()?.Trim()) != null) + { + if (SHADER_DEFINITION_END.Equals(line, StringComparison.InvariantCultureIgnoreCase)) + { + break; + } + + if (!s_emptyLineRegex.IsMatch(line)) + { + Match techniqueMatch = s_techniqueRegex.Match(line); + if (techniqueMatch.Success) + { + techniques.Add(currentTechnique = new Technique(techniqueMatch.Groups[1].Value)); + continue; + } + + Match shaderInfoMatch = s_shaderInfoRegex.Match(line); + if (shaderInfoMatch.Success) + { + if (!Enum.TryParse(shaderInfoMatch.Groups[4].Value, out ShaderFlags flags)) + { + throw new InvalidDataException( + $"pass shader flags '{shaderInfoMatch.Groups[4].Value}' one or more flags are invalid or unsupported."); + } + currentTechnique?.Add( + new ShaderInfo( + shaderInfoMatch.Groups[1].Value, + shaderInfoMatch.Groups[2].Value, + shaderInfoMatch.Groups[3].Value, + flags)); + } + } + } + + string shaderSource = sr.ReadToEnd(); + + return new Shader( + techniques.Select( + t => + { + return (t.Name, + t.ShaderInfos.Select( + s => + { + using CompilationResult cr = ShaderBytecode.Compile( + shaderSource, + s.EntryPoint, + s.Profile, + s.Flags); + if (cr.HasErrors) { throw new InvalidDataException(cr.Message); } + return s.Type switch + { + "vs" => (Shader.Type.VertexShader, + (ComObject)new VertexShader(graphicsDevice.Device, cr), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), + "ps" => (Shader.Type.PixelShader, + (ComObject)new PixelShader(graphicsDevice.Device, cr), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), + "ds" => (Shader.Type.DomainShader, + (ComObject)new DomainShader(graphicsDevice.Device, cr), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), + "gs" => (Shader.Type.GeometryShader, + (ComObject)new GeometryShader(graphicsDevice.Device, cr), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), + "hs" => (Shader.Type.HullShader, + (ComObject)new HullShader(graphicsDevice.Device, cr), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), + "cs" => (Shader.Type.ComputeShader, + (ComObject)new ComputeShader(graphicsDevice.Device, cr), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), + _ => throw new InvalidDataException( + $"pass shader type '{s.Type}' doesn't exists or is unsupported.") + }; + }) + ); + })); + } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.cs b/src/Exomia.Framework/Graphics/SpriteBatch.cs index 73b1a397..07b255a3 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.cs @@ -25,9 +25,6 @@ using SharpDX; using SharpDX.Direct3D; using SharpDX.Direct3D11; -using SharpDX.DXGI; -using Buffer = SharpDX.Direct3D11.Buffer; -using MapFlags = SharpDX.Direct3D11.MapFlags; namespace Exomia.Framework.Graphics { @@ -159,10 +156,7 @@ public SpriteBatch(IGraphicsDevice iDevice, SpriteSortAlgorithm sortAlgorithm = _vertexShader = technique; _pixelShader = technique; - _vertexInputLayout = new InputLayout( - _device, - technique.GetShaderSignature(Shader.Shader.Type.VertexShader), - technique.CreateInputElements(Shader.Shader.Type.VertexShader)); + _vertexInputLayout = technique.CreateInputLayout(iDevice, Shader.Shader.Type.VertexShader); } _vertexBuffer = VertexBuffer.Create(iDevice, MAX_VERTEX_COUNT); @@ -286,84 +280,31 @@ public void Resize(float width, float height) }; } - /// - /// Updates the vertex from sprite information. - /// - /// [in,out] Information describing the sprite. - /// [in,out] If non-null, the vpct pointer. - /// The delta x coordinate. - /// The delta y coordinate. - private static unsafe void UpdateVertexFromSpriteInfo(ref SpriteInfo spriteInfo, - VertexPositionColorTexture* vpctPtr, - float deltaX, - float deltaY) + internal struct SpriteInfo { - Vector2 origin = spriteInfo.Origin; - - // ReSharper disable once CompareOfFloatsByEqualityOperator - if (spriteInfo.Source.Width != 0f) - { - origin.X /= spriteInfo.Source.Width; - } - - // ReSharper disable once CompareOfFloatsByEqualityOperator - if (spriteInfo.Source.Height != 0f) - { - origin.Y /= spriteInfo.Source.Height; - } - - // ReSharper disable once CompareOfFloatsByEqualityOperator - if (spriteInfo.Rotation == 0f) - { - for (int j = 0; j < VERTICES_PER_SPRITE; j++) - { - VertexPositionColorTexture* vertex = vpctPtr + j; - - Vector2 corner = s_cornerOffsets[j]; - float posX = (corner.X - origin.X) * spriteInfo.Destination.Width; - float posY = (corner.Y - origin.Y) * spriteInfo.Destination.Height; - - vertex->X = spriteInfo.Destination.X + posX; - vertex->Y = spriteInfo.Destination.Y + posY; - vertex->Z = spriteInfo.Depth; - vertex->W = 1.0f; + public RectangleF Source; + public RectangleF Destination; + public Vector2 Origin; + public float Rotation; + public float Depth; + public SpriteEffects SpriteEffects; + public Color Color; + public float Opacity; + } - vertex->R = spriteInfo.Color.R * spriteInfo.Opacity; - vertex->G = spriteInfo.Color.G * spriteInfo.Opacity; - vertex->B = spriteInfo.Color.B * spriteInfo.Opacity; - vertex->A = spriteInfo.Color.A * spriteInfo.Opacity; + internal readonly struct TextureInfo + { + public readonly ShaderResourceView View; + public readonly int Width; + public readonly int Height; + public readonly long Ptr64; - corner = s_cornerOffsets[j ^ (int)spriteInfo.SpriteEffects]; - vertex->U = (spriteInfo.Source.X + (corner.X * spriteInfo.Source.Width)) * deltaX; - vertex->V = (spriteInfo.Source.Y + (corner.Y * spriteInfo.Source.Height)) * deltaY; - } - } - else + public TextureInfo(ShaderResourceView view, int width, int height) { - float cos = (float)Math.Cos(spriteInfo.Rotation); - float sin = (float)Math.Sin(spriteInfo.Rotation); - for (int j = 0; j < VERTICES_PER_SPRITE; j++) - { - VertexPositionColorTexture* vertex = vpctPtr + j; - - Vector2 corner = s_cornerOffsets[j]; - float posX = (corner.X - origin.X) * spriteInfo.Destination.Width; - float posY = (corner.Y - origin.Y) * spriteInfo.Destination.Height; - - vertex->X = (spriteInfo.Destination.X + (posX * cos)) - (posY * sin); - vertex->Y = spriteInfo.Destination.Y + (posX * sin) + (posY * cos); - vertex->Z = spriteInfo.Depth; - vertex->W = 1.0f; - - vertex->R = spriteInfo.Color.R * spriteInfo.Opacity; - vertex->G = spriteInfo.Color.G * spriteInfo.Opacity; - vertex->B = spriteInfo.Color.B * spriteInfo.Opacity; - vertex->A = spriteInfo.Color.A * spriteInfo.Opacity; - - corner = s_cornerOffsets[j ^ (int)spriteInfo.SpriteEffects]; - vertex->U = (spriteInfo.Source.X + (corner.X * spriteInfo.Source.Width)) * deltaX; - vertex->V = (spriteInfo.Source.Y + (corner.Y * spriteInfo.Source.Height)) * deltaY; - } + View = view; + Width = width; + Height = height; + Ptr64 = view.NativePointer.ToInt64(); } } @@ -551,34 +492,6 @@ private void PrepareForRendering() _context.InputAssembler.SetVertexBuffers(0, _vertexBuffer); } - internal struct SpriteInfo - { - public RectangleF Source; - public RectangleF Destination; - public Vector2 Origin; - public float Rotation; - public float Depth; - public SpriteEffects SpriteEffects; - public Color Color; - public float Opacity; - } - - internal readonly struct TextureInfo - { - public readonly ShaderResourceView View; - public readonly int Width; - public readonly int Height; - public readonly long Ptr64; - - public TextureInfo(ShaderResourceView view, int width, int height) - { - View = view; - Width = width; - Height = height; - Ptr64 = view.NativePointer.ToInt64(); - } - } - [StructLayout(LayoutKind.Explicit, Size = VERTEX_STRIDE)] private struct VertexPositionColorTexture { @@ -613,6 +526,87 @@ private struct VertexPositionColorTexture public float V; } + /// + /// Updates the vertex from sprite information. + /// + /// [in,out] Information describing the sprite. + /// [in,out] If non-null, the vpct pointer. + /// The delta x coordinate. + /// The delta y coordinate. + private static unsafe void UpdateVertexFromSpriteInfo(ref SpriteInfo spriteInfo, + VertexPositionColorTexture* vpctPtr, + float deltaX, + float deltaY) + { + Vector2 origin = spriteInfo.Origin; + + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (spriteInfo.Source.Width != 0f) + { + origin.X /= spriteInfo.Source.Width; + } + + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (spriteInfo.Source.Height != 0f) + { + origin.Y /= spriteInfo.Source.Height; + } + + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (spriteInfo.Rotation == 0f) + { + for (int j = 0; j < VERTICES_PER_SPRITE; j++) + { + VertexPositionColorTexture* vertex = vpctPtr + j; + + Vector2 corner = s_cornerOffsets[j]; + float posX = (corner.X - origin.X) * spriteInfo.Destination.Width; + float posY = (corner.Y - origin.Y) * spriteInfo.Destination.Height; + + vertex->X = spriteInfo.Destination.X + posX; + vertex->Y = spriteInfo.Destination.Y + posY; + vertex->Z = spriteInfo.Depth; + vertex->W = 1.0f; + + vertex->R = spriteInfo.Color.R * spriteInfo.Opacity; + vertex->G = spriteInfo.Color.G * spriteInfo.Opacity; + vertex->B = spriteInfo.Color.B * spriteInfo.Opacity; + vertex->A = spriteInfo.Color.A * spriteInfo.Opacity; + + corner = s_cornerOffsets[j ^ (int)spriteInfo.SpriteEffects]; + vertex->U = (spriteInfo.Source.X + (corner.X * spriteInfo.Source.Width)) * deltaX; + vertex->V = (spriteInfo.Source.Y + (corner.Y * spriteInfo.Source.Height)) * deltaY; + } + } + else + { + float cos = (float)Math.Cos(spriteInfo.Rotation); + float sin = (float)Math.Sin(spriteInfo.Rotation); + for (int j = 0; j < VERTICES_PER_SPRITE; j++) + { + VertexPositionColorTexture* vertex = vpctPtr + j; + + Vector2 corner = s_cornerOffsets[j]; + float posX = (corner.X - origin.X) * spriteInfo.Destination.Width; + float posY = (corner.Y - origin.Y) * spriteInfo.Destination.Height; + + vertex->X = (spriteInfo.Destination.X + (posX * cos)) - (posY * sin); + vertex->Y = spriteInfo.Destination.Y + (posX * sin) + (posY * cos); + vertex->Z = spriteInfo.Depth; + vertex->W = 1.0f; + + vertex->R = spriteInfo.Color.R * spriteInfo.Opacity; + vertex->G = spriteInfo.Color.G * spriteInfo.Opacity; + vertex->B = spriteInfo.Color.B * spriteInfo.Opacity; + vertex->A = spriteInfo.Color.A * spriteInfo.Opacity; + + corner = s_cornerOffsets[j ^ (int)spriteInfo.SpriteEffects]; + vertex->U = (spriteInfo.Source.X + (corner.X * spriteInfo.Source.Width)) * deltaX; + vertex->V = (spriteInfo.Source.Y + (corner.Y * spriteInfo.Source.Height)) * deltaY; + } + } + } + #region Drawing #region Defaults diff --git a/tools/Exomia.Framework.ContentManager/MainForm.cs b/tools/Exomia.Framework.ContentManager/MainForm.cs index 138b3293..81d1394f 100644 --- a/tools/Exomia.Framework.ContentManager/MainForm.cs +++ b/tools/Exomia.Framework.ContentManager/MainForm.cs @@ -78,29 +78,6 @@ public void SetProgressbarValue(bool state) }); } - private static bool IsNumber(object? value) - { - return value is sbyte - || value is byte - || value is short - || value is ushort - || value is int - || value is uint - || value is long - || value is ulong - || value is float - || value is double - || value is decimal; - } - - private static void ForAll(Action action, params T[] items) - { - foreach (T item in items) - { - action(item); - } - } - private void Clear() { richTextBox1.InvokeIfRequired( @@ -197,5 +174,28 @@ public int Compare(object x, object y) return 0; } } + + private static bool IsNumber(object? value) + { + return value is sbyte + || value is byte + || value is short + || value is ushort + || value is int + || value is uint + || value is long + || value is ulong + || value is float + || value is double + || value is decimal; + } + + private static void ForAll(Action action, params T[] items) + { + foreach (T item in items) + { + action(item); + } + } } } \ No newline at end of file From faad69045516cfe852db5514e381e69435aa62e0 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Tue, 10 Nov 2020 11:28:10 +0100 Subject: [PATCH 14/44] ref --- src/Exomia.Framework/Graphics/Shader/Shader.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Exomia.Framework/Graphics/Shader/Shader.cs b/src/Exomia.Framework/Graphics/Shader/Shader.cs index 4c8132d5..256579d8 100644 --- a/src/Exomia.Framework/Graphics/Shader/Shader.cs +++ b/src/Exomia.Framework/Graphics/Shader/Shader.cs @@ -234,6 +234,7 @@ public ComputeShader GetComputeShader() /// /// The . /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ShaderSignature GetShaderSignature(Type type) { return _passes[type].signature; @@ -247,6 +248,7 @@ public ShaderSignature GetShaderSignature(Type type) /// /// The . /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ShaderReflection GetShaderReflection(Type type) { return _passes[type].reflection; @@ -261,6 +263,7 @@ public ShaderReflection GetShaderReflection(Type type) /// The new input layout. /// /// Thrown when one or more required arguments are null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public InputLayout CreateInputLayout(IGraphicsDevice graphicsDevice, Type type) { return new InputLayout( From 1177eb4ac9f82c2ba1563b44c5f8fca315e7a213 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Tue, 10 Nov 2020 11:42:08 +0100 Subject: [PATCH 15/44] ref --- src/Exomia.Framework/Graphics/Shader/Shader.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Exomia.Framework/Graphics/Shader/Shader.cs b/src/Exomia.Framework/Graphics/Shader/Shader.cs index 256579d8..fee95130 100644 --- a/src/Exomia.Framework/Graphics/Shader/Shader.cs +++ b/src/Exomia.Framework/Graphics/Shader/Shader.cs @@ -423,13 +423,11 @@ private void Dispose(bool disposing) { if (!_disposed) { - // ReSharper disable once UseDeconstruction - foreach (KeyValuePair keyValuePair in _passes) + foreach (var (shader, signature, reflection) in _passes.Values) { - keyValuePair.Value.reflection.Dispose(); - keyValuePair.Value.signature.Dispose(); - keyValuePair.Value.shader.Dispose(); + reflection.Dispose(); + signature.Dispose(); + shader.Dispose(); } if (disposing) { From 66ea8283a136af7b7411d9118f790ee2ed344d56 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Tue, 10 Nov 2020 12:16:47 +0100 Subject: [PATCH 16/44] - renamed Shader.Technique to Shader.Group - 'Shaderdefinition' changed technique renamed to group --- .../Graphics/Shader/Shader.cs | 152 +++++++++--------- .../Graphics/Shader/ShaderFileLoader.cs | 32 ++-- src/Exomia.Framework/Graphics/SpriteBatch.cs | 8 +- .../Resources/shaders/canvas.ehlsl | 2 +- .../Resources/shaders/position_color.ehlsl | 2 +- .../shaders/position_color_texture.ehlsl | 2 +- .../shaders/position_normal_texture.ehlsl | 8 +- 7 files changed, 102 insertions(+), 104 deletions(-) diff --git a/src/Exomia.Framework/Graphics/Shader/Shader.cs b/src/Exomia.Framework/Graphics/Shader/Shader.cs index fee95130..271a1b66 100644 --- a/src/Exomia.Framework/Graphics/Shader/Shader.cs +++ b/src/Exomia.Framework/Graphics/Shader/Shader.cs @@ -63,95 +63,94 @@ public enum Type ComputeShader } - private readonly Dictionary _techniques; + private readonly Dictionary _groups; /// - /// Specify the technique to get + /// Specify the group to get. /// - /// The technique name. + /// The group name. /// - /// The . + /// The . /// - public Technique this[string name] + public Group this[string name] { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return GetTechnique(name); } + get { return GetGroup(name); } } /// /// Initializes a new instance of the class. /// - /// The techniques. - internal Shader( - IEnumerable<(string technique, IEnumerable<(Type, ComObject, ShaderSignature, ShaderReflection)> passes)> - techniques) + /// The shader groups. + internal Shader(IEnumerable<(string name, IEnumerable<(Type, ComObject, ShaderSignature, ShaderReflection)>)> + groups) { - _techniques = new Dictionary(StringComparer.InvariantCultureIgnoreCase); - foreach ((string technique, - IEnumerable<(Type, ComObject, ShaderSignature, ShaderReflection)> passes) in techniques) + _groups = new Dictionary(StringComparer.InvariantCultureIgnoreCase); + foreach ((string name, + IEnumerable<(Type, ComObject, ShaderSignature, ShaderReflection)> entries) in groups) { - _techniques.Add(technique, new Technique(passes)); + _groups.Add(name, new Group(entries)); } } /// - /// Gets all technique names from this shader instance. + /// Gets all group names from this shader instance. /// /// - /// An array of technique names. + /// An array of group names. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public string[] GetTechniqueNames() + public string[] GetGroupNames() { - return _techniques.Keys.ToArray(); + return _groups.Keys.ToArray(); } /// - /// Attempts to get a from the given . + /// Attempts to get a from the given . /// - /// The technique name. - /// [out] The technique. + /// The group name. + /// [out] The . /// /// True if it succeeds, false if it fails. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool TryGetTechnique(string name, out Technique technique) + public bool TryGetGroup(string name, out Group group) { - return _techniques.TryGetValue(name, out technique); + return _groups.TryGetValue(name, out group); } /// - /// Attempts to get a from the given . + /// Attempts to get a from the given . /// - /// The technique name. + /// The group name. /// - /// The . + /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Technique GetTechnique(string name) + public Group GetGroup(string name) { - return _techniques[name]; + return _groups[name]; } /// - /// A technique. This class cannot be inherited. + /// A shader group collection. This class cannot be inherited. /// - public sealed class Technique + public sealed class Group { private readonly - Dictionary _passes; + Dictionary _entries; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The passes. - internal Technique(IEnumerable<(Type, ComObject, ShaderSignature, ShaderReflection)> passes) + /// The entries. + internal Group(IEnumerable<(Type, ComObject, ShaderSignature, ShaderReflection)> entries) { - _passes = new Dictionary(); + _entries = new Dictionary(); foreach ((Type type, ComObject comObject, ShaderSignature signature, - ShaderReflection reflection) in passes) + ShaderReflection reflection) in entries) { - _passes.Add(type, (comObject, signature, reflection)); + _entries.Add(type, (comObject, signature, reflection)); } } @@ -164,7 +163,7 @@ internal Technique(IEnumerable<(Type, ComObject, ShaderSignature, ShaderReflecti [MethodImpl(MethodImplOptions.AggressiveInlining)] public VertexShader GetVertexShader() { - return (VertexShader)_passes[Type.VertexShader].shader; + return (VertexShader)_entries[Type.VertexShader].shader; } /// @@ -176,7 +175,7 @@ public VertexShader GetVertexShader() [MethodImpl(MethodImplOptions.AggressiveInlining)] public PixelShader GetPixelShader() { - return (PixelShader)_passes[Type.PixelShader].shader; + return (PixelShader)_entries[Type.PixelShader].shader; } /// @@ -188,7 +187,7 @@ public PixelShader GetPixelShader() [MethodImpl(MethodImplOptions.AggressiveInlining)] public DomainShader GetDomainShader() { - return (DomainShader)_passes[Type.DomainShader].shader; + return (DomainShader)_entries[Type.DomainShader].shader; } /// @@ -200,7 +199,7 @@ public DomainShader GetDomainShader() [MethodImpl(MethodImplOptions.AggressiveInlining)] public GeometryShader GetGeometryShader() { - return (GeometryShader)_passes[Type.GeometryShader].shader; + return (GeometryShader)_entries[Type.GeometryShader].shader; } /// @@ -212,7 +211,7 @@ public GeometryShader GetGeometryShader() [MethodImpl(MethodImplOptions.AggressiveInlining)] public HullShader GetHullShader() { - return (HullShader)_passes[Type.HullShader].shader; + return (HullShader)_entries[Type.HullShader].shader; } /// @@ -224,7 +223,7 @@ public HullShader GetHullShader() [MethodImpl(MethodImplOptions.AggressiveInlining)] public ComputeShader GetComputeShader() { - return (ComputeShader)_passes[Type.ComputeShader].shader; + return (ComputeShader)_entries[Type.ComputeShader].shader; } /// @@ -237,11 +236,10 @@ public ComputeShader GetComputeShader() [MethodImpl(MethodImplOptions.AggressiveInlining)] public ShaderSignature GetShaderSignature(Type type) { - return _passes[type].signature; + return _entries[type].signature; } /// - /// s /// Gets the . /// /// The type. @@ -251,7 +249,7 @@ public ShaderSignature GetShaderSignature(Type type) [MethodImpl(MethodImplOptions.AggressiveInlining)] public ShaderReflection GetShaderReflection(Type type) { - return _passes[type].reflection; + return _entries[type].reflection; } /// @@ -340,79 +338,79 @@ public InputElement[] CreateInputElements(Type type) /// /// Implicit converts the given Shader to a . /// - /// The technique. + /// The . /// /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator VertexShader(Technique technique) + public static implicit operator VertexShader(Group group) { - return technique.GetVertexShader(); + return group.GetVertexShader(); } /// /// Implicit converts the given Shader to a . /// - /// The technique. + /// The . /// /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator PixelShader(Technique technique) + public static implicit operator PixelShader(Group group) { - return technique.GetPixelShader(); + return group.GetPixelShader(); } /// /// Implicit converts the given Shader to a . /// - /// The technique. + /// The . /// /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator DomainShader(Technique technique) + public static implicit operator DomainShader(Group group) { - return technique.GetDomainShader(); + return group.GetDomainShader(); } /// /// Implicit converts the given Shader to a . /// - /// The technique. + /// The . /// /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator GeometryShader(Technique technique) + public static implicit operator GeometryShader(Group group) { - return technique.GetGeometryShader(); + return group.GetGeometryShader(); } /// /// Implicit converts the given Shader to a . /// - /// The technique. + /// The . /// /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator HullShader(Technique technique) + public static implicit operator HullShader(Group group) { - return technique.GetHullShader(); + return group.GetHullShader(); } /// /// Implicit converts the given Shader to a . /// - /// The technique. + /// The . /// /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator ComputeShader(Technique technique) + public static implicit operator ComputeShader(Group group) { - return technique.GetComputeShader(); + return group.GetComputeShader(); } #region IDisposable Support @@ -423,22 +421,22 @@ private void Dispose(bool disposing) { if (!_disposed) { - foreach (var (shader, signature, reflection) in _passes.Values) - { - reflection.Dispose(); - signature.Dispose(); - shader.Dispose(); - } if (disposing) { - _passes.Clear(); + foreach (var (shader, signature, reflection) in _entries.Values) + { + reflection.Dispose(); + signature.Dispose(); + shader.Dispose(); + } + _entries.Clear(); } _disposed = true; } } /// - ~Technique() + ~Group() { Dispose(false); } @@ -463,13 +461,13 @@ private void Dispose(bool disposing) { if (!_disposed) { - foreach (KeyValuePair keyValuePair in _techniques) - { - keyValuePair.Value.Dispose(); - } if (disposing) { - _techniques.Clear(); + foreach (Group group in _groups.Values) + { + group.Dispose(); + } + _groups.Clear(); } _disposed = true; } diff --git a/src/Exomia.Framework/Graphics/Shader/ShaderFileLoader.cs b/src/Exomia.Framework/Graphics/Shader/ShaderFileLoader.cs index 03fbb911..ef240ee9 100644 --- a/src/Exomia.Framework/Graphics/Shader/ShaderFileLoader.cs +++ b/src/Exomia.Framework/Graphics/Shader/ShaderFileLoader.cs @@ -29,8 +29,8 @@ static class ShaderFileLoader "^\\s*\\**\\s*$", RegexOptions.Compiled | RegexOptions.Singleline); - private static readonly Regex s_techniqueRegex = new Regex( - "^\\s*\\*\\s*technique\\s*(.*)$", + private static readonly Regex s_groupRegex = new Regex( + "^\\s*\\*\\s*group\\s*(.*)$", RegexOptions.Compiled | RegexOptions.Singleline); private static readonly Regex s_shaderInfoRegex = new Regex( @@ -38,9 +38,9 @@ static class ShaderFileLoader RegexOptions.Compiled | RegexOptions.Singleline); /// - /// A technique. This class cannot be inherited. + /// A group. This class cannot be inherited. /// - private sealed class Technique + private sealed class Group { /// /// Gets the name. @@ -59,10 +59,10 @@ private sealed class Technique public IList ShaderInfos { get; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The name. - public Technique(string name) + public Group(string name) { Name = name; ShaderInfos = new List(2); @@ -147,10 +147,10 @@ public override string ToString() return null; } - IList techniques = new List(1); + IList groups = new List(1); - Technique? currentTechnique = null; - string? line; + Group? currentGroup = null; + string? line; while ((line = sr.ReadLine()?.Trim()) != null) { if (SHADER_DEFINITION_END.Equals(line, StringComparison.InvariantCultureIgnoreCase)) @@ -160,10 +160,10 @@ public override string ToString() if (!s_emptyLineRegex.IsMatch(line)) { - Match techniqueMatch = s_techniqueRegex.Match(line); - if (techniqueMatch.Success) + Match groupMatch = s_groupRegex.Match(line); + if (groupMatch.Success) { - techniques.Add(currentTechnique = new Technique(techniqueMatch.Groups[1].Value)); + groups.Add(currentGroup = new Group(groupMatch.Groups[1].Value)); continue; } @@ -173,9 +173,9 @@ public override string ToString() if (!Enum.TryParse(shaderInfoMatch.Groups[4].Value, out ShaderFlags flags)) { throw new InvalidDataException( - $"pass shader flags '{shaderInfoMatch.Groups[4].Value}' one or more flags are invalid or unsupported."); + $"shader flags '{shaderInfoMatch.Groups[4].Value}' one or more flags are invalid or unsupported."); } - currentTechnique?.Add( + currentGroup?.Add( new ShaderInfo( shaderInfoMatch.Groups[1].Value, shaderInfoMatch.Groups[2].Value, @@ -188,7 +188,7 @@ public override string ToString() string shaderSource = sr.ReadToEnd(); return new Shader( - techniques.Select( + groups.Select( t => { return (t.Name, @@ -228,7 +228,7 @@ public override string ToString() ShaderSignature.GetInputSignature(cr), new ShaderReflection(cr)), _ => throw new InvalidDataException( - $"pass shader type '{s.Type}' doesn't exists or is unsupported.") + $"shader type '{s.Type}' doesn't exists or is unsupported.") }; }) ); diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.cs b/src/Exomia.Framework/Graphics/SpriteBatch.cs index 07b255a3..99cc47a1 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.cs @@ -149,14 +149,14 @@ public SpriteBatch(IGraphicsDevice iDevice, SpriteSortAlgorithm sortAlgorithm = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.{Shaders.POSITION_COLOR_TEXTURE}") ?? throw new NullReferenceException($"{assembly.GetName().Name}.{Shaders.POSITION_COLOR_TEXTURE}")) { - Shader.Shader.Technique technique = + Shader.Shader.Group group = (_shader = ShaderFileLoader.FromStream(iDevice, stream) ?? throw new NullReferenceException(nameof(ShaderFileLoader.FromStream)))["DEFAULT"]; - _vertexShader = technique; - _pixelShader = technique; + _vertexShader = group; + _pixelShader = group; - _vertexInputLayout = technique.CreateInputLayout(iDevice, Shader.Shader.Type.VertexShader); + _vertexInputLayout = group.CreateInputLayout(iDevice, Shader.Shader.Type.VertexShader); } _vertexBuffer = VertexBuffer.Create(iDevice, MAX_VERTEX_COUNT); diff --git a/src/Exomia.Framework/Resources/shaders/canvas.ehlsl b/src/Exomia.Framework/Resources/shaders/canvas.ehlsl index 1fb7c445..99186dc2 100644 --- a/src/Exomia.Framework/Resources/shaders/canvas.ehlsl +++ b/src/Exomia.Framework/Resources/shaders/canvas.ehlsl @@ -1,6 +1,6 @@ /** Shaderdefinition * - * technique DEFAULT + * group DEFAULT * vs VSMain vs_5_0 OptimizationLevel3 * ps PSMain ps_5_0 OptimizationLevel3 */ diff --git a/src/Exomia.Framework/Resources/shaders/position_color.ehlsl b/src/Exomia.Framework/Resources/shaders/position_color.ehlsl index 54154171..63b481b8 100644 --- a/src/Exomia.Framework/Resources/shaders/position_color.ehlsl +++ b/src/Exomia.Framework/Resources/shaders/position_color.ehlsl @@ -1,6 +1,6 @@ /** Shaderdefinition * - * technique DEFAULT + * group DEFAULT * vs VSMain vs_5_0 OptimizationLevel3 * ps PSMain ps_5_0 OptimizationLevel3 */ diff --git a/src/Exomia.Framework/Resources/shaders/position_color_texture.ehlsl b/src/Exomia.Framework/Resources/shaders/position_color_texture.ehlsl index 4d73e51f..b957adaa 100644 --- a/src/Exomia.Framework/Resources/shaders/position_color_texture.ehlsl +++ b/src/Exomia.Framework/Resources/shaders/position_color_texture.ehlsl @@ -1,6 +1,6 @@ /** Shaderdefinition * - * technique DEFAULT + * group DEFAULT * vs VSMain vs_5_0 OptimizationLevel3 * ps PSMain ps_5_0 OptimizationLevel3 */ diff --git a/src/Exomia.Framework/Resources/shaders/position_normal_texture.ehlsl b/src/Exomia.Framework/Resources/shaders/position_normal_texture.ehlsl index 376adad7..260428d9 100644 --- a/src/Exomia.Framework/Resources/shaders/position_normal_texture.ehlsl +++ b/src/Exomia.Framework/Resources/shaders/position_normal_texture.ehlsl @@ -1,18 +1,18 @@ /** Shaderdefinition * - * technique VERTEX_LIGHTING_PHONG + * group VERTEX_LIGHTING_PHONG * vs VS_VERTEX_LIGHTING_PHONG vs_5_0 OptimizationLevel3 * ps PS_VERTEX_LIGHTING ps_5_0 OptimizationLevel3 * - * technique VERTEX_LIGHTING_BLINNPHONG + * group VERTEX_LIGHTING_BLINNPHONG * vs VS_VERTEX_LIGHTING_BLINNPHONG vs_5_0 OptimizationLevel3 * ps PS_VERTEX_LIGHTING ps_5_0 OptimizationLevel3 * - * technique PIXEL_LIGHTING_PHONG + * group PIXEL_LIGHTING_PHONG * vs VS_PIXEL_LIGHTING_PHONG vs_5_0 OptimizationLevel3 * ps PS_PIXEL_LIGHTING_PHONG ps_5_0 OptimizationLevel3 * - * technique PIXEL_LIGHTING_BLINNPHONG + * group PIXEL_LIGHTING_BLINNPHONG * vs VS_PIXEL_LIGHTING_BLINNPHONG vs_5_0 OptimizationLevel3 * ps PS_PIXEL_LIGHTING_BLINNPHONG ps_5_0 OptimizationLevel3 */ From d2b64795abe58cbb4594f42eace20d9c755a680d Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Tue, 10 Nov 2020 22:25:33 +0100 Subject: [PATCH 17/44] ref & renaming --- .../ContentSerialization/ContentSerializer.cs | 103 +++++++++--------- ....cs => ColorContentSerializationReader.cs} | 5 +- .../RectangleContentSerializationReader.cs | 29 +++++ .../Readers/RectangleFCR.cs | 50 --------- .../RectangleFContentSerializationReader.cs | 29 +++++ ...s => Vector2ContentSerializationReader.cs} | 5 +- ...s => Vector3ContentSerializationReader.cs} | 5 +- ....cs => ColorContentSerializationWriter.cs} | 5 +- .../RectangleContentSerializationWriter.cs | 26 +++++ .../Writers/RectangleFCW.cs | 44 -------- .../RectangleFContentSerializationWriter.cs | 26 +++++ ...s => Vector2ContentSerializationWriter.cs} | 5 +- ...s => Vector3ContentSerializationWriter.cs} | 5 +- src/Exomia.Framework/Exomia.Framework.csproj | 14 +++ .../Extensions/DeconstructExtensions.cs | 27 +++++ ... SpriteFont.ContentSerializationReader.cs} | 14 +-- ... SpriteFont.ContentSerializationWriter.cs} | 15 +-- src/Exomia.Framework/Graphics/SpriteFont.cs | 2 +- .../Graphics/SpriteFontContentReader.cs | 13 +-- 19 files changed, 219 insertions(+), 203 deletions(-) rename src/Exomia.Framework/ContentSerialization/Readers/{ColorCR.cs => ColorContentSerializationReader.cs} (81%) create mode 100644 src/Exomia.Framework/ContentSerialization/Readers/RectangleContentSerializationReader.cs delete mode 100644 src/Exomia.Framework/ContentSerialization/Readers/RectangleFCR.cs create mode 100644 src/Exomia.Framework/ContentSerialization/Readers/RectangleFContentSerializationReader.cs rename src/Exomia.Framework/ContentSerialization/Readers/{Vector2CR.cs => Vector2ContentSerializationReader.cs} (76%) rename src/Exomia.Framework/ContentSerialization/Readers/{Vector3CR.cs => Vector3ContentSerializationReader.cs} (79%) rename src/Exomia.Framework/ContentSerialization/Writers/{ColorCW.cs => ColorContentSerializationWriter.cs} (80%) create mode 100644 src/Exomia.Framework/ContentSerialization/Writers/RectangleContentSerializationWriter.cs delete mode 100644 src/Exomia.Framework/ContentSerialization/Writers/RectangleFCW.cs create mode 100644 src/Exomia.Framework/ContentSerialization/Writers/RectangleFContentSerializationWriter.cs rename src/Exomia.Framework/ContentSerialization/Writers/{Vector2CW.cs => Vector2ContentSerializationWriter.cs} (77%) rename src/Exomia.Framework/ContentSerialization/Writers/{Vector3CW.cs => Vector3ContentSerializationWriter.cs} (79%) create mode 100644 src/Exomia.Framework/Extensions/DeconstructExtensions.cs rename src/Exomia.Framework/Graphics/{SpriteFontCR.cs => SpriteFont.ContentSerializationReader.cs} (86%) rename src/Exomia.Framework/Graphics/{SpriteFontCW.cs => SpriteFont.ContentSerializationWriter.cs} (85%) diff --git a/src/Exomia.Framework/ContentSerialization/ContentSerializer.cs b/src/Exomia.Framework/ContentSerialization/ContentSerializer.cs index 2b915c7f..8b8af4a6 100644 --- a/src/Exomia.Framework/ContentSerialization/ContentSerializer.cs +++ b/src/Exomia.Framework/ContentSerialization/ContentSerializer.cs @@ -16,6 +16,9 @@ using Exomia.Framework.ContentSerialization.Readers; using Exomia.Framework.ContentSerialization.Types; using Exomia.Framework.ContentSerialization.Writers; +#if NETSTANDARD2_0 +using Exomia.Framework.Extensions; +#endif using SharpDX; namespace Exomia.Framework.ContentSerialization @@ -117,8 +120,7 @@ static ContentSerializer() { if (a.FullName.StartsWith("System") || a.FullName.StartsWith("SharpDX") || - a.FullName.StartsWith("ms") || - a.FullName.StartsWith("Xilium.CefGlue")) { continue; } + a.FullName.StartsWith("ms")) { continue; } foreach (Type t in a.GetTypes()) { @@ -135,28 +137,28 @@ static ContentSerializer() #region SharpDX - AddWriter(new Vector3CW()); - AddWriter(new Vector2CW()); - AddWriter(new ColorCW()); - AddWriter(new RectangleCW()); - AddWriter(new RectangleFCW()); + AddWriter(new Vector3ContentSerializationWriter()); + AddWriter(new Vector2ContentSerializationWriter()); + AddWriter(new ColorContentSerializationWriter()); + AddWriter(new RectangleContentSerializationWriter()); + AddWriter(new RectangleFContentSerializationWriter()); - AddReader(new Vector3CR()); - AddReader(new Vector2CR()); - AddReader(new ColorCR()); - AddReader(new RectangleCR()); - AddReader(new RectangleFCR()); + AddReader(new Vector3ContentSerializationReader()); + AddReader(new Vector2ContentSerializationReader()); + AddReader(new ColorContentSerializationReader()); + AddReader(new RectangleContentSerializationReader()); + AddReader(new RectangleFContentSerializationReader()); #endregion } /// - /// Adds a new content pipeline reader to the content pipeline. + /// Adds a new to the content pipeline. /// - /// the type the reader can read. - /// IContentSerializationReader. - /// ArgumentNullException. - /// CSReaderException. + /// The type the reader can read. + /// The . + /// Thrown when one or more required arguments are null. + /// Thrown when a Create struct Reader error condition occurs. public static void AddReader(Type type, IContentSerializationReader reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } @@ -173,20 +175,20 @@ public static void AddReader(Type type, IContentSerializationReader reader) /// /// Adds a new content pipeline reader to the content pipeline. /// - /// the type the reader can read. - /// IContentSerializationReader. + /// Generic type parameter. + /// The . public static void AddReader(IContentSerializationReader reader) { AddReader(typeof(T), reader); } /// - /// Adds a new content pipeline writer to the content pipeline. + /// Adds a new to the content pipeline. /// - /// the type the writer can write. - /// IContentSerializationWriter. - /// ArgumentNullException. - /// CSWriterException. + /// The type the writer can write. + /// The . + /// Thrown when one or more required arguments are null. + /// Thrown when a Create struct Writer error condition occurs. public static void AddWriter(Type type, IContentSerializationWriter writer) { if (writer == null) { throw new ArgumentNullException(nameof(writer)); } @@ -202,17 +204,13 @@ public static void AddWriter(Type type, IContentSerializationWriter writer) /// /// Adds a new content pipeline writer to the content pipeline. /// - /// the type the writer can write. - /// IContentSerializationWriter. + /// Generic type parameter. + /// The . public static void AddWriter(IContentSerializationWriter writer) { AddWriter(typeof(T), writer); } - /// - /// Adds an assembly. - /// - /// The assembly. private static void AddAssembly(Assembly assembly) { string assemblyName = assembly.GetName().Name; @@ -229,7 +227,7 @@ private static void AddAssembly(Assembly assembly) /// /// Generic type parameter. /// Name of the asset. - /// Object. + /// The object. /// (Optional) True to minify. /// Thrown when one or more required arguments are null. public static void Write(string assetName, T obj, bool minify = false) where T : class @@ -265,13 +263,13 @@ public static void Write(string assetName, T obj, bool minify = false) where /// /// The write handler. /// The tab space. - /// Object. - /// the type the reader can read. + /// The Object. + /// The type the reader can read. /// /// Thrown when a Create struct Writer error condition /// occurs. /// - internal static void Write(Action writeHandler, string tabSpace, object obj, Type type) + internal static void Write(Action writeHandler, string tabSpace, object? obj, Type type) { if (obj == null) { return; } @@ -283,20 +281,20 @@ internal static void Write(Action writeHandler, string tabSpace, ContentSerializationContext context = new ContentSerializationContext(); writer.Write(context, obj); - foreach (KeyValuePair ctxt in context.Content) + foreach ((var key, ContentSerializationContextValue value) in context.Content) { - if (ctxt.Value.Object == null) { continue; } + if (value.Object == null) { continue; } - if (s_types.TryGetValue(ctxt.Value.Type.Name.ToUpper(), out IType it) || - s_types.TryGetValue(ctxt.Value.Type.BaseType.Name.ToUpper(), out it)) + if (s_types.TryGetValue(value.Type.Name.ToUpper(), out IType it) || + s_types.TryGetValue(value.Type.BaseType!.Name.ToUpper(), out it)) { - it.Write(writeHandler, tabSpace, ctxt.Key, ctxt.Value.Object); + it.Write(writeHandler, tabSpace, key, value.Object); } else { - writeHandler(tabSpace, $"[{ctxt.Key}:{ctxt.Value.Type}]"); - Write(writeHandler, tabSpace + TABSPACE, ctxt.Value.Object, ctxt.Value.Type); - writeHandler(tabSpace, $"[/{ctxt.Key}]"); + writeHandler(tabSpace, $"[{key}:{value.Type}]"); + Write(writeHandler, tabSpace + TABSPACE, value.Object, value.Type); + writeHandler(tabSpace, $"[/{key}]"); } } } @@ -306,10 +304,10 @@ internal static void Write(Action writeHandler, string tabSpace, #region ContentReader /// - /// Reads a object from the given stream. + /// Reads an object from the given stream. /// /// Generic type parameter. - /// Stream. + /// The stream. /// (Optional) True to keep open. /// /// A T. @@ -347,11 +345,11 @@ public static T Read(Stream stream, bool keepOpen = false) where T : class /// /// Reads a object from the given stream. /// - /// Stream. - /// the type the reader can read. + /// The stream. + /// The type the reader can read. /// The object key. /// - /// T Object. + /// An object. /// /// /// Thrown when a Create struct Reader error condition @@ -365,9 +363,7 @@ internal static object Read(CSStreamReader stream, Type type, string objKey) } ContentSerializationContext context = new ContentSerializationContext(); - Read(stream, ref context, objKey); - return reader.Read(context); } @@ -404,7 +400,7 @@ private static void Read(CSStreamReader stream, ref ContentSerializationContext if (string.IsNullOrEmpty(genericTypeInfo)) { throw new CSReaderException( - $"ERROR: NO GENERIC TYPE INFO DEFINED -> {baseTypeInfo}"); + $"ERROR: No generic type info defined -> {baseTypeInfo}"); } context.Set( key, it.Read(stream, key, genericTypeInfo, dimensionInfo), it.BaseType); @@ -422,14 +418,15 @@ private static void Read(CSStreamReader stream, ref ContentSerializationContext if ($"/{objKey}" != key) { throw new CSReaderException( - $"ERROR: INVALID ENDTAG DEFINITION! -> {objKey} != {key}"); + $"ERROR: Invalid end tag definition! -> {objKey} != {key}"); } return; } } break; case '/': - throw new CSReaderException($"ERROR: INVALID FILE CONTENT! -> invalid char '{c}'!"); + throw new CSReaderException( + $"ERROR: Invalid file content char '{c}' at ({stream.Line}:{stream.Index})!"); case '\n': case '\r': case '\t': @@ -437,7 +434,7 @@ private static void Read(CSStreamReader stream, ref ContentSerializationContext break; default: Console.WriteLine( - $"WARNING: invalid char '{c}' found near line {stream.Line} -> index {stream.Index}!"); + $"WARNING: invalid char '{c}' found near ({stream.Line}:{stream.Index})!"); break; } } diff --git a/src/Exomia.Framework/ContentSerialization/Readers/ColorCR.cs b/src/Exomia.Framework/ContentSerialization/Readers/ColorContentSerializationReader.cs similarity index 81% rename from src/Exomia.Framework/ContentSerialization/Readers/ColorCR.cs rename to src/Exomia.Framework/ContentSerialization/Readers/ColorContentSerializationReader.cs index 28a1b21f..807719e9 100644 --- a/src/Exomia.Framework/ContentSerialization/Readers/ColorCR.cs +++ b/src/Exomia.Framework/ContentSerialization/Readers/ColorContentSerializationReader.cs @@ -12,10 +12,7 @@ namespace Exomia.Framework.ContentSerialization.Readers { - /// - /// A color carriage return. This class cannot be inherited. - /// - sealed class ColorCR : ContentSerializationReader + sealed class ColorContentSerializationReader : ContentSerializationReader { /// public override Color ReadContext(ContentSerializationContext context) diff --git a/src/Exomia.Framework/ContentSerialization/Readers/RectangleContentSerializationReader.cs b/src/Exomia.Framework/ContentSerialization/Readers/RectangleContentSerializationReader.cs new file mode 100644 index 00000000..7a434a2d --- /dev/null +++ b/src/Exomia.Framework/ContentSerialization/Readers/RectangleContentSerializationReader.cs @@ -0,0 +1,29 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using SharpDX; + +namespace Exomia.Framework.ContentSerialization.Readers +{ + sealed class RectangleContentSerializationReader : ContentSerializationReader + { + /// + public override Rectangle ReadContext(ContentSerializationContext context) + { + return new Rectangle + { + X = context.Get(nameof(Rectangle.X)), + Y = context.Get(nameof(Rectangle.Y)), + Width = context.Get(nameof(Rectangle.Width)), + Height = context.Get(nameof(Rectangle.Height)) + }; + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/ContentSerialization/Readers/RectangleFCR.cs b/src/Exomia.Framework/ContentSerialization/Readers/RectangleFCR.cs deleted file mode 100644 index 9ef0ec16..00000000 --- a/src/Exomia.Framework/ContentSerialization/Readers/RectangleFCR.cs +++ /dev/null @@ -1,50 +0,0 @@ -#region License - -// Copyright (c) 2018-2020, exomia -// All rights reserved. -// -// This source code is licensed under the BSD-style license found in the -// LICENSE file in the root directory of this source tree. - -#endregion - -using SharpDX; - -namespace Exomia.Framework.ContentSerialization.Readers -{ - /// - /// A rectangle fcr. This class cannot be inherited. - /// - sealed class RectangleFCR : ContentSerializationReader - { - /// - public override RectangleF ReadContext(ContentSerializationContext context) - { - return new RectangleF - { - X = context.Get(nameof(RectangleF.X)), - Y = context.Get(nameof(RectangleF.Y)), - Width = context.Get(nameof(RectangleF.Width)), - Height = context.Get(nameof(RectangleF.Height)) - }; - } - } - - /// - /// A rectangle carriage return. This class cannot be inherited. - /// - sealed class RectangleCR : ContentSerializationReader - { - /// - public override Rectangle ReadContext(ContentSerializationContext context) - { - return new Rectangle - { - X = context.Get(nameof(Rectangle.X)), - Y = context.Get(nameof(Rectangle.Y)), - Width = context.Get(nameof(Rectangle.Width)), - Height = context.Get(nameof(Rectangle.Height)) - }; - } - } -} \ No newline at end of file diff --git a/src/Exomia.Framework/ContentSerialization/Readers/RectangleFContentSerializationReader.cs b/src/Exomia.Framework/ContentSerialization/Readers/RectangleFContentSerializationReader.cs new file mode 100644 index 00000000..b06cb526 --- /dev/null +++ b/src/Exomia.Framework/ContentSerialization/Readers/RectangleFContentSerializationReader.cs @@ -0,0 +1,29 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using SharpDX; + +namespace Exomia.Framework.ContentSerialization.Readers +{ + sealed class RectangleFContentSerializationReader : ContentSerializationReader + { + /// + public override RectangleF ReadContext(ContentSerializationContext context) + { + return new RectangleF + { + X = context.Get(nameof(RectangleF.X)), + Y = context.Get(nameof(RectangleF.Y)), + Width = context.Get(nameof(RectangleF.Width)), + Height = context.Get(nameof(RectangleF.Height)) + }; + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/ContentSerialization/Readers/Vector2CR.cs b/src/Exomia.Framework/ContentSerialization/Readers/Vector2ContentSerializationReader.cs similarity index 76% rename from src/Exomia.Framework/ContentSerialization/Readers/Vector2CR.cs rename to src/Exomia.Framework/ContentSerialization/Readers/Vector2ContentSerializationReader.cs index 888231d3..13179d1a 100644 --- a/src/Exomia.Framework/ContentSerialization/Readers/Vector2CR.cs +++ b/src/Exomia.Framework/ContentSerialization/Readers/Vector2ContentSerializationReader.cs @@ -12,10 +12,7 @@ namespace Exomia.Framework.ContentSerialization.Readers { - /// - /// A vector 2 carriage return. This class cannot be inherited. - /// - sealed class Vector2CR : ContentSerializationReader + sealed class Vector2ContentSerializationReader : ContentSerializationReader { /// public override Vector2 ReadContext(ContentSerializationContext context) diff --git a/src/Exomia.Framework/ContentSerialization/Readers/Vector3CR.cs b/src/Exomia.Framework/ContentSerialization/Readers/Vector3ContentSerializationReader.cs similarity index 79% rename from src/Exomia.Framework/ContentSerialization/Readers/Vector3CR.cs rename to src/Exomia.Framework/ContentSerialization/Readers/Vector3ContentSerializationReader.cs index 3511e85f..a07eda88 100644 --- a/src/Exomia.Framework/ContentSerialization/Readers/Vector3CR.cs +++ b/src/Exomia.Framework/ContentSerialization/Readers/Vector3ContentSerializationReader.cs @@ -12,10 +12,7 @@ namespace Exomia.Framework.ContentSerialization.Readers { - /// - /// A vector 3 carriage return. This class cannot be inherited. - /// - sealed class Vector3CR : ContentSerializationReader + sealed class Vector3ContentSerializationReader : ContentSerializationReader { /// public override Vector3 ReadContext(ContentSerializationContext context) diff --git a/src/Exomia.Framework/ContentSerialization/Writers/ColorCW.cs b/src/Exomia.Framework/ContentSerialization/Writers/ColorContentSerializationWriter.cs similarity index 80% rename from src/Exomia.Framework/ContentSerialization/Writers/ColorCW.cs rename to src/Exomia.Framework/ContentSerialization/Writers/ColorContentSerializationWriter.cs index be18a7c7..8d2df092 100644 --- a/src/Exomia.Framework/ContentSerialization/Writers/ColorCW.cs +++ b/src/Exomia.Framework/ContentSerialization/Writers/ColorContentSerializationWriter.cs @@ -12,10 +12,7 @@ namespace Exomia.Framework.ContentSerialization.Writers { - /// - /// A color cw. This class cannot be inherited. - /// - sealed class ColorCW : ContentSerializationWriter + sealed class ColorContentSerializationWriter : ContentSerializationWriter { /// public override void WriteContext(ContentSerializationContext context, Color obj) diff --git a/src/Exomia.Framework/ContentSerialization/Writers/RectangleContentSerializationWriter.cs b/src/Exomia.Framework/ContentSerialization/Writers/RectangleContentSerializationWriter.cs new file mode 100644 index 00000000..45f6b66f --- /dev/null +++ b/src/Exomia.Framework/ContentSerialization/Writers/RectangleContentSerializationWriter.cs @@ -0,0 +1,26 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using SharpDX; + +namespace Exomia.Framework.ContentSerialization.Writers +{ + sealed class RectangleContentSerializationWriter : ContentSerializationWriter + { + /// + public override void WriteContext(ContentSerializationContext context, Rectangle obj) + { + context.Set(nameof(Rectangle.X), obj.X); + context.Set(nameof(Rectangle.Y), obj.Y); + context.Set(nameof(Rectangle.Width), obj.Width); + context.Set(nameof(Rectangle.Height), obj.Height); + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/ContentSerialization/Writers/RectangleFCW.cs b/src/Exomia.Framework/ContentSerialization/Writers/RectangleFCW.cs deleted file mode 100644 index 461cf87d..00000000 --- a/src/Exomia.Framework/ContentSerialization/Writers/RectangleFCW.cs +++ /dev/null @@ -1,44 +0,0 @@ -#region License - -// Copyright (c) 2018-2020, exomia -// All rights reserved. -// -// This source code is licensed under the BSD-style license found in the -// LICENSE file in the root directory of this source tree. - -#endregion - -using SharpDX; - -namespace Exomia.Framework.ContentSerialization.Writers -{ - /// - /// A rectangle fcw. This class cannot be inherited. - /// - sealed class RectangleFCW : ContentSerializationWriter - { - /// - public override void WriteContext(ContentSerializationContext context, RectangleF obj) - { - context.Set(nameof(RectangleF.X), obj.X); - context.Set(nameof(RectangleF.Y), obj.Y); - context.Set(nameof(RectangleF.Width), obj.Width); - context.Set(nameof(RectangleF.Height), obj.Height); - } - } - - /// - /// A rectangle cw. This class cannot be inherited. - /// - sealed class RectangleCW : ContentSerializationWriter - { - /// - public override void WriteContext(ContentSerializationContext context, Rectangle obj) - { - context.Set(nameof(Rectangle.X), obj.X); - context.Set(nameof(Rectangle.Y), obj.Y); - context.Set(nameof(Rectangle.Width), obj.Width); - context.Set(nameof(Rectangle.Height), obj.Height); - } - } -} \ No newline at end of file diff --git a/src/Exomia.Framework/ContentSerialization/Writers/RectangleFContentSerializationWriter.cs b/src/Exomia.Framework/ContentSerialization/Writers/RectangleFContentSerializationWriter.cs new file mode 100644 index 00000000..4bca32a3 --- /dev/null +++ b/src/Exomia.Framework/ContentSerialization/Writers/RectangleFContentSerializationWriter.cs @@ -0,0 +1,26 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using SharpDX; + +namespace Exomia.Framework.ContentSerialization.Writers +{ + sealed class RectangleFContentSerializationWriter : ContentSerializationWriter + { + /// + public override void WriteContext(ContentSerializationContext context, RectangleF obj) + { + context.Set(nameof(RectangleF.X), obj.X); + context.Set(nameof(RectangleF.Y), obj.Y); + context.Set(nameof(RectangleF.Width), obj.Width); + context.Set(nameof(RectangleF.Height), obj.Height); + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/ContentSerialization/Writers/Vector2CW.cs b/src/Exomia.Framework/ContentSerialization/Writers/Vector2ContentSerializationWriter.cs similarity index 77% rename from src/Exomia.Framework/ContentSerialization/Writers/Vector2CW.cs rename to src/Exomia.Framework/ContentSerialization/Writers/Vector2ContentSerializationWriter.cs index 040c151e..748ea654 100644 --- a/src/Exomia.Framework/ContentSerialization/Writers/Vector2CW.cs +++ b/src/Exomia.Framework/ContentSerialization/Writers/Vector2ContentSerializationWriter.cs @@ -12,10 +12,7 @@ namespace Exomia.Framework.ContentSerialization.Writers { - /// - /// A vector 2 cw. This class cannot be inherited. - /// - sealed class Vector2CW : ContentSerializationWriter + sealed class Vector2ContentSerializationWriter : ContentSerializationWriter { /// public override void WriteContext(ContentSerializationContext context, Vector2 obj) diff --git a/src/Exomia.Framework/ContentSerialization/Writers/Vector3CW.cs b/src/Exomia.Framework/ContentSerialization/Writers/Vector3ContentSerializationWriter.cs similarity index 79% rename from src/Exomia.Framework/ContentSerialization/Writers/Vector3CW.cs rename to src/Exomia.Framework/ContentSerialization/Writers/Vector3ContentSerializationWriter.cs index 214e2cc9..1c20f06c 100644 --- a/src/Exomia.Framework/ContentSerialization/Writers/Vector3CW.cs +++ b/src/Exomia.Framework/ContentSerialization/Writers/Vector3ContentSerializationWriter.cs @@ -12,10 +12,7 @@ namespace Exomia.Framework.ContentSerialization.Writers { - /// - /// A vector 3 cw. This class cannot be inherited. - /// - sealed class Vector3CW : ContentSerializationWriter + sealed class Vector3ContentSerializationWriter : ContentSerializationWriter { /// public override void WriteContext(ContentSerializationContext context, Vector3 obj) diff --git a/src/Exomia.Framework/Exomia.Framework.csproj b/src/Exomia.Framework/Exomia.Framework.csproj index dd0dc96a..3bb5a048 100644 --- a/src/Exomia.Framework/Exomia.Framework.csproj +++ b/src/Exomia.Framework/Exomia.Framework.csproj @@ -181,6 +181,20 @@ RenderForm.cs + + + + + Math2.cs + + + + + + + SpriteFont.cs + + diff --git a/src/Exomia.Framework/Extensions/DeconstructExtensions.cs b/src/Exomia.Framework/Extensions/DeconstructExtensions.cs new file mode 100644 index 00000000..ef40d4d9 --- /dev/null +++ b/src/Exomia.Framework/Extensions/DeconstructExtensions.cs @@ -0,0 +1,27 @@ +#if NETSTANDARD2_0 +using System.Collections.Generic; + +namespace Exomia.Framework.Extensions +{ + + /// + /// A deconstruct extensions. + /// + public static class DeconstructExtensions + { + /// + /// A type deconstruct-or that extracts the individual members from this object. + /// + /// Type of the key. + /// Type of the value. + /// The kvp. + /// [out] The key. + /// [out] The value. + public static void Deconstruct(this KeyValuePair kvp, out TKey key, out TValue value) + { + key = kvp.Key; + value = kvp.Value; + } + } +} +#endif \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteFontCR.cs b/src/Exomia.Framework/Graphics/SpriteFont.ContentSerializationReader.cs similarity index 86% rename from src/Exomia.Framework/Graphics/SpriteFontCR.cs rename to src/Exomia.Framework/Graphics/SpriteFont.ContentSerializationReader.cs index 97ad13db..757c9196 100644 --- a/src/Exomia.Framework/Graphics/SpriteFontCR.cs +++ b/src/Exomia.Framework/Graphics/SpriteFont.ContentSerializationReader.cs @@ -15,10 +15,7 @@ namespace Exomia.Framework.Graphics { - /// - /// A sprite font carriage return. This class cannot be inherited. - /// - sealed class SpriteFontCR : ContentSerializationReader + sealed class SpriteFontContentSerializationReader : ContentSerializationReader { /// public override SpriteFont ReadContext(ContentSerializationContext context) @@ -39,10 +36,7 @@ public override SpriteFont ReadContext(ContentSerializationContext context) }; } } - - /// - /// A sprite font glyph carriage return. This class cannot be inherited. - /// + sealed class SpriteFontGlyphCR : ContentSerializationReader { /// @@ -58,10 +52,6 @@ public override SpriteFont.Glyph ReadContext(ContentSerializationContext context }; } } - - /// - /// A sprite font kerning carriage return. This class cannot be inherited. - /// sealed class SpriteFontKerningCR : ContentSerializationReader { /// diff --git a/src/Exomia.Framework/Graphics/SpriteFontCW.cs b/src/Exomia.Framework/Graphics/SpriteFont.ContentSerializationWriter.cs similarity index 85% rename from src/Exomia.Framework/Graphics/SpriteFontCW.cs rename to src/Exomia.Framework/Graphics/SpriteFont.ContentSerializationWriter.cs index 21ee3554..0ef1f8b2 100644 --- a/src/Exomia.Framework/Graphics/SpriteFontCW.cs +++ b/src/Exomia.Framework/Graphics/SpriteFont.ContentSerializationWriter.cs @@ -13,10 +13,7 @@ namespace Exomia.Framework.Graphics { - /// - /// A sprite font cw. This class cannot be inherited. - /// - sealed class SpriteFontCW : ContentSerializationWriter + sealed class SpriteFontContentSerializationWriter : ContentSerializationWriter { /// public override void WriteContext(ContentSerializationContext context, SpriteFont obj) @@ -39,10 +36,7 @@ public override void WriteContext(ContentSerializationContext context, SpriteFon context.Set(nameof(SpriteFont.ImageData), Convert.ToBase64String(obj.ImageData)); } } - - /// - /// A sprite font glyph cw. This class cannot be inherited. - /// + sealed class SpriteFontGlyphCW : ContentSerializationWriter { /// @@ -55,10 +49,7 @@ public override void WriteContext(ContentSerializationContext context, SpriteFon context.Set(nameof(SpriteFont.Glyph.XAdvance), obj.XAdvance); } } - - /// - /// A sprite font kerning cw. This class cannot be inherited. - /// + sealed class SpriteFontKerningCW : ContentSerializationWriter { /// diff --git a/src/Exomia.Framework/Graphics/SpriteFont.cs b/src/Exomia.Framework/Graphics/SpriteFont.cs index 89cb0b98..a7460e8b 100644 --- a/src/Exomia.Framework/Graphics/SpriteFont.cs +++ b/src/Exomia.Framework/Graphics/SpriteFont.cs @@ -21,7 +21,7 @@ namespace Exomia.Framework.Graphics /// A sprite font. This class cannot be inherited. /// [ContentReadable(typeof(SpriteFontContentReader))] - [ContentSerializable(typeof(SpriteFontCR), typeof(SpriteFontCW))] + [ContentSerializable(typeof(SpriteFontContentSerializationReader), typeof(SpriteFontContentSerializationWriter))] public sealed class SpriteFont : IDisposable { private Glyph _defaultGlyph; diff --git a/src/Exomia.Framework/Graphics/SpriteFontContentReader.cs b/src/Exomia.Framework/Graphics/SpriteFontContentReader.cs index e1170373..eb141197 100644 --- a/src/Exomia.Framework/Graphics/SpriteFontContentReader.cs +++ b/src/Exomia.Framework/Graphics/SpriteFontContentReader.cs @@ -15,16 +15,13 @@ namespace Exomia.Framework.Graphics { - /// - /// A sprite font content reader. This class cannot be inherited. - /// sealed class SpriteFontContentReader : IContentReader { /// public object? ReadContent(IContentManager contentManager, ref ContentReaderParameters parameters) { SpriteFont font = ContentSerializer.Read(parameters.Stream); - if (font.ImageData == null) + if (font.ImageData.Length <= 0) { return null; } @@ -34,9 +31,11 @@ sealed class SpriteFontContentReader : IContentReader try { - using MemoryStream ms = new MemoryStream(font.ImageData) { Position = 0 }; - font.Texture = Texture.Load(graphicsDevice.Device, ms) ?? - throw new NullReferenceException($"{nameof(font.Texture)}"); + using (MemoryStream ms = new MemoryStream(font.ImageData) { Position = 0 }) + { + font.Texture = Texture.Load(graphicsDevice.Device, ms) ?? + throw new NullReferenceException($"{nameof(font.Texture)}"); + } } catch { return null; } From d70690d9ff39a87cf54591369999f785ac896769 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Wed, 11 Nov 2020 10:51:29 +0100 Subject: [PATCH 18/44] ref & cleanup --- .../ContentSerialization/ContentSerializer.cs | 2 +- src/Exomia.Framework/Exomia.Framework.csproj | 7 + .../Extensions/DeconstructExtensions.cs | 12 +- src/Exomia.Framework/Graphics/Model/Mesh.cs | 82 +- src/Exomia.Framework/Graphics/Model/Obj.cs | 10 +- .../Graphics/Shader/ShaderFileLoader.cs | 192 ++-- .../Graphics/SpriteBatch.Drawing.cs | 881 +++++++++++++++++ src/Exomia.Framework/Graphics/SpriteBatch.cs | 926 +----------------- .../SpriteFont.ContentSerializationReader.cs | 3 +- .../SpriteFont.ContentSerializationWriter.cs | 4 +- src/Exomia.Framework/Graphics/SpriteFont.cs | 48 +- .../MainForm.cs | 46 +- 12 files changed, 1135 insertions(+), 1078 deletions(-) create mode 100644 src/Exomia.Framework/Graphics/SpriteBatch.Drawing.cs diff --git a/src/Exomia.Framework/ContentSerialization/ContentSerializer.cs b/src/Exomia.Framework/ContentSerialization/ContentSerializer.cs index 8b8af4a6..f5c0472b 100644 --- a/src/Exomia.Framework/ContentSerialization/ContentSerializer.cs +++ b/src/Exomia.Framework/ContentSerialization/ContentSerializer.cs @@ -16,10 +16,10 @@ using Exomia.Framework.ContentSerialization.Readers; using Exomia.Framework.ContentSerialization.Types; using Exomia.Framework.ContentSerialization.Writers; +using SharpDX; #if NETSTANDARD2_0 using Exomia.Framework.Extensions; #endif -using SharpDX; namespace Exomia.Framework.ContentSerialization { diff --git a/src/Exomia.Framework/Exomia.Framework.csproj b/src/Exomia.Framework/Exomia.Framework.csproj index 3bb5a048..0e671565 100644 --- a/src/Exomia.Framework/Exomia.Framework.csproj +++ b/src/Exomia.Framework/Exomia.Framework.csproj @@ -189,6 +189,13 @@ + + + + SpriteBatch.cs + + + diff --git a/src/Exomia.Framework/Extensions/DeconstructExtensions.cs b/src/Exomia.Framework/Extensions/DeconstructExtensions.cs index ef40d4d9..1bd06e80 100644 --- a/src/Exomia.Framework/Extensions/DeconstructExtensions.cs +++ b/src/Exomia.Framework/Extensions/DeconstructExtensions.cs @@ -1,4 +1,14 @@ -#if NETSTANDARD2_0 +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +#if NETSTANDARD2_0 using System.Collections.Generic; namespace Exomia.Framework.Extensions diff --git a/src/Exomia.Framework/Graphics/Model/Mesh.cs b/src/Exomia.Framework/Graphics/Model/Mesh.cs index f00f76c0..1d23179c 100644 --- a/src/Exomia.Framework/Graphics/Model/Mesh.cs +++ b/src/Exomia.Framework/Graphics/Model/Mesh.cs @@ -53,6 +53,47 @@ private Mesh(PositionNormalTexture2D[] vertices, uint[] indices, Texture texture Material = material; } + /// + /// Initializes a new instance from the given instance. + /// + /// The object. + /// The texture. + /// The material. + /// + /// A Mesh. + /// + public static Mesh FromObj(Obj obj, Texture texture, Material material) + { + List vertices = new List(); + List indices = new List(); + + uint index = 0; + foreach (Obj.Face face in obj.Faces) + { + PositionNormalTexture2D FromIndex(int i) + { + Obj.Vertex v = obj.Vertices[face.Vertices[i].V - 1]; + Obj.Normal n = obj.Normals[face.Vertices[i].N - 1]; + Obj.Texture t = obj.Textures[face.Vertices[i].T - 1]; + return new PositionNormalTexture2D(v.X, v.Y, v.Z, v.W, n.X, n.Y, n.Z, t.U, t.V); + } + + vertices.Add(FromIndex(0)); + vertices.Add(FromIndex(1)); + uint indexZero = index++; + for (int i = 2; i < face.Vertices.Length; i++) + { + indices.Add(indexZero); + indices.Add(index++); + indices.Add(index); + vertices.Add(FromIndex(i)); + } + index++; + } + + return new Mesh(vertices.ToArray(), indices.ToArray(), texture, material); + } + /// /// A position normal texture. /// @@ -146,46 +187,5 @@ public PositionNormalTexture2D(float x, V = v; } } - - /// - /// Initializes a new instance from the given instance. - /// - /// The object. - /// The texture. - /// The material. - /// - /// A Mesh. - /// - public static Mesh FromObj(Obj obj, Texture texture, Material material) - { - List vertices = new List(); - List indices = new List(); - - uint index = 0; - foreach (Obj.Face face in obj.Faces) - { - PositionNormalTexture2D FromIndex(int i) - { - Obj.Vertex v = obj.Vertices[face.Vertices[i].V - 1]; - Obj.Normal n = obj.Normals[face.Vertices[i].N - 1]; - Obj.Texture t = obj.Textures[face.Vertices[i].T - 1]; - return new PositionNormalTexture2D(v.X, v.Y, v.Z, v.W, n.X, n.Y, n.Z, t.U, t.V); - } - - vertices.Add(FromIndex(0)); - vertices.Add(FromIndex(1)); - uint indexZero = index++; - for (int i = 2; i < face.Vertices.Length; i++) - { - indices.Add(indexZero); - indices.Add(index++); - indices.Add(index); - vertices.Add(FromIndex(i)); - } - index++; - } - - return new Mesh(vertices.ToArray(), indices.ToArray(), texture, material); - } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Model/Obj.cs b/src/Exomia.Framework/Graphics/Model/Obj.cs index 1e4ee821..80f08125 100644 --- a/src/Exomia.Framework/Graphics/Model/Obj.cs +++ b/src/Exomia.Framework/Graphics/Model/Obj.cs @@ -59,6 +59,11 @@ private Obj(Vertex[] vertices, Normal[] normals, Texture[] textures, Face[] face Faces = faces; } + internal static Obj Create(Vertex[] vertices, Normal[] normals, Texture[] textures, Face[] faces) + { + return new Obj(vertices, normals, textures, faces); + } + /// /// A vertex. /// @@ -270,10 +275,5 @@ public override string ToString() return $"{string.Join(", ", Vertices)} [{Vertices.Length}]"; } } - - internal static Obj Create(Vertex[] vertices, Normal[] normals, Texture[] textures, Face[] faces) - { - return new Obj(vertices, normals, textures, faces); - } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Shader/ShaderFileLoader.cs b/src/Exomia.Framework/Graphics/Shader/ShaderFileLoader.cs index ef240ee9..5aab1a52 100644 --- a/src/Exomia.Framework/Graphics/Shader/ShaderFileLoader.cs +++ b/src/Exomia.Framework/Graphics/Shader/ShaderFileLoader.cs @@ -37,6 +37,102 @@ static class ShaderFileLoader "^\\s*\\*\\s*(vs|ps|ds|gs|hs|cs)\\s*([^\\s]+)\\s*([^\\s]+)\\s(.*)$", RegexOptions.Compiled | RegexOptions.Singleline); + public static Shader? FromStream(IGraphicsDevice graphicsDevice, Stream stream) + { + using StreamReader sr = new StreamReader(stream, Encoding.Default, true, 4096, true); + if (!SHADER_DEFINITION.Equals(sr.ReadLine()?.Trim(), StringComparison.InvariantCultureIgnoreCase)) + { + return null; + } + + IList groups = new List(1); + + Group? currentGroup = null; + string? line; + while ((line = sr.ReadLine()?.Trim()) != null) + { + if (SHADER_DEFINITION_END.Equals(line, StringComparison.InvariantCultureIgnoreCase)) + { + break; + } + + if (!s_emptyLineRegex.IsMatch(line)) + { + Match groupMatch = s_groupRegex.Match(line); + if (groupMatch.Success) + { + groups.Add(currentGroup = new Group(groupMatch.Groups[1].Value)); + continue; + } + + Match shaderInfoMatch = s_shaderInfoRegex.Match(line); + if (shaderInfoMatch.Success) + { + if (!Enum.TryParse(shaderInfoMatch.Groups[4].Value, out ShaderFlags flags)) + { + throw new InvalidDataException( + $"shader flags '{shaderInfoMatch.Groups[4].Value}' one or more flags are invalid or unsupported."); + } + currentGroup?.Add( + new ShaderInfo( + shaderInfoMatch.Groups[1].Value, + shaderInfoMatch.Groups[2].Value, + shaderInfoMatch.Groups[3].Value, + flags)); + } + } + } + + string shaderSource = sr.ReadToEnd(); + + return new Shader( + groups.Select( + t => + { + return (t.Name, + t.ShaderInfos.Select( + s => + { + using CompilationResult cr = ShaderBytecode.Compile( + shaderSource, + s.EntryPoint, + s.Profile, + s.Flags); + if (cr.HasErrors) { throw new InvalidDataException(cr.Message); } + return s.Type switch + { + "vs" => (Shader.Type.VertexShader, + (ComObject)new VertexShader(graphicsDevice.Device, cr), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), + "ps" => (Shader.Type.PixelShader, + (ComObject)new PixelShader(graphicsDevice.Device, cr), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), + "ds" => (Shader.Type.DomainShader, + (ComObject)new DomainShader(graphicsDevice.Device, cr), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), + "gs" => (Shader.Type.GeometryShader, + (ComObject)new GeometryShader(graphicsDevice.Device, cr), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), + "hs" => (Shader.Type.HullShader, + (ComObject)new HullShader(graphicsDevice.Device, cr), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), + "cs" => (Shader.Type.ComputeShader, + (ComObject)new ComputeShader(graphicsDevice.Device, cr), + ShaderSignature.GetInputSignature(cr), + new ShaderReflection(cr)), + _ => throw new InvalidDataException( + $"shader type '{s.Type}' doesn't exists or is unsupported.") + }; + }) + ); + })); + } + /// /// A group. This class cannot be inherited. /// @@ -138,101 +234,5 @@ public override string ToString() return $"{Type} {EntryPoint} {Profile} {Flags}"; } } - - public static Shader? FromStream(IGraphicsDevice graphicsDevice, Stream stream) - { - using StreamReader sr = new StreamReader(stream, Encoding.Default, true, 4096, true); - if (!SHADER_DEFINITION.Equals(sr.ReadLine()?.Trim(), StringComparison.InvariantCultureIgnoreCase)) - { - return null; - } - - IList groups = new List(1); - - Group? currentGroup = null; - string? line; - while ((line = sr.ReadLine()?.Trim()) != null) - { - if (SHADER_DEFINITION_END.Equals(line, StringComparison.InvariantCultureIgnoreCase)) - { - break; - } - - if (!s_emptyLineRegex.IsMatch(line)) - { - Match groupMatch = s_groupRegex.Match(line); - if (groupMatch.Success) - { - groups.Add(currentGroup = new Group(groupMatch.Groups[1].Value)); - continue; - } - - Match shaderInfoMatch = s_shaderInfoRegex.Match(line); - if (shaderInfoMatch.Success) - { - if (!Enum.TryParse(shaderInfoMatch.Groups[4].Value, out ShaderFlags flags)) - { - throw new InvalidDataException( - $"shader flags '{shaderInfoMatch.Groups[4].Value}' one or more flags are invalid or unsupported."); - } - currentGroup?.Add( - new ShaderInfo( - shaderInfoMatch.Groups[1].Value, - shaderInfoMatch.Groups[2].Value, - shaderInfoMatch.Groups[3].Value, - flags)); - } - } - } - - string shaderSource = sr.ReadToEnd(); - - return new Shader( - groups.Select( - t => - { - return (t.Name, - t.ShaderInfos.Select( - s => - { - using CompilationResult cr = ShaderBytecode.Compile( - shaderSource, - s.EntryPoint, - s.Profile, - s.Flags); - if (cr.HasErrors) { throw new InvalidDataException(cr.Message); } - return s.Type switch - { - "vs" => (Shader.Type.VertexShader, - (ComObject)new VertexShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr), - new ShaderReflection(cr)), - "ps" => (Shader.Type.PixelShader, - (ComObject)new PixelShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr), - new ShaderReflection(cr)), - "ds" => (Shader.Type.DomainShader, - (ComObject)new DomainShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr), - new ShaderReflection(cr)), - "gs" => (Shader.Type.GeometryShader, - (ComObject)new GeometryShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr), - new ShaderReflection(cr)), - "hs" => (Shader.Type.HullShader, - (ComObject)new HullShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr), - new ShaderReflection(cr)), - "cs" => (Shader.Type.ComputeShader, - (ComObject)new ComputeShader(graphicsDevice.Device, cr), - ShaderSignature.GetInputSignature(cr), - new ShaderReflection(cr)), - _ => throw new InvalidDataException( - $"shader type '{s.Type}' doesn't exists or is unsupported.") - }; - }) - ); - })); - } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.Drawing.cs b/src/Exomia.Framework/Graphics/SpriteBatch.Drawing.cs new file mode 100644 index 00000000..d9eed65f --- /dev/null +++ b/src/Exomia.Framework/Graphics/SpriteBatch.Drawing.cs @@ -0,0 +1,881 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using System.Text; +using System.Threading; +using SharpDX; + +namespace Exomia.Framework.Graphics +{ + public sealed partial class SpriteBatch + { + #region Defaults + + /// + /// Draw rectangle. + /// + /// Destination rectangle. + /// The color. + /// Width of the line. + /// The rotation. + /// The opacity. + /// Depth of the layer. + public void DrawRectangle(in RectangleF destinationRectangle, + in Color color, + float lineWidth, + float rotation, + float opacity, + float layerDepth) + { + DrawRectangle(destinationRectangle, color, lineWidth, rotation, s_vector2Zero, opacity, layerDepth); + } + + /// + /// Draw rectangle. + /// + /// Destination rectangle. + /// The color. + /// Width of the line. + /// The rotation. + /// The origin. + /// The opacity. + /// Depth of the layer. + public void DrawRectangle(in RectangleF destinationRectangle, + in Color color, + float lineWidth, + float rotation, + in Vector2 origin, + float opacity, + float layerDepth) + { + Vector2[] vertex; + + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (rotation == 0.0f) + { + vertex = new[] + { + destinationRectangle.TopLeft, destinationRectangle.TopRight, destinationRectangle.BottomRight, + destinationRectangle.BottomLeft + }; + } + else + { + vertex = new Vector2[4]; + + Vector2 o = origin; + + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (destinationRectangle.Width != 0f) + { + o.X /= destinationRectangle.Width; + } + + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (destinationRectangle.Height != 0f) + { + o.Y /= destinationRectangle.Height; + } + + float cos = (float)Math.Cos(rotation); + float sin = (float)Math.Sin(rotation); + for (int j = 0; j < VERTICES_PER_SPRITE; j++) + { + Vector2 corner = s_cornerOffsets[j]; + float posX = (corner.X - o.X) * destinationRectangle.Width; + float posY = (corner.Y - o.Y) * destinationRectangle.Height; + + vertex[j] = new Vector2( + (destinationRectangle.X + (posX * cos)) - (posY * sin), + destinationRectangle.Y + (posX * sin) + (posY * cos)); + } + } + + DrawPolygon(vertex, color, lineWidth, opacity, layerDepth); + } + + /// + /// Draw fill rectangle. + /// + /// Destination rectangle. + /// The color. + /// Depth of the layer. + public void DrawFillRectangle(in RectangleF destinationRectangle, in Color color, float layerDepth) + { + DrawSprite( + _whiteTexture, destinationRectangle, false, s_nullRectangle, + color, 0.0f, s_vector2Zero, 1.0f, SpriteEffects.None, layerDepth); + } + + /// + /// Draw fill rectangle. + /// + /// Destination rectangle. + /// The color. + /// The opacity. + /// Depth of the layer. + public void DrawFillRectangle(in RectangleF destinationRectangle, + in Color color, + float opacity, + float layerDepth) + { + DrawSprite( + _whiteTexture, destinationRectangle, false, s_nullRectangle, + color, 0.0f, s_vector2Zero, opacity, SpriteEffects.None, layerDepth); + } + + /// + /// Draw fill rectangle. + /// + /// Destination rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// Depth of the layer. + public void DrawFillRectangle(in RectangleF destinationRectangle, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + float layerDepth) + { + DrawSprite( + _whiteTexture, destinationRectangle, false, s_nullRectangle, + color, rotation, origin, opacity, SpriteEffects.None, layerDepth); + } + + /// + /// Draw line. + /// + /// The first point. + /// The second point. + /// The color. + /// Width of the line. + /// The opacity. + /// Depth of the layer. + public void DrawLine(in Vector2 point1, + in Vector2 point2, + in Color color, + float lineWidth, + float opacity, + float layerDepth) + { + DrawLine(point1, point2, color, lineWidth, opacity, 1.0f, layerDepth); + } + + /// + /// Draw line. + /// + /// The first point. + /// The second point. + /// The color. + /// Width of the line. + /// The opacity. + /// The length factor. + /// Depth of the layer. + public void DrawLine(in Vector2 point1, + in Vector2 point2, + in Color color, + float lineWidth, + float opacity, + float lengthFactor, + float layerDepth) + { + DrawSprite( + _whiteTexture, new RectangleF( + point1.X, point1.Y, Vector2.Distance(point1, point2) * lengthFactor, lineWidth), false, + s_nullRectangle, color, (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X), + s_vector2Zero, opacity, SpriteEffects.None, layerDepth); + } + + /// + /// Draw polygon. + /// + /// The vertex. + /// The color. + /// Width of the line. + /// The opacity. + /// Depth of the layer. + public void DrawPolygon(Vector2[] vertex, in Color color, float lineWidth, float opacity, float layerDepth) + { + if (vertex.Length > 1) + { + int l = vertex.Length - 1; + for (int i = 0; i < l; i++) + { + DrawLine(vertex[i], vertex[i + 1], color, lineWidth, opacity, layerDepth); + } + DrawLine(vertex[l], vertex[0], color, lineWidth, opacity, layerDepth); + } + } + + /// + /// Draw circle. + /// + /// The center. + /// The radius. + /// The color. + /// Width of the line. + /// The opacity. + /// The segments. + /// Depth of the layer. + public void DrawCircle(in Vector2 center, + float radius, + in Color color, + float lineWidth, + float opacity, + int segments, + float layerDepth) + { + DrawCircle(center, radius, 0, MathUtil.TwoPi, color, lineWidth, opacity, segments, layerDepth); + } + + /// + /// Draw circle. + /// + /// The center. + /// The radius. + /// The start. + /// The end. + /// The color. + /// Width of the line. + /// The opacity. + /// The segments. + /// Depth of the layer. + public void DrawCircle(in Vector2 center, + float radius, + float start, + float end, + in Color color, + float lineWidth, + float opacity, + int segments, + float layerDepth) + { + Vector2[] vertex = new Vector2[segments]; + + float increment = (end - start) / segments; + float theta = start; + + for (int i = 0; i < segments; i++) + { + vertex[i].X = center.X + (radius * (float)Math.Cos(theta)); + vertex[i].Y = center.Y + (radius * (float)Math.Sin(theta)); + theta += increment; + } + + DrawPolygon(vertex, color, lineWidth, opacity, layerDepth); + } + + #endregion + + #region Texture + + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// The position. + /// The color. + public void Draw(Texture texture, in Vector2 position, in Color color) + { + DrawSprite( + texture, new RectangleF(position.X, position.Y, 1f, 1f), true, s_nullRectangle, + color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); + } + + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// Destination rectangle. + /// The color. + public void Draw(Texture texture, in RectangleF destinationRectangle, in Color color) + { + DrawSprite( + texture, destinationRectangle, false, s_nullRectangle, + color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); + } + + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// The position. + /// Source rectangle. + /// The color. + public void Draw(Texture texture, in Vector2 position, in Rectangle? sourceRectangle, in Color color) + { + DrawSprite( + texture, new RectangleF(position.X, position.Y, 1f, 1f), true, sourceRectangle, + color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); + } + + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// Destination rectangle. + /// Source rectangle. + /// The color. + public void Draw(Texture texture, + in RectangleF destinationRectangle, + in Rectangle? sourceRectangle, + in Color color) + { + DrawSprite( + texture, destinationRectangle, false, sourceRectangle, + color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); + } + + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// The position. + /// The color. + /// The rotation. + /// The origin. + /// (Optional) Depth of the layer. + public void Draw(Texture texture, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float layerDepth = 0f) + { + DrawSprite( + texture, new RectangleF(position.X, position.Y, 1f, 1f), true, s_nullRectangle, + color, rotation, origin, 1.0f, SpriteEffects.None, layerDepth); + } + + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// Destination rectangle. + /// The color. + /// The rotation. + /// The origin. + /// Depth of the layer. + public void Draw(Texture texture, + in RectangleF destinationRectangle, + in Color color, + float rotation, + in Vector2 origin, + float layerDepth = 0f) + { + DrawSprite( + texture, destinationRectangle, false, s_nullRectangle, + color, rotation, origin, 1.0f, SpriteEffects.None, layerDepth); + } + + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// Destination rectangle. + /// Source rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + /// Depth of the layer. + public void Draw(Texture texture, + in RectangleF destinationRectangle, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects, + float layerDepth) + { + DrawSprite( + texture, destinationRectangle, false, sourceRectangle, + color, rotation, origin, opacity, effects, layerDepth); + } + + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// The position. + /// Source rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The scale. + /// The opacity. + /// The effects. + /// Depth of the layer. + public void Draw(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float scale, + float opacity, + SpriteEffects effects, + float layerDepth) + { + DrawSprite( + texture, new RectangleF(position.X, position.Y, scale, scale), true, sourceRectangle, + color, rotation, origin, opacity, effects, layerDepth); + } + + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// The position. + /// Source rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The scale. + /// The opacity. + /// The effects. + /// Depth of the layer. + public void Draw(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + in Vector2 scale, + float opacity, + SpriteEffects effects, + float layerDepth) + { + DrawSprite( + texture, new RectangleF(position.X, position.Y, scale.X, scale.Y), true, sourceRectangle, + color, rotation, origin, opacity, effects, layerDepth); + } + + private unsafe void DrawSprite(Texture texture, + in RectangleF destination, + bool scaleDestination, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects, + float depth) + { + if (!_isBeginCalled) + { + throw new InvalidOperationException("Begin must be called before draw"); + } + + if (texture.TexturePointer == IntPtr.Zero) + { + throw new ArgumentNullException(nameof(texture)); + } + + if (_spriteQueueCount >= _spriteQueue.Length) + { + bool lockTaken = false; + try + { + _spinLock.Enter(ref lockTaken); + + int size = _spriteQueue.Length * 2; + _sortIndices = new int[size]; + _sortedSprites = new SpriteInfo[size]; + Array.Resize(ref _spriteQueue, size); + Array.Resize(ref _spriteTextures, size); + } + finally + { + if (lockTaken) + { + _spinLock.Exit(false); + } + } + } + + if (!_textureInfos.TryGetValue(texture.TexturePointer, out TextureInfo textureInfo)) + { + bool lockTaken = false; + try + { + _spinLock.Enter(ref lockTaken); + if (!_textureInfos.TryGetValue(texture.TexturePointer, out textureInfo)) + { + textureInfo = new TextureInfo(texture.TextureView, texture.Width, texture.Height); + _textureInfos.Add(texture.TexturePointer, textureInfo); + } + } + finally + { + if (lockTaken) + { + _spinLock.Exit(false); + } + } + } + + int spriteQueueCount = Interlocked.Increment(ref _spriteQueueCount) - 1; + fixed (SpriteInfo* spriteInfo = &_spriteQueue[spriteQueueCount]) + { + float width; + float height; + if (sourceRectangle.HasValue) + { + Rectangle rectangle = sourceRectangle.Value; + spriteInfo->Source.X = rectangle.X; + spriteInfo->Source.Y = rectangle.Y; + width = rectangle.Width; + height = rectangle.Height; + } + else + { + spriteInfo->Source.X = 0; + spriteInfo->Source.Y = 0; + width = texture.Width; + height = texture.Height; + } + + spriteInfo->Source.Width = width; + spriteInfo->Source.Height = height; + + spriteInfo->Destination.X = destination.X; + spriteInfo->Destination.Y = destination.Y; + + if (scaleDestination) + { + spriteInfo->Destination.Width = destination.Width * width; + spriteInfo->Destination.Height = destination.Height * height; + } + else + { + spriteInfo->Destination.Width = destination.Width; + spriteInfo->Destination.Height = destination.Height; + } + + if (spriteInfo->Destination.Width < 0) + { + spriteInfo->Destination.X += spriteInfo->Destination.Width; + spriteInfo->Destination.Width = -spriteInfo->Destination.Width; + } + + if (spriteInfo->Destination.Height < 0) + { + spriteInfo->Destination.Y += spriteInfo->Destination.Height; + spriteInfo->Destination.Height = -spriteInfo->Destination.Height; + } + + spriteInfo->Origin = origin; + spriteInfo->Rotation = rotation; + spriteInfo->Depth = depth; + spriteInfo->SpriteEffects = effects; + spriteInfo->Color = color; + spriteInfo->Opacity = opacity; + } + + _spriteTextures[spriteQueueCount] = textureInfo; + } + + #endregion + + #region SpiteFont + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + /// Depth of the layer. + public void DrawText(SpriteFont font, string text, in Vector2 position, in Color color, float layerDepth) + { + font.Draw( + DrawTextInternal, text, position, + color, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + /// The rotation. + /// Depth of the layer. + public void DrawText(SpriteFont font, + string text, + in Vector2 position, + in Color color, + float rotation, + float layerDepth) + { + font.Draw( + DrawTextInternal, text, position, + color, rotation, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + /// Depth of the layer. + public void DrawText(SpriteFont font, + string text, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects, + float layerDepth) + { + font.Draw( + DrawTextInternal, text, position, + color, rotation, origin, opacity, effects, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The start. + /// The end. + /// The position. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + /// Depth of the layer. + public void DrawText(SpriteFont font, + string text, + int start, + int end, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects, + float layerDepth) + { + font.Draw( + DrawTextInternal, text, start, end, position, + color, rotation, origin, opacity, effects, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The start. + /// The end. + /// The position. + /// The dimension. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + /// Depth of the layer. + public void DrawText(SpriteFont font, + string text, + int start, + int end, + in Vector2 position, + in Size2F dimension, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects, + float layerDepth) + { + font.Draw( + DrawTextInternal, text, start, end, position, dimension, + color, rotation, origin, opacity, effects, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + /// Depth of the layer. + public void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, in Color color, float layerDepth) + { + font.Draw( + DrawTextInternal, text, position, + color, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + /// The rotation. + /// Depth of the layer. + public void DrawText(SpriteFont font, + StringBuilder text, + in Vector2 position, + in Color color, + float rotation, + float layerDepth) + { + font.Draw( + DrawTextInternal, text, position, + color, rotation, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + /// Depth of the layer. + public void DrawText(SpriteFont font, + StringBuilder text, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects, + float layerDepth) + { + font.Draw( + DrawTextInternal, text, position, + color, rotation, origin, opacity, effects, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The start. + /// The end. + /// The position. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + /// Depth of the layer. + public void DrawText(SpriteFont font, + StringBuilder text, + int start, + int end, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects, + float layerDepth) + { + font.Draw( + DrawTextInternal, text, start, end, position, + color, rotation, origin, opacity, effects, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The start. + /// The end. + /// The position. + /// The dimension. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + /// Depth of the layer. + public void DrawText(SpriteFont font, + StringBuilder text, + int start, + int end, + in Vector2 position, + in Size2F dimension, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects, + float layerDepth) + { + font.Draw( + DrawTextInternal, text, start, end, position, dimension, + color, rotation, origin, opacity, effects, layerDepth); + } + + /// + /// Draw text internal. + /// + /// The texture. + /// The position. + /// Source rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The scale. + /// The opacity. + /// The effects. + /// Depth of the layer. + internal void DrawTextInternal(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float scale, + float opacity, + SpriteEffects effects, + float layerDepth) + { + DrawSprite( + texture, new RectangleF(position.X, position.Y, scale, scale), true, sourceRectangle, + color, rotation, origin, opacity, effects, layerDepth); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.cs b/src/Exomia.Framework/Graphics/SpriteBatch.cs index 99cc47a1..a1b60c6d 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.cs @@ -15,7 +15,6 @@ using System.IO; using System.Reflection; using System.Runtime.InteropServices; -using System.Text; using System.Threading; using System.Threading.Tasks; using Exomia.Framework.Graphics.Buffers; @@ -31,7 +30,7 @@ namespace Exomia.Framework.Graphics /// /// A sprite batch. This class cannot be inherited. /// - public sealed class SpriteBatch : IDisposable + public sealed partial class SpriteBatch : IDisposable { private const int MAX_BATCH_SIZE = 1 << 13; private const int INITIAL_QUEUE_SIZE = 1 << 7; @@ -280,34 +279,6 @@ public void Resize(float width, float height) }; } - internal struct SpriteInfo - { - public RectangleF Source; - public RectangleF Destination; - public Vector2 Origin; - public float Rotation; - public float Depth; - public SpriteEffects SpriteEffects; - public Color Color; - public float Opacity; - } - - internal readonly struct TextureInfo - { - public readonly ShaderResourceView View; - public readonly int Width; - public readonly int Height; - public readonly long Ptr64; - - public TextureInfo(ShaderResourceView view, int width, int height) - { - View = view; - Width = width; - Height = height; - Ptr64 = view.NativePointer.ToInt64(); - } - } - /// /// Draw batch per texture. /// @@ -492,40 +463,6 @@ private void PrepareForRendering() _context.InputAssembler.SetVertexBuffers(0, _vertexBuffer); } - [StructLayout(LayoutKind.Explicit, Size = VERTEX_STRIDE)] - private struct VertexPositionColorTexture - { - [FieldOffset(0)] - public float X; - - [FieldOffset(4)] - public float Y; - - [FieldOffset(8)] - public float Z; - - [FieldOffset(12)] - public float W; - - [FieldOffset(16)] - public float R; - - [FieldOffset(20)] - public float G; - - [FieldOffset(24)] - public float B; - - [FieldOffset(28)] - public float A; - - [FieldOffset(32)] - public float U; - - [FieldOffset(36)] - public float V; - } - /// /// Updates the vertex from sprite information. /// @@ -607,847 +544,68 @@ private static unsafe void UpdateVertexFromSpriteInfo(ref SpriteInfo } } - #region Drawing - - #region Defaults - - /// - /// Draw rectangle. - /// - /// Destination rectangle. - /// The color. - /// Width of the line. - /// The rotation. - /// The opacity. - /// Depth of the layer. - public void DrawRectangle(in RectangleF destinationRectangle, - in Color color, - float lineWidth, - float rotation, - float opacity, - float layerDepth) - { - DrawRectangle(destinationRectangle, color, lineWidth, rotation, s_vector2Zero, opacity, layerDepth); - } - - /// - /// Draw rectangle. - /// - /// Destination rectangle. - /// The color. - /// Width of the line. - /// The rotation. - /// The origin. - /// The opacity. - /// Depth of the layer. - public void DrawRectangle(in RectangleF destinationRectangle, - in Color color, - float lineWidth, - float rotation, - in Vector2 origin, - float opacity, - float layerDepth) - { - Vector2[] vertex; - - // ReSharper disable once CompareOfFloatsByEqualityOperator - if (rotation == 0.0f) - { - vertex = new[] - { - destinationRectangle.TopLeft, destinationRectangle.TopRight, destinationRectangle.BottomRight, - destinationRectangle.BottomLeft - }; - } - else - { - vertex = new Vector2[4]; - - Vector2 o = origin; - - // ReSharper disable once CompareOfFloatsByEqualityOperator - if (destinationRectangle.Width != 0f) - { - o.X /= destinationRectangle.Width; - } - - // ReSharper disable once CompareOfFloatsByEqualityOperator - if (destinationRectangle.Height != 0f) - { - o.Y /= destinationRectangle.Height; - } - - float cos = (float)Math.Cos(rotation); - float sin = (float)Math.Sin(rotation); - for (int j = 0; j < VERTICES_PER_SPRITE; j++) - { - Vector2 corner = s_cornerOffsets[j]; - float posX = (corner.X - o.X) * destinationRectangle.Width; - float posY = (corner.Y - o.Y) * destinationRectangle.Height; - - vertex[j] = new Vector2( - (destinationRectangle.X + (posX * cos)) - (posY * sin), - destinationRectangle.Y + (posX * sin) + (posY * cos)); - } - } - - DrawPolygon(vertex, color, lineWidth, opacity, layerDepth); - } - - /// - /// Draw fill rectangle. - /// - /// Destination rectangle. - /// The color. - /// Depth of the layer. - public void DrawFillRectangle(in RectangleF destinationRectangle, in Color color, float layerDepth) - { - DrawSprite( - _whiteTexture, destinationRectangle, false, s_nullRectangle, - color, 0.0f, s_vector2Zero, 1.0f, SpriteEffects.None, layerDepth); - } - - /// - /// Draw fill rectangle. - /// - /// Destination rectangle. - /// The color. - /// The opacity. - /// Depth of the layer. - public void DrawFillRectangle(in RectangleF destinationRectangle, - in Color color, - float opacity, - float layerDepth) - { - DrawSprite( - _whiteTexture, destinationRectangle, false, s_nullRectangle, - color, 0.0f, s_vector2Zero, opacity, SpriteEffects.None, layerDepth); - } - - /// - /// Draw fill rectangle. - /// - /// Destination rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// Depth of the layer. - public void DrawFillRectangle(in RectangleF destinationRectangle, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - float layerDepth) - { - DrawSprite( - _whiteTexture, destinationRectangle, false, s_nullRectangle, - color, rotation, origin, opacity, SpriteEffects.None, layerDepth); - } - - /// - /// Draw line. - /// - /// The first point. - /// The second point. - /// The color. - /// Width of the line. - /// The opacity. - /// Depth of the layer. - public void DrawLine(in Vector2 point1, - in Vector2 point2, - in Color color, - float lineWidth, - float opacity, - float layerDepth) - { - DrawLine(point1, point2, color, lineWidth, opacity, 1.0f, layerDepth); - } - - /// - /// Draw line. - /// - /// The first point. - /// The second point. - /// The color. - /// Width of the line. - /// The opacity. - /// The length factor. - /// Depth of the layer. - public void DrawLine(in Vector2 point1, - in Vector2 point2, - in Color color, - float lineWidth, - float opacity, - float lengthFactor, - float layerDepth) - { - DrawSprite( - _whiteTexture, new RectangleF( - point1.X, point1.Y, Vector2.Distance(point1, point2) * lengthFactor, lineWidth), false, - s_nullRectangle, color, (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X), - s_vector2Zero, opacity, SpriteEffects.None, layerDepth); - } - - /// - /// Draw polygon. - /// - /// The vertex. - /// The color. - /// Width of the line. - /// The opacity. - /// Depth of the layer. - public void DrawPolygon(Vector2[] vertex, in Color color, float lineWidth, float opacity, float layerDepth) - { - if (vertex.Length > 1) - { - int l = vertex.Length - 1; - for (int i = 0; i < l; i++) - { - DrawLine(vertex[i], vertex[i + 1], color, lineWidth, opacity, layerDepth); - } - DrawLine(vertex[l], vertex[0], color, lineWidth, opacity, layerDepth); - } - } - - /// - /// Draw circle. - /// - /// The center. - /// The radius. - /// The color. - /// Width of the line. - /// The opacity. - /// The segments. - /// Depth of the layer. - public void DrawCircle(in Vector2 center, - float radius, - in Color color, - float lineWidth, - float opacity, - int segments, - float layerDepth) - { - DrawCircle(center, radius, 0, MathUtil.TwoPi, color, lineWidth, opacity, segments, layerDepth); - } - - /// - /// Draw circle. - /// - /// The center. - /// The radius. - /// The start. - /// The end. - /// The color. - /// Width of the line. - /// The opacity. - /// The segments. - /// Depth of the layer. - public void DrawCircle(in Vector2 center, - float radius, - float start, - float end, - in Color color, - float lineWidth, - float opacity, - int segments, - float layerDepth) - { - Vector2[] vertex = new Vector2[segments]; - - float increment = (end - start) / segments; - float theta = start; - - for (int i = 0; i < segments; i++) - { - vertex[i].X = center.X + (radius * (float)Math.Cos(theta)); - vertex[i].Y = center.Y + (radius * (float)Math.Sin(theta)); - theta += increment; - } - - DrawPolygon(vertex, color, lineWidth, opacity, layerDepth); - } - - #endregion - - #region Texture - - /// - /// Draws. - /// - /// The texture. - /// The position. - /// The color. - public void Draw(Texture texture, in Vector2 position, in Color color) - { - DrawSprite( - texture, new RectangleF(position.X, position.Y, 1f, 1f), true, s_nullRectangle, - color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); - } - - /// - /// Draws. - /// - /// The texture. - /// Destination rectangle. - /// The color. - public void Draw(Texture texture, in RectangleF destinationRectangle, in Color color) - { - DrawSprite( - texture, destinationRectangle, false, s_nullRectangle, - color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); - } - - /// - /// Draws. - /// - /// The texture. - /// The position. - /// Source rectangle. - /// The color. - public void Draw(Texture texture, in Vector2 position, in Rectangle? sourceRectangle, in Color color) - { - DrawSprite( - texture, new RectangleF(position.X, position.Y, 1f, 1f), true, sourceRectangle, - color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); - } - - /// - /// Draws. - /// - /// The texture. - /// Destination rectangle. - /// Source rectangle. - /// The color. - public void Draw(Texture texture, - in RectangleF destinationRectangle, - in Rectangle? sourceRectangle, - in Color color) - { - DrawSprite( - texture, destinationRectangle, false, sourceRectangle, - color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); - } - - /// - /// Draws. - /// - /// The texture. - /// Destination rectangle. - /// Source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. - public void Draw(Texture texture, - in RectangleF destinationRectangle, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) - { - DrawSprite( - texture, destinationRectangle, false, sourceRectangle, - color, rotation, origin, opacity, effects, layerDepth); - } - - /// - /// Draws. - /// - /// The texture. - /// The position. - /// Source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The scale. - /// The opacity. - /// The effects. - /// Depth of the layer. - public void Draw(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float scale, - float opacity, - SpriteEffects effects, - float layerDepth) - { - DrawSprite( - texture, new RectangleF(position.X, position.Y, scale, scale), true, sourceRectangle, - color, rotation, origin, opacity, effects, layerDepth); - } - - /// - /// Draws. - /// - /// The texture. - /// The position. - /// Source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The scale. - /// The opacity. - /// The effects. - /// Depth of the layer. - public void Draw(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - in Vector2 scale, - float opacity, - SpriteEffects effects, - float layerDepth) + internal struct SpriteInfo { - DrawSprite( - texture, new RectangleF(position.X, position.Y, scale.X, scale.Y), true, sourceRectangle, - color, rotation, origin, opacity, effects, layerDepth); + public RectangleF Source; + public RectangleF Destination; + public Vector2 Origin; + public float Rotation; + public float Depth; + public SpriteEffects SpriteEffects; + public Color Color; + public float Opacity; } - /// - /// Draw sprite. - /// - /// - /// Thrown when one or more required arguments are - /// null. - /// - /// Thrown when the requested operation is invalid. - /// The texture. - /// Destination for the. - /// True to scale destination. - /// Source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// The depth. - private unsafe void DrawSprite(Texture texture, - in RectangleF destination, - bool scaleDestination, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float depth) + internal readonly struct TextureInfo { - if (!_isBeginCalled) - { - throw new InvalidOperationException("Begin must be called before draw"); - } - - if (texture.TexturePointer == IntPtr.Zero) - { - throw new ArgumentNullException(nameof(texture)); - } - - if (_spriteQueueCount >= _spriteQueue.Length) - { - bool lockTaken = false; - try - { - _spinLock.Enter(ref lockTaken); - - int size = _spriteQueue.Length * 2; - _sortIndices = new int[size]; - _sortedSprites = new SpriteInfo[size]; - Array.Resize(ref _spriteQueue, size); - Array.Resize(ref _spriteTextures, size); - } - finally - { - if (lockTaken) - { - _spinLock.Exit(false); - } - } - } - - if (!_textureInfos.TryGetValue(texture.TexturePointer, out TextureInfo textureInfo)) - { - bool lockTaken = false; - try - { - _spinLock.Enter(ref lockTaken); - if (!_textureInfos.TryGetValue(texture.TexturePointer, out textureInfo)) - { - textureInfo = new TextureInfo(texture.TextureView, texture.Width, texture.Height); - _textureInfos.Add(texture.TexturePointer, textureInfo); - } - } - finally - { - if (lockTaken) - { - _spinLock.Exit(false); - } - } - } + public readonly ShaderResourceView View; + public readonly int Width; + public readonly int Height; + public readonly long Ptr64; - int spriteQueueCount = Interlocked.Increment(ref _spriteQueueCount) - 1; - fixed (SpriteInfo* spriteInfo = &_spriteQueue[spriteQueueCount]) + public TextureInfo(ShaderResourceView view, int width, int height) { - float width; - float height; - if (sourceRectangle.HasValue) - { - Rectangle rectangle = sourceRectangle.Value; - spriteInfo->Source.X = rectangle.X; - spriteInfo->Source.Y = rectangle.Y; - width = rectangle.Width; - height = rectangle.Height; - } - else - { - spriteInfo->Source.X = 0; - spriteInfo->Source.Y = 0; - width = texture.Width; - height = texture.Height; - } - - spriteInfo->Source.Width = width; - spriteInfo->Source.Height = height; - - spriteInfo->Destination.X = destination.X; - spriteInfo->Destination.Y = destination.Y; - - if (scaleDestination) - { - spriteInfo->Destination.Width = destination.Width * width; - spriteInfo->Destination.Height = destination.Height * height; - } - else - { - spriteInfo->Destination.Width = destination.Width; - spriteInfo->Destination.Height = destination.Height; - } - - if (spriteInfo->Destination.Width < 0) - { - spriteInfo->Destination.X += spriteInfo->Destination.Width; - spriteInfo->Destination.Width = -spriteInfo->Destination.Width; - } - - if (spriteInfo->Destination.Height < 0) - { - spriteInfo->Destination.Y += spriteInfo->Destination.Height; - spriteInfo->Destination.Height = -spriteInfo->Destination.Height; - } - - spriteInfo->Origin = origin; - spriteInfo->Rotation = rotation; - spriteInfo->Depth = depth; - spriteInfo->SpriteEffects = effects; - spriteInfo->Color = color; - spriteInfo->Opacity = opacity; + View = view; + Width = width; + Height = height; + Ptr64 = view.NativePointer.ToInt64(); } - - _spriteTextures[spriteQueueCount] = textureInfo; - } - - #endregion - - #region SpiteFont - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// Depth of the layer. - public void DrawText(SpriteFont font, string text, in Vector2 position, in Color color, float layerDepth) - { - font.Draw( - DrawTextInternal, text, position, - color, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); } - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. - /// Depth of the layer. - public void DrawText(SpriteFont font, - string text, - in Vector2 position, - in Color color, - float rotation, - float layerDepth) + [StructLayout(LayoutKind.Explicit, Size = VERTEX_STRIDE)] + private struct VertexPositionColorTexture { - font.Draw( - DrawTextInternal, text, position, - color, rotation, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); - } + [FieldOffset(0)] + public float X; - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. - public void DrawText(SpriteFont font, - string text, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, position, - color, rotation, origin, opacity, effects, layerDepth); - } + [FieldOffset(4)] + public float Y; - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The start. - /// The end. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. - public void DrawText(SpriteFont font, - string text, - int start, - int end, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, start, end, position, - color, rotation, origin, opacity, effects, layerDepth); - } + [FieldOffset(8)] + public float Z; - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The start. - /// The end. - /// The position. - /// The dimension. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. - public void DrawText(SpriteFont font, - string text, - int start, - int end, - in Vector2 position, - in Size2F dimension, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, start, end, position, dimension, - color, rotation, origin, opacity, effects, layerDepth); - } + [FieldOffset(12)] + public float W; - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// Depth of the layer. - public void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, in Color color, float layerDepth) - { - font.Draw( - DrawTextInternal, text, position, - color, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); - } + [FieldOffset(16)] + public float R; - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. - /// Depth of the layer. - public void DrawText(SpriteFont font, - StringBuilder text, - in Vector2 position, - in Color color, - float rotation, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, position, - color, rotation, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); - } + [FieldOffset(20)] + public float G; - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. - public void DrawText(SpriteFont font, - StringBuilder text, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, position, - color, rotation, origin, opacity, effects, layerDepth); - } + [FieldOffset(24)] + public float B; - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The start. - /// The end. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. - public void DrawText(SpriteFont font, - StringBuilder text, - int start, - int end, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, start, end, position, - color, rotation, origin, opacity, effects, layerDepth); - } + [FieldOffset(28)] + public float A; - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The start. - /// The end. - /// The position. - /// The dimension. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. - public void DrawText(SpriteFont font, - StringBuilder text, - int start, - int end, - in Vector2 position, - in Size2F dimension, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, start, end, position, dimension, - color, rotation, origin, opacity, effects, layerDepth); - } + [FieldOffset(32)] + public float U; - /// - /// Draw text internal. - /// - /// The texture. - /// The position. - /// Source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The scale. - /// The opacity. - /// The effects. - /// Depth of the layer. - internal void DrawTextInternal(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float scale, - float opacity, - SpriteEffects effects, - float layerDepth) - { - DrawSprite( - texture, new RectangleF(position.X, position.Y, scale, scale), true, sourceRectangle, - color, rotation, origin, opacity, effects, layerDepth); + [FieldOffset(36)] + public float V; } - #endregion - - #endregion - #region IDisposable Support /// diff --git a/src/Exomia.Framework/Graphics/SpriteFont.ContentSerializationReader.cs b/src/Exomia.Framework/Graphics/SpriteFont.ContentSerializationReader.cs index 757c9196..130d2a2c 100644 --- a/src/Exomia.Framework/Graphics/SpriteFont.ContentSerializationReader.cs +++ b/src/Exomia.Framework/Graphics/SpriteFont.ContentSerializationReader.cs @@ -36,7 +36,7 @@ public override SpriteFont ReadContext(ContentSerializationContext context) }; } } - + sealed class SpriteFontGlyphCR : ContentSerializationReader { /// @@ -52,6 +52,7 @@ public override SpriteFont.Glyph ReadContext(ContentSerializationContext context }; } } + sealed class SpriteFontKerningCR : ContentSerializationReader { /// diff --git a/src/Exomia.Framework/Graphics/SpriteFont.ContentSerializationWriter.cs b/src/Exomia.Framework/Graphics/SpriteFont.ContentSerializationWriter.cs index 0ef1f8b2..0b921186 100644 --- a/src/Exomia.Framework/Graphics/SpriteFont.ContentSerializationWriter.cs +++ b/src/Exomia.Framework/Graphics/SpriteFont.ContentSerializationWriter.cs @@ -36,7 +36,7 @@ public override void WriteContext(ContentSerializationContext context, SpriteFon context.Set(nameof(SpriteFont.ImageData), Convert.ToBase64String(obj.ImageData)); } } - + sealed class SpriteFontGlyphCW : ContentSerializationWriter { /// @@ -49,7 +49,7 @@ public override void WriteContext(ContentSerializationContext context, SpriteFon context.Set(nameof(SpriteFont.Glyph.XAdvance), obj.XAdvance); } } - + sealed class SpriteFontKerningCW : ContentSerializationWriter { /// diff --git a/src/Exomia.Framework/Graphics/SpriteFont.cs b/src/Exomia.Framework/Graphics/SpriteFont.cs index a7460e8b..e95ff29c 100644 --- a/src/Exomia.Framework/Graphics/SpriteFont.cs +++ b/src/Exomia.Framework/Graphics/SpriteFont.cs @@ -180,6 +180,30 @@ public SpriteFont() Dispose(false); } + /// + /// Draw font. + /// + /// The texture. + /// The position. + /// Source rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The scale. + /// The opacity. + /// The effects. + /// Depth of the layer. + internal delegate void DrawFont(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float scale, + float opacity, + SpriteEffects effects, + float layerDepth); + /// /// A glyph. /// @@ -234,30 +258,6 @@ public struct Kerning public int Offset; } - /// - /// Draw font. - /// - /// The texture. - /// The position. - /// Source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The scale. - /// The opacity. - /// The effects. - /// Depth of the layer. - internal delegate void DrawFont(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float scale, - float opacity, - SpriteEffects effects, - float layerDepth); - #region String /// diff --git a/tools/Exomia.Framework.ContentManager/MainForm.cs b/tools/Exomia.Framework.ContentManager/MainForm.cs index 81d1394f..97e86dd4 100644 --- a/tools/Exomia.Framework.ContentManager/MainForm.cs +++ b/tools/Exomia.Framework.ContentManager/MainForm.cs @@ -152,29 +152,6 @@ private void MainForm_FormClosing(object sender, FormClosingEventArgs e) _projectFile = null; } - private class NodeSorter : IComparer - { - // Compare the length of the strings, or the strings - // themselves, if they are the same length. - public int Compare(object x, object y) - { - if (x is TreeNode tx && y is TreeNode ty) - { - if (tx.Name.StartsWith(FOLDER_KEY_PREFIX) && !ty.Name.StartsWith(FOLDER_KEY_PREFIX)) - { - return -1; - } - if (!tx.Name.StartsWith(FOLDER_KEY_PREFIX) && ty.Name.StartsWith(FOLDER_KEY_PREFIX)) - { - return 1; - } - return string.Compare(tx.Text, ty.Text, StringComparison.InvariantCultureIgnoreCase); - } - - return 0; - } - } - private static bool IsNumber(object? value) { return value is sbyte @@ -197,5 +174,28 @@ private static void ForAll(Action action, params T[] items) action(item); } } + + private class NodeSorter : IComparer + { + // Compare the length of the strings, or the strings + // themselves, if they are the same length. + public int Compare(object x, object y) + { + if (x is TreeNode tx && y is TreeNode ty) + { + if (tx.Name.StartsWith(FOLDER_KEY_PREFIX) && !ty.Name.StartsWith(FOLDER_KEY_PREFIX)) + { + return -1; + } + if (!tx.Name.StartsWith(FOLDER_KEY_PREFIX) && ty.Name.StartsWith(FOLDER_KEY_PREFIX)) + { + return 1; + } + return string.Compare(tx.Text, ty.Text, StringComparison.InvariantCultureIgnoreCase); + } + + return 0; + } + } } } \ No newline at end of file From c877b7fd7e514e3db75776725cced4628eb68636 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Wed, 11 Nov 2020 12:02:49 +0100 Subject: [PATCH 19/44] changed input pipeline return type from bool to "EventAction" --- .../Game/RenderForm.Events.cs | 36 +++++++++++++------ src/Exomia.Framework/Input/InputState.cs | 17 +++++++++ src/Exomia.Framework/Input/KeyEventHandler.cs | 12 +++---- .../Input/MouseEventHandler.cs | 4 +-- 4 files changed, 50 insertions(+), 19 deletions(-) create mode 100644 src/Exomia.Framework/Input/InputState.cs diff --git a/src/Exomia.Framework/Game/RenderForm.Events.cs b/src/Exomia.Framework/Game/RenderForm.Events.cs index 6387752a..d5515971 100644 --- a/src/Exomia.Framework/Game/RenderForm.Events.cs +++ b/src/Exomia.Framework/Game/RenderForm.Events.cs @@ -167,7 +167,11 @@ private unsafe IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lPara MouseButtons mouseButtons = (MouseButtons)LowWord(m.wParam); for (int i = 0; i < _mouseMovePipe.Count; i++) { - if (_mouseMovePipe[i].Invoke(new MouseEventArgs(x, y, mouseButtons, 0, 0))) { break; } + if (_mouseMovePipe[i].Invoke(new MouseEventArgs(x, y, mouseButtons, 0, 0)) == + EventAction.StopPropagation) + { + break; + } } return IntPtr.Zero; } @@ -179,7 +183,8 @@ private unsafe IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lPara int wheelDelta = HighWord(m.wParam); for (int i = 0; i < _mouseWheelPipe.Count; i++) { - if (_mouseWheelPipe[i].Invoke(new MouseEventArgs(x, y, mouseButtons, 2, wheelDelta))) + if (_mouseWheelPipe[i].Invoke(new MouseEventArgs(x, y, mouseButtons, 2, wheelDelta)) == + EventAction.StopPropagation) { break; } @@ -197,7 +202,11 @@ private unsafe IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lPara MouseButtons mouseButtons = (MouseButtons)LowWord(m.wParam); for (int i = 0; i < _mouseClickPipe.Count; i++) { - if (_mouseClickPipe[i].Invoke(new MouseEventArgs(x, y, mouseButtons, 2, 0))) { break; } + if (_mouseClickPipe[i].Invoke(new MouseEventArgs(x, y, mouseButtons, 2, 0)) == + EventAction.StopPropagation) + { + break; + } } return IntPtr.Zero; } @@ -210,7 +219,7 @@ private void RawKeyMessage(ref Message m) { for (int i = 0; i < _rawKeyPipe.Count; i++) { - if (_rawKeyPipe[i].Invoke(m)) + if (_rawKeyPipe[i].Invoke(m) == EventAction.StopPropagation) { break; } @@ -236,7 +245,7 @@ private void RawKeyMessage(ref Message m) } for (int i = 0; i < _keyDownPipe.Count; i++) { - if (_keyDownPipe[i].Invoke(vKey, _keyModifier)) + if (_keyDownPipe[i].Invoke(vKey, _keyModifier) == EventAction.StopPropagation) { break; } @@ -258,7 +267,7 @@ private void RawKeyMessage(ref Message m) } for (int i = 0; i < _keyUpPipe.Count; i++) { - if (_keyUpPipe[i].Invoke(vKey, _keyModifier)) + if (_keyUpPipe[i].Invoke(vKey, _keyModifier) == EventAction.StopPropagation) { break; } @@ -268,7 +277,7 @@ private void RawKeyMessage(ref Message m) case WM.CHAR: for (int i = 0; i < _keyPressPipe.Count; i++) { - if (_keyPressPipe[i].Invoke((char)vKey)) + if (_keyPressPipe[i].Invoke((char)vKey) == EventAction.StopPropagation) { break; } @@ -285,7 +294,7 @@ private void RawMouseDown(ref Message m, MouseButtons buttons) int high = HighWord(m.lParam); for (int i = 0; i < _mouseDownPipe.Count; i++) { - if (_mouseDownPipe[i].Invoke(new MouseEventArgs(low, high, buttons, 1, 0))) + if (_mouseDownPipe[i].Invoke(new MouseEventArgs(low, high, buttons, 1, 0)) == EventAction.StopPropagation) { break; } @@ -302,7 +311,8 @@ private void RawMouseUp(ref Message m, MouseButtons buttons) int clicks = (_state & 0x4000000) == 0x4000000 ? 2 : 1; for (int i = 0; i < _mouseClickPipe.Count; i++) { - if (_mouseClickPipe[i].Invoke(new MouseEventArgs(low, high, buttons, clicks, 0))) + if (_mouseClickPipe[i].Invoke(new MouseEventArgs(low, high, buttons, clicks, 0)) == + EventAction.StopPropagation) { break; } @@ -311,7 +321,10 @@ private void RawMouseUp(ref Message m, MouseButtons buttons) _state &= ~0xC000000; for (int i = 0; i < _mouseUpPipe.Count; i++) { - if (_mouseUpPipe[i].Invoke(new MouseEventArgs(low, high, buttons, 1, 0))) { break; } + if (_mouseUpPipe[i].Invoke(new MouseEventArgs(low, high, buttons, 1, 0)) == EventAction.StopPropagation) + { + break; + } } } @@ -346,7 +359,8 @@ private void RawMouseInput(in RAWINPUTMOUSE e) } for (int i = 0; i < _mouseRawInputPipe.Count; i++) { - if (_mouseRawInputPipe[i].Invoke(new MouseEventArgs(e.LastX, e.LastY, buttons, clicks, e.ButtonData))) + if (_mouseRawInputPipe[i].Invoke(new MouseEventArgs(e.LastX, e.LastY, buttons, clicks, e.ButtonData)) == + EventAction.StopPropagation) { break; } diff --git a/src/Exomia.Framework/Input/InputState.cs b/src/Exomia.Framework/Input/InputState.cs new file mode 100644 index 00000000..e2baaa1b --- /dev/null +++ b/src/Exomia.Framework/Input/InputState.cs @@ -0,0 +1,17 @@ +namespace Exomia.Framework.Input +{ + /// + /// Values that represent EventAction. + /// + public enum EventAction + { + /// + /// An enum constant representing the continue option. + /// + Continue = 0, + /// + /// An enum constant representing the stop propagation option. + /// + StopPropagation = 1, + } +} diff --git a/src/Exomia.Framework/Input/KeyEventHandler.cs b/src/Exomia.Framework/Input/KeyEventHandler.cs index ac1fe9b7..28b18948 100644 --- a/src/Exomia.Framework/Input/KeyEventHandler.cs +++ b/src/Exomia.Framework/Input/KeyEventHandler.cs @@ -18,25 +18,25 @@ namespace Exomia.Framework.Input /// The key value. /// The modifiers. /// - /// true if the key event was handled; false otherwise. + /// An . /// - public delegate bool KeyEventHandler(int keyValue, KeyModifier modifiers); + public delegate EventAction KeyEventHandler(int keyValue, KeyModifier modifiers); /// /// Delegate for handling key press events. /// /// The key. /// - /// true if the key press event was handled; false otherwise. + /// An . /// - public delegate bool KeyPressEventHandler(char key); + public delegate EventAction KeyPressEventHandler(char key); /// /// Delegate for handling raw key events. /// /// The message. /// - /// true if the message event was handled; false otherwise. + /// An . /// - public delegate bool RawKeyEventHandler(in Message message); + public delegate EventAction RawKeyEventHandler(in Message message); } \ No newline at end of file diff --git a/src/Exomia.Framework/Input/MouseEventHandler.cs b/src/Exomia.Framework/Input/MouseEventHandler.cs index a233656b..39401528 100644 --- a/src/Exomia.Framework/Input/MouseEventHandler.cs +++ b/src/Exomia.Framework/Input/MouseEventHandler.cs @@ -15,7 +15,7 @@ namespace Exomia.Framework.Input /// /// In mouse event information. /// - /// true if the mouse event was handled; false otherwise. + /// An . /// - public delegate bool MouseEventHandler(in MouseEventArgs mouseEventArgs); + public delegate EventAction MouseEventHandler(in MouseEventArgs mouseEventArgs); } \ No newline at end of file From e2e4135c92c78de3e33d4667bca4d5b5561a8a9c Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Wed, 11 Nov 2020 12:26:44 +0100 Subject: [PATCH 20/44] angle between two vectors changed --- .../Extensions/Vector/Vector2Extensions.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Exomia.Framework/Mathematics/Extensions/Vector/Vector2Extensions.cs b/src/Exomia.Framework/Mathematics/Extensions/Vector/Vector2Extensions.cs index 163d32bf..da2c0cc0 100644 --- a/src/Exomia.Framework/Mathematics/Extensions/Vector/Vector2Extensions.cs +++ b/src/Exomia.Framework/Mathematics/Extensions/Vector/Vector2Extensions.cs @@ -20,22 +20,22 @@ namespace Exomia.Framework.Mathematics.Extensions.Vector public static class Vector2Extensions { /// - /// calculate the angle between two vectors. + /// Calculate the angle between two vectors. /// /// this vec1. /// vec2. /// - /// angle between the two vectors in radians. + /// The angle between the two vectors in radians. /// public static double AngleBetween(this Vector2 vec1, in Vector2 vec2) { - float scalar = (vec1.X * vec2.X) + (vec1.Y * vec2.Y); - float length = vec1.Length() * vec2.Length(); - return Math.Cos(scalar / length); + return Math.Atan2( + (vec1.X * vec2.Y) - (vec2.X * vec1.Y), + (vec1.X * vec2.X) + (vec1.Y * vec2.Y)); } /// - /// calculates the horizontal angle of a vector2. + /// Calculates the horizontal angle of a vector2. /// /// this vec. /// @@ -48,7 +48,7 @@ public static double AngleHorizontal(this Vector2 vec) } /// - /// calculates the vertical angle of a vector2. + /// Calculates the vertical angle of a vector2. /// /// this vec. /// @@ -61,7 +61,7 @@ public static double AngleVertical(this Vector2 vec) } /// - /// rotate a vector by an angle (in radian) + /// Rotate a vector by an angle (in radian) /// /// this vec. /// angle. @@ -76,7 +76,7 @@ public static Vector2 Rotate(this Vector2 vec, double angle) } /// - /// transforms the vector with a transform matrix. + /// Transforms the vector with a transform matrix. /// /// this vec. /// transform. From 1906b6d9698d1dbfde58b39354ddbac541930427 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Wed, 11 Nov 2020 12:35:38 +0100 Subject: [PATCH 21/44] summary update --- .../Extensions/Vector/Vector2Extensions.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Exomia.Framework/Mathematics/Extensions/Vector/Vector2Extensions.cs b/src/Exomia.Framework/Mathematics/Extensions/Vector/Vector2Extensions.cs index da2c0cc0..099f84dc 100644 --- a/src/Exomia.Framework/Mathematics/Extensions/Vector/Vector2Extensions.cs +++ b/src/Exomia.Framework/Mathematics/Extensions/Vector/Vector2Extensions.cs @@ -22,24 +22,24 @@ public static class Vector2Extensions /// /// Calculate the angle between two vectors. /// - /// this vec1. - /// vec2. + /// This . + /// The . /// /// The angle between the two vectors in radians. /// public static double AngleBetween(this Vector2 vec1, in Vector2 vec2) { return Math.Atan2( - (vec1.X * vec2.Y) - (vec2.X * vec1.Y), + (vec1.X * vec2.Y) - (vec2.X * vec1.Y), (vec1.X * vec2.X) + (vec1.Y * vec2.Y)); } /// /// Calculates the horizontal angle of a vector2. /// - /// this vec. + /// This . /// - /// angle horizontal. + /// The angle horizontal. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double AngleHorizontal(this Vector2 vec) @@ -48,11 +48,11 @@ public static double AngleHorizontal(this Vector2 vec) } /// - /// Calculates the vertical angle of a vector2. + /// Calculates the vertical angle of a . /// - /// this vec. + /// This . /// - /// angle vertical. + /// The angle vertical. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double AngleVertical(this Vector2 vec) @@ -61,12 +61,12 @@ public static double AngleVertical(this Vector2 vec) } /// - /// Rotate a vector by an angle (in radian) + /// Rotate a by an angle (in radian) /// - /// this vec. + /// This . /// angle. /// - /// new rotated vector2. + /// The new rotated . /// public static Vector2 Rotate(this Vector2 vec, double angle) { @@ -76,12 +76,12 @@ public static Vector2 Rotate(this Vector2 vec, double angle) } /// - /// Transforms the vector with a transform matrix. + /// Transforms the with a transform . /// /// this vec. /// transform. /// - /// new vector2. + /// the new . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector2 Transform(this Vector2 vec, in Matrix transform) From bdbd14d9081931d91f8811eda3509f2366b1d68b Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Wed, 11 Nov 2020 13:48:14 +0100 Subject: [PATCH 22/44] fixed not fully updated EventAction changes --- .../Game/Camera/Controller/RotationController.cs | 4 ++-- .../Camera/Controller/TranslationKeyboardController.cs | 8 ++++---- .../Mathematics/Extensions/Vector/Vector2Extensions.cs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Exomia.Framework/Game/Camera/Controller/RotationController.cs b/src/Exomia.Framework/Game/Camera/Controller/RotationController.cs index c18c3252..7a05858d 100644 --- a/src/Exomia.Framework/Game/Camera/Controller/RotationController.cs +++ b/src/Exomia.Framework/Game/Camera/Controller/RotationController.cs @@ -99,14 +99,14 @@ void IInputHandler.UnregisterInput(IInputDevice device) device.RegisterRawMouseInput(CameraOnRawMouseInput); } - private bool CameraOnRawMouseInput(in MouseEventArgs mouseEventArgs) + private EventAction CameraOnRawMouseInput(in MouseEventArgs mouseEventArgs) { if (mouseEventArgs.X != 0 || mouseEventArgs.Y != 0) { Interlocked.Add(ref _x, mouseEventArgs.X); Interlocked.Add(ref _y, mouseEventArgs.Y); } - return false; + return EventAction.Continue; } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Game/Camera/Controller/TranslationKeyboardController.cs b/src/Exomia.Framework/Game/Camera/Controller/TranslationKeyboardController.cs index 80fa5507..70c4b04d 100644 --- a/src/Exomia.Framework/Game/Camera/Controller/TranslationKeyboardController.cs +++ b/src/Exomia.Framework/Game/Camera/Controller/TranslationKeyboardController.cs @@ -99,16 +99,16 @@ void IUpdateableCameraComponent.Update(GameTime gameTime, ICamera camera) } } - private bool CameraOnKeyDown(int keyValue, KeyModifier modifiers) + private EventAction CameraOnKeyDown(int keyValue, KeyModifier modifiers) { _keysDown.Add(keyValue); - return false; + return EventAction.Continue; } - private bool CameraOnKeyUp(int keyValue, KeyModifier modifiers) + private EventAction CameraOnKeyUp(int keyValue, KeyModifier modifiers) { _keysDown.Remove(keyValue); - return false; + return EventAction.Continue; } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Mathematics/Extensions/Vector/Vector2Extensions.cs b/src/Exomia.Framework/Mathematics/Extensions/Vector/Vector2Extensions.cs index 099f84dc..fb1b1164 100644 --- a/src/Exomia.Framework/Mathematics/Extensions/Vector/Vector2Extensions.cs +++ b/src/Exomia.Framework/Mathematics/Extensions/Vector/Vector2Extensions.cs @@ -15,7 +15,7 @@ namespace Exomia.Framework.Mathematics.Extensions.Vector { /// - /// Vector2Extensions static class. + /// A vector 2 extensions class. /// public static class Vector2Extensions { From e64fd55c800f5077180833196212993a42351268 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Wed, 11 Nov 2020 14:35:58 +0100 Subject: [PATCH 23/44] added angle to method --- .../Extensions/Vector/Vector2Extensions.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Exomia.Framework/Mathematics/Extensions/Vector/Vector2Extensions.cs b/src/Exomia.Framework/Mathematics/Extensions/Vector/Vector2Extensions.cs index fb1b1164..913fdc05 100644 --- a/src/Exomia.Framework/Mathematics/Extensions/Vector/Vector2Extensions.cs +++ b/src/Exomia.Framework/Mathematics/Extensions/Vector/Vector2Extensions.cs @@ -19,6 +19,19 @@ namespace Exomia.Framework.Mathematics.Extensions.Vector /// public static class Vector2Extensions { + /// + /// Calculate the angle from the anchor point to another point vector. + /// + /// This anchor . + /// The point . + /// + /// The angle from anchor vector to the point vector in radians. + /// + public static double AngleTo(this Vector2 anchor, in Vector2 point) + { + return Math.Atan2(point.Y - anchor.Y, point.X - anchor.X); + } + /// /// Calculate the angle between two vectors. /// @@ -35,7 +48,7 @@ public static double AngleBetween(this Vector2 vec1, in Vector2 vec2) } /// - /// Calculates the horizontal angle of a vector2. + /// Calculates the horizontal angle of a . /// /// This . /// From 2adee8e3c3930ea95c5099d8210db7f86d29d7c1 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Wed, 11 Nov 2020 15:54:42 +0100 Subject: [PATCH 24/44] added possibility to set the ortho projection matrix centered in the viewport --- src/Exomia.Framework/Graphics/SpriteBatch.cs | 71 +++++++++++--------- 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.cs b/src/Exomia.Framework/Graphics/SpriteBatch.cs index a1b60c6d..6df60af8 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.cs @@ -61,13 +61,13 @@ private static readonly Vector2[] private readonly VertexBuffer _vertexBuffer; private readonly ConstantBuffer _perFrameBuffer; - private readonly Shader.Shader _shader; - private readonly PixelShader _pixelShader; - private readonly VertexShader _vertexShader; - private readonly Texture _whiteTexture; - - private BlendState? _defaultBlendState, _blendState; - private DepthStencilState? _defaultDepthStencilState, _depthStencilState; + private readonly Shader.Shader _shader; + private readonly PixelShader _pixelShader; + private readonly VertexShader _vertexShader; + private readonly Texture _whiteTexture; + private readonly bool _center; + private BlendState? _defaultBlendState, _blendState; + private DepthStencilState? _defaultDepthStencilState, _depthStencilState; private RasterizerState? _defaultRasterizerState, _defaultRasterizerScissorEnabledState, @@ -116,32 +116,36 @@ static SpriteBatch() /// /// Initializes a new instance of the class. /// - /// - /// Thrown when one or more arguments have unsupported or - /// illegal values. - /// - /// Zero-based index of the device. - /// (Optional) The sort algorithm. - public SpriteBatch(IGraphicsDevice iDevice, SpriteSortAlgorithm sortAlgorithm = SpriteSortAlgorithm.MergeSort) + /// The graphics device. + /// (Optional) True to center the coordinate system in the viewport. + /// (Optional) The sort algorithm. + /// Thrown when one or more arguments have unsupported or + /// illegal values. + /// Thrown when a value was unexpectedly null. + public SpriteBatch(IGraphicsDevice graphicsDevice, + bool center = false, + SpriteSortAlgorithm sortAlgorithm = SpriteSortAlgorithm.MergeSort) { - _device = iDevice.Device; - _context = iDevice.DeviceContext; - + _device = graphicsDevice.Device; + _context = graphicsDevice.DeviceContext; + + _center = center; + _spriteSort = sortAlgorithm switch { SpriteSortAlgorithm.MergeSort => new SpriteMergeSort(), _ => throw new ArgumentException($"invalid sort algorithm ({sortAlgorithm})", nameof(sortAlgorithm)) }; + + _defaultBlendState = graphicsDevice.BlendStates.AlphaBlend; + _defaultSamplerState = graphicsDevice.SamplerStates.LinearWrap; + _defaultDepthStencilState = graphicsDevice.DepthStencilStates.None; + _defaultRasterizerState = graphicsDevice.RasterizerStates.CullBackDepthClipOff; + _defaultRasterizerScissorEnabledState = graphicsDevice.RasterizerStates.CullBackDepthClipOffScissorEnabled; - _defaultBlendState = iDevice.BlendStates.AlphaBlend; - _defaultSamplerState = iDevice.SamplerStates.LinearWrap; - _defaultDepthStencilState = iDevice.DepthStencilStates.None; - _defaultRasterizerState = iDevice.RasterizerStates.CullBackDepthClipOff; - _defaultRasterizerScissorEnabledState = iDevice.RasterizerStates.CullBackDepthClipOffScissorEnabled; + _whiteTexture = graphicsDevice.Textures.White; - _whiteTexture = iDevice.Textures.White; - - _indexBuffer = IndexBuffer.Create(iDevice, s_indices); + _indexBuffer = IndexBuffer.Create(graphicsDevice, s_indices); Assembly assembly = Assembly.GetExecutingAssembly(); using (Stream stream = @@ -149,17 +153,17 @@ public SpriteBatch(IGraphicsDevice iDevice, SpriteSortAlgorithm sortAlgorithm = throw new NullReferenceException($"{assembly.GetName().Name}.{Shaders.POSITION_COLOR_TEXTURE}")) { Shader.Shader.Group group = - (_shader = ShaderFileLoader.FromStream(iDevice, stream) ?? + (_shader = ShaderFileLoader.FromStream(graphicsDevice, stream) ?? throw new NullReferenceException(nameof(ShaderFileLoader.FromStream)))["DEFAULT"]; _vertexShader = group; _pixelShader = group; - _vertexInputLayout = group.CreateInputLayout(iDevice, Shader.Shader.Type.VertexShader); + _vertexInputLayout = group.CreateInputLayout(graphicsDevice, Shader.Shader.Type.VertexShader); } - _vertexBuffer = VertexBuffer.Create(iDevice, MAX_VERTEX_COUNT); - _perFrameBuffer = ConstantBuffer.Create(iDevice); + _vertexBuffer = VertexBuffer.Create(graphicsDevice, MAX_VERTEX_COUNT); + _perFrameBuffer = ConstantBuffer.Create(graphicsDevice); _sortIndices = new int[MAX_BATCH_SIZE]; _sortedSprites = new SpriteInfo[MAX_BATCH_SIZE]; @@ -167,9 +171,9 @@ public SpriteBatch(IGraphicsDevice iDevice, SpriteSortAlgorithm sortAlgorithm = _spriteQueue = new SpriteInfo[MAX_BATCH_SIZE]; _spriteTextures = new TextureInfo[MAX_BATCH_SIZE]; - iDevice.ResizeFinished += IDevice_onResizeFinished; + graphicsDevice.ResizeFinished += IDevice_onResizeFinished; - Resize(iDevice.Viewport); + Resize(graphicsDevice.Viewport); } /// @@ -268,14 +272,15 @@ public void Resize(float width, float height) { float xRatio = width > 0 ? 1f / width : 0f; float yRatio = height > 0 ? -1f / height : 0f; + _projectionMatrix = new Matrix { M11 = xRatio * 2f, M22 = yRatio * 2f, M33 = 1f, M44 = 1f, - M41 = -1f, - M42 = 1f + M41 = -(_center ? 0f : 1f), + M42 = _center ? 0f : 1f }; } From b20f8fd46350675897a76e25580718f40e4a0fca Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Thu, 12 Nov 2020 09:02:47 +0100 Subject: [PATCH 25/44] cs project changed --- src/Exomia.Framework/Exomia.Framework.csproj | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Exomia.Framework/Exomia.Framework.csproj b/src/Exomia.Framework/Exomia.Framework.csproj index 0e671565..619fb0d8 100644 --- a/src/Exomia.Framework/Exomia.Framework.csproj +++ b/src/Exomia.Framework/Exomia.Framework.csproj @@ -8,6 +8,7 @@ true enable true + TRACE;$(Platform) @@ -42,16 +43,13 @@ portable true - DEBUG;TRACE;x86 - DEBUG;TRACE;$(Platform) true + $(DefineConstants);DEBUG none false - TRACE;x86 - TRACE;$(Platform) From 173f7d0fb46f022dc0e8483638859d47ec117a6e Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Fri, 13 Nov 2020 12:29:19 +0100 Subject: [PATCH 26/44] added line --- .../Graphics/SpriteBatch.Drawing.cs | 73 +++++++- src/Exomia.Framework/Mathematics/Line2.cs | 177 ++++++++++++++++++ src/Exomia.Framework/VectorI2.cs | 3 +- src/Exomia.Framework/VectorI3.cs | 3 +- 4 files changed, 250 insertions(+), 6 deletions(-) create mode 100644 src/Exomia.Framework/Mathematics/Line2.cs diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.Drawing.cs b/src/Exomia.Framework/Graphics/SpriteBatch.Drawing.cs index d9eed65f..4c240a16 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.Drawing.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.Drawing.cs @@ -9,8 +9,10 @@ #endregion using System; +using System.Runtime.CompilerServices; using System.Text; using System.Threading; +using Exomia.Framework.Mathematics; using SharpDX; namespace Exomia.Framework.Graphics @@ -28,6 +30,7 @@ public sealed partial class SpriteBatch /// The rotation. /// The opacity. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawRectangle(in RectangleF destinationRectangle, in Color color, float lineWidth, @@ -108,6 +111,7 @@ public void DrawRectangle(in RectangleF destinationRectangle, /// Destination rectangle. /// The color. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawFillRectangle(in RectangleF destinationRectangle, in Color color, float layerDepth) { DrawSprite( @@ -122,6 +126,7 @@ public void DrawFillRectangle(in RectangleF destinationRectangle, in Color color /// The color. /// The opacity. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawFillRectangle(in RectangleF destinationRectangle, in Color color, float opacity, @@ -141,6 +146,7 @@ public void DrawFillRectangle(in RectangleF destinationRectangle, /// The origin. /// The opacity. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawFillRectangle(in RectangleF destinationRectangle, in Color color, float rotation, @@ -162,6 +168,7 @@ public void DrawFillRectangle(in RectangleF destinationRectangle, /// Width of the line. /// The opacity. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawLine(in Vector2 point1, in Vector2 point2, in Color color, @@ -172,6 +179,24 @@ public void DrawLine(in Vector2 point1, DrawLine(point1, point2, color, lineWidth, opacity, 1.0f, layerDepth); } + /// + /// Draw line. + /// + /// The line. + /// The color. + /// Width of the line. + /// The opacity. + /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawLine(in Line2 line, + in Color color, + float lineWidth, + float opacity, + float layerDepth) + { + DrawLine(in line, color, lineWidth, opacity, 1.0f, layerDepth); + } + /// /// Draw line. /// @@ -182,6 +207,7 @@ public void DrawLine(in Vector2 point1, /// The opacity. /// The length factor. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawLine(in Vector2 point1, in Vector2 point2, in Color color, @@ -190,10 +216,32 @@ public void DrawLine(in Vector2 point1, float lengthFactor, float layerDepth) { + DrawLine(new Line2(point1, point2), color, lineWidth, opacity, lengthFactor, layerDepth); + } + + /// + /// Draw line. + /// + /// The line. + /// The color. + /// Width of the line. + /// The opacity. + /// The length factor. + /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawLine(in Line2 line, + in Color color, + float lineWidth, + float opacity, + float lengthFactor, + float layerDepth) + { + float dx = line.X2 - line.X1; + float dy = line.Y2 - line.Y1; DrawSprite( _whiteTexture, new RectangleF( - point1.X, point1.Y, Vector2.Distance(point1, point2) * lengthFactor, lineWidth), false, - s_nullRectangle, color, (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X), + line.X1, line.Y1, (float)Math.Sqrt((dx * dx) + (dy * dy)) * lengthFactor, lineWidth), false, + s_nullRectangle, color, (float)Math.Atan2(dy, dx), s_vector2Zero, opacity, SpriteEffects.None, layerDepth); } @@ -228,6 +276,7 @@ public void DrawPolygon(Vector2[] vertex, in Color color, float lineWidth, float /// The opacity. /// The segments. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawCircle(in Vector2 center, float radius, in Color color, @@ -286,6 +335,7 @@ public void DrawCircle(in Vector2 center, /// The texture. /// The position. /// The color. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Draw(Texture texture, in Vector2 position, in Color color) { DrawSprite( @@ -299,6 +349,7 @@ public void Draw(Texture texture, in Vector2 position, in Color color) /// The texture. /// Destination rectangle. /// The color. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Draw(Texture texture, in RectangleF destinationRectangle, in Color color) { DrawSprite( @@ -313,6 +364,7 @@ public void Draw(Texture texture, in RectangleF destinationRectangle, in Color c /// The position. /// Source rectangle. /// The color. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Draw(Texture texture, in Vector2 position, in Rectangle? sourceRectangle, in Color color) { DrawSprite( @@ -327,6 +379,7 @@ public void Draw(Texture texture, in Vector2 position, in Rectangle? sourceRecta /// Destination rectangle. /// Source rectangle. /// The color. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Draw(Texture texture, in RectangleF destinationRectangle, in Rectangle? sourceRectangle, @@ -346,6 +399,7 @@ public void Draw(Texture texture, /// The rotation. /// The origin. /// (Optional) Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Draw(Texture texture, in Vector2 position, in Color color, @@ -367,6 +421,7 @@ public void Draw(Texture texture, /// The rotation. /// The origin. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Draw(Texture texture, in RectangleF destinationRectangle, in Color color, @@ -391,6 +446,7 @@ public void Draw(Texture texture, /// The opacity. /// The effects. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Draw(Texture texture, in RectangleF destinationRectangle, in Rectangle? sourceRectangle, @@ -419,6 +475,7 @@ public void Draw(Texture texture, /// The opacity. /// The effects. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Draw(Texture texture, in Vector2 position, in Rectangle? sourceRectangle, @@ -448,6 +505,7 @@ public void Draw(Texture texture, /// The opacity. /// The effects. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Draw(Texture texture, in Vector2 position, in Rectangle? sourceRectangle, @@ -601,6 +659,7 @@ private unsafe void DrawSprite(Texture texture, /// The position. /// The color. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, string text, in Vector2 position, in Color color, float layerDepth) { font.Draw( @@ -617,6 +676,7 @@ public void DrawText(SpriteFont font, string text, in Vector2 position, in Color /// The color. /// The rotation. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, string text, in Vector2 position, @@ -641,6 +701,7 @@ public void DrawText(SpriteFont font, /// The opacity. /// The effects. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, string text, in Vector2 position, @@ -670,6 +731,7 @@ public void DrawText(SpriteFont font, /// The opacity. /// The effects. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, string text, int start, @@ -702,6 +764,7 @@ public void DrawText(SpriteFont font, /// The opacity. /// The effects. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, string text, int start, @@ -728,6 +791,7 @@ public void DrawText(SpriteFont font, /// The position. /// The color. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, in Color color, float layerDepth) { font.Draw( @@ -744,6 +808,7 @@ public void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, i /// The color. /// The rotation. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, @@ -768,6 +833,7 @@ public void DrawText(SpriteFont font, /// The opacity. /// The effects. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, @@ -797,6 +863,7 @@ public void DrawText(SpriteFont font, /// The opacity. /// The effects. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, StringBuilder text, int start, @@ -829,6 +896,7 @@ public void DrawText(SpriteFont font, /// The opacity. /// The effects. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, StringBuilder text, int start, @@ -860,6 +928,7 @@ public void DrawText(SpriteFont font, /// The opacity. /// The effects. /// Depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void DrawTextInternal(Texture texture, in Vector2 position, in Rectangle? sourceRectangle, diff --git a/src/Exomia.Framework/Mathematics/Line2.cs b/src/Exomia.Framework/Mathematics/Line2.cs new file mode 100644 index 00000000..5d22115a --- /dev/null +++ b/src/Exomia.Framework/Mathematics/Line2.cs @@ -0,0 +1,177 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using System.Globalization; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using SharpDX; + +namespace Exomia.Framework.Mathematics +{ + /// + /// A 2d line. + /// + /// + [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 16)] + public readonly struct Line2 : IFormattable + { + /// + /// The first x value. + /// + public readonly float X1; + + /// + /// The second x value. + /// + public readonly float X2; + + /// + /// The first y value. + /// + public readonly float Y1; + + /// + /// The second y value. + /// + public readonly float Y2; + + /// + /// Initializes a new instance of the struct. + /// + /// The first x value. + /// The second x value. + /// The first y value. + /// The second y value. + public Line2(float x1, float x2, float y1, float y2) + { + X1 = x1; + X2 = x2; + Y1 = y1; + Y2 = y2; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The VectorI2 to process. + /// The VectorI2 to process. + public Line2(VectorI2 a, VectorI2 b) + : this(a.X, b.X, a.Y, b.Y) { } + + /// + /// Initializes a new instance of the struct. + /// + /// The Vector2 to process. + /// The Vector2 to process. + public Line2(Vector2 a, Vector2 b) + : this(a.X, b.X, a.Y, b.Y) { } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; false otherwise. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(in Line2 other) + { + // ReSharper disable CompareOfFloatsByEqualityOperator + return + X1 == other.X1 && + X2 == other.X2 && + Y1 == other.Y1 && + Y2 == other.Y2; + + // ReSharper restore CompareOfFloatsByEqualityOperator + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override bool Equals(object value) + { + if (value is Line2 other) + { + return Equals(in other); + } + return false; + } + + /// + public override int GetHashCode() + { + return (((((X1.GetHashCode() * 307) ^ Y1.GetHashCode()) * 521) ^ X2.GetHashCode()) * 853) ^ + Y2.GetHashCode(); + } + + /// + public override string ToString() + { + return string.Format( + CultureInfo.CurrentCulture, + "X1:{0} Y1:{1} | X2:{2} Y2:{3}", X1, Y1, X2, Y2); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string? format) + { + if (format == null) + { + return ToString(); + } + + return string.Format( + CultureInfo.CurrentCulture, + "X1:{0} Y1:{1} | X2:{2} Y2:{3}", + X1.ToString(format, CultureInfo.CurrentCulture), + Y1.ToString(format, CultureInfo.CurrentCulture), + X2.ToString(format, CultureInfo.CurrentCulture), + Y2.ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format( + formatProvider, + "X1:{0} Y1:{1} | X2:{2} Y2:{3}", X1, Y1, X2, Y2); + } + + /// + public string ToString(string? format, IFormatProvider formatProvider) + { + if (format == null) + { + return ToString(formatProvider); + } + + return string.Format( + formatProvider, + "X1:{0} Y1:{1} | X2:{2} Y2:{3}", + X1.ToString(format, formatProvider), + Y1.ToString(format, formatProvider), + X2.ToString(format, formatProvider), + Y2.ToString(format, formatProvider)); + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/VectorI2.cs b/src/Exomia.Framework/VectorI2.cs index 5baa599e..d83c9ed6 100644 --- a/src/Exomia.Framework/VectorI2.cs +++ b/src/Exomia.Framework/VectorI2.cs @@ -79,8 +79,7 @@ public VectorI2(int x, int y) /// /// The to compare with this instance. /// - /// true if the specified is equal to this instance; otherwise, - /// false. + /// true if the specified is equal to this instance; false otherwise. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly bool Equals(in VectorI2 other) diff --git a/src/Exomia.Framework/VectorI3.cs b/src/Exomia.Framework/VectorI3.cs index 98e1d392..c04f45ad 100644 --- a/src/Exomia.Framework/VectorI3.cs +++ b/src/Exomia.Framework/VectorI3.cs @@ -105,8 +105,7 @@ public VectorI3(in VectorI2 value, int z) /// /// The to compare with this instance. /// - /// true if the specified is equal to this instance; - /// false otherwise. + /// true if the specified is equal to this instance; false otherwise. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly bool Equals(in VectorI3 other) From f138685614fb79518adeae387f800c6cbf575c5b Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Fri, 13 Nov 2020 12:43:39 +0100 Subject: [PATCH 27/44] removed version tag, changed line constructor param order --- src/Exomia.Framework/Exomia.Framework.csproj | 1 - src/Exomia.Framework/Mathematics/Line2.cs | 12 ++++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Exomia.Framework/Exomia.Framework.csproj b/src/Exomia.Framework/Exomia.Framework.csproj index 619fb0d8..24acde4f 100644 --- a/src/Exomia.Framework/Exomia.Framework.csproj +++ b/src/Exomia.Framework/Exomia.Framework.csproj @@ -12,7 +12,6 @@ - 1.4.1 exomia exomia;saika01 a framework for building 2D and 3D games and more inspired by the XNA/Mono framework diff --git a/src/Exomia.Framework/Mathematics/Line2.cs b/src/Exomia.Framework/Mathematics/Line2.cs index 5d22115a..36a2425f 100644 --- a/src/Exomia.Framework/Mathematics/Line2.cs +++ b/src/Exomia.Framework/Mathematics/Line2.cs @@ -47,14 +47,14 @@ namespace Exomia.Framework.Mathematics /// Initializes a new instance of the struct. /// /// The first x value. - /// The second x value. /// The first y value. + /// The second x value. /// The second y value. - public Line2(float x1, float x2, float y1, float y2) + public Line2(float x1, float y1, float x2, float y2) { X1 = x1; - X2 = x2; Y1 = y1; + X2 = x2; Y2 = y2; } @@ -64,7 +64,7 @@ public Line2(float x1, float x2, float y1, float y2) /// The VectorI2 to process. /// The VectorI2 to process. public Line2(VectorI2 a, VectorI2 b) - : this(a.X, b.X, a.Y, b.Y) { } + : this(a.X, a.Y, b.X, b.Y) { } /// /// Initializes a new instance of the struct. @@ -72,7 +72,7 @@ public Line2(VectorI2 a, VectorI2 b) /// The Vector2 to process. /// The Vector2 to process. public Line2(Vector2 a, Vector2 b) - : this(a.X, b.X, a.Y, b.Y) { } + : this(a.X, a.Y, b.X, b.Y) { } /// /// Determines whether the specified is equal to this instance. @@ -87,8 +87,8 @@ public bool Equals(in Line2 other) // ReSharper disable CompareOfFloatsByEqualityOperator return X1 == other.X1 && - X2 == other.X2 && Y1 == other.Y1 && + X2 == other.X2 && Y2 == other.Y2; // ReSharper restore CompareOfFloatsByEqualityOperator From c789d286ead798f68b360771152244876e16832f Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Sat, 14 Nov 2020 00:14:17 +0100 Subject: [PATCH 28/44] summary changed --- .../Compression/CompressMode.cs | 4 ++-- .../Compression/ContentCompressor.cs | 22 +++++-------------- .../ContentSerializableAttribute.cs | 20 +++++++---------- .../ContentSerializationContext.cs | 21 +++++------------- 4 files changed, 21 insertions(+), 46 deletions(-) diff --git a/src/Exomia.Framework/ContentSerialization/Compression/CompressMode.cs b/src/Exomia.Framework/ContentSerialization/Compression/CompressMode.cs index 277c8db9..eed2361b 100644 --- a/src/Exomia.Framework/ContentSerialization/Compression/CompressMode.cs +++ b/src/Exomia.Framework/ContentSerialization/Compression/CompressMode.cs @@ -11,12 +11,12 @@ namespace Exomia.Framework.ContentSerialization.Compression { /// - /// CompressMode. + /// Values that represent CompressMode. /// public enum CompressMode : byte { /// - /// gzip (default) + /// An enum constant representing the gzip option (default). /// Gzip = 1 } diff --git a/src/Exomia.Framework/ContentSerialization/Compression/ContentCompressor.cs b/src/Exomia.Framework/ContentSerialization/Compression/ContentCompressor.cs index 2856cf9a..c5ff1675 100644 --- a/src/Exomia.Framework/ContentSerialization/Compression/ContentCompressor.cs +++ b/src/Exomia.Framework/ContentSerialization/Compression/ContentCompressor.cs @@ -16,12 +16,12 @@ namespace Exomia.Framework.ContentSerialization.Compression { /// - /// ContentCompressor class. + /// A content compressor. /// public static class ContentCompressor { /// - /// the default compressed e1 extension. + /// The default compressed e1 extension. /// public const string DEFAULT_COMPRESSED_EXTENSION = ".e1"; @@ -29,7 +29,7 @@ public static class ContentCompressor private static readonly byte[] s_magicHeader = { 64, 101, 120, 49 }; /// - /// compress a given stream with the given compression mode. + /// Compress a given stream with the given compression mode. /// /// the stream to compress. /// [out] than finished the compressed out stream. @@ -71,7 +71,7 @@ public static bool CompressStream(Stream stream, } /// - /// decompress a given stream with the given compression mode. + /// Decompress a given stream with the given compression mode. /// /// the stream to compress. /// [out] than finished the decompressed out stream. @@ -114,12 +114,7 @@ public static bool DecompressStream(Stream stream, out Stream streamOut) } #region GZIP - - /// - /// Gzip compress. - /// - /// the stream to compress. - /// [out] than finished the compressed out stream. + private static void GzipCompress(Stream stream, Stream streamOut) { using (GZipStream gs = new GZipStream(streamOut, CompressionLevel.Optimal, true)) @@ -133,12 +128,7 @@ private static void GzipCompress(Stream stream, Stream streamOut) } streamOut.Position = 0; } - - /// - /// Gzip decompress. - /// - /// the stream to compress. - /// [out] than finished the compressed out stream. + private static void GzipDecompress(Stream stream, out Stream streamOut) { streamOut = new MemoryStream(); diff --git a/src/Exomia.Framework/ContentSerialization/ContentSerializableAttribute.cs b/src/Exomia.Framework/ContentSerialization/ContentSerializableAttribute.cs index 210331c5..1b8ce50e 100644 --- a/src/Exomia.Framework/ContentSerialization/ContentSerializableAttribute.cs +++ b/src/Exomia.Framework/ContentSerialization/ContentSerializableAttribute.cs @@ -13,7 +13,7 @@ namespace Exomia.Framework.ContentSerialization { /// - /// used to mark a content serializable class. + /// Used to mark a content serializable class. /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] public sealed class ContentSerializableAttribute : Attribute @@ -33,19 +33,15 @@ public sealed class ContentSerializableAttribute : Attribute /// The writer. /// internal IContentSerializationWriter Writer { get; } - - /// + /// - /// ContentSerializableAttribute constructor. + /// Initializes a new instance of the class. /// - /// - /// the content reader type - /// - /// - /// - /// the content writer type - /// - /// + /// the content reader type + /// + /// the content writer type + /// + /// Thrown when a Type Load error condition occurs. public ContentSerializableAttribute(Type reader, Type writer) { Reader = System.Activator.CreateInstance(reader) as IContentSerializationReader ?? diff --git a/src/Exomia.Framework/ContentSerialization/ContentSerializationContext.cs b/src/Exomia.Framework/ContentSerialization/ContentSerializationContext.cs index 3686277c..82a4843a 100644 --- a/src/Exomia.Framework/ContentSerialization/ContentSerializationContext.cs +++ b/src/Exomia.Framework/ContentSerialization/ContentSerializationContext.cs @@ -15,9 +15,9 @@ namespace Exomia.Framework.ContentSerialization { /// - /// ContentSerializationContext class + /// A content serialization context. This class cannot be inherited. /// - public class ContentSerializationContext + public sealed class ContentSerializationContext { internal Dictionary Content { get; } = new Dictionary(); @@ -71,25 +71,14 @@ internal void Set(string key, object obj, Type type) } } } - - /// - /// A content serialization context value. - /// + struct ContentSerializationContextValue { - /// - /// The type. - /// - public Type Type; - - /// - /// The object. - /// + public Type Type; public object Object; /// - /// Initializes a new instance of the - /// struct. + /// Initializes a new instance of the struct. /// /// The type. /// The object. From 5362a26c0ce3ecd331f34d66a1b2a708a1848623 Mon Sep 17 00:00:00 2001 From: Daniel Baetz Date: Sun, 15 Nov 2020 21:29:17 +0100 Subject: [PATCH 29/44] cleanup --- .../Exomia.Framework.Example.Canvas.csproj | 8 +- .../Exomia.Framework.Example.Canvas/MyGame.cs | 11 +- .../Compression/ContentCompressor.cs | 4 +- .../ContentSerializableAttribute.cs | 16 +- .../ContentSerializationContext.cs | 2 +- .../ContentSerialization/ContentSerializer.cs | 1 + src/Exomia.Framework/Exomia.Framework.csproj | 2 + .../Game/RenderForm.Events.cs | 9 +- src/Exomia.Framework/Graphics/Canvas.cs | 301 +++++++++++++++++- src/Exomia.Framework/Graphics/SpriteBatch.cs | 172 +++++----- src/Exomia.Framework/IDrawable.cs | 2 +- src/Exomia.Framework/Input/InputState.cs | 15 +- src/Exomia.Framework/Input/KeyEventHandler.cs | 6 +- .../Input/MouseEventHandler.cs | 2 +- src/Exomia.Framework/Mathematics/Line2.cs | 6 +- .../Resources/shaders/canvas.ehlsl | 19 +- 16 files changed, 423 insertions(+), 153 deletions(-) diff --git a/examples/Exomia.Framework.Example.Canvas/Exomia.Framework.Example.Canvas.csproj b/examples/Exomia.Framework.Example.Canvas/Exomia.Framework.Example.Canvas.csproj index 81495bc6..a07bcdce 100644 --- a/examples/Exomia.Framework.Example.Canvas/Exomia.Framework.Example.Canvas.csproj +++ b/examples/Exomia.Framework.Example.Canvas/Exomia.Framework.Example.Canvas.csproj @@ -49,12 +49,8 @@ - - - - - - + + \ No newline at end of file diff --git a/examples/Exomia.Framework.Example.Canvas/MyGame.cs b/examples/Exomia.Framework.Example.Canvas/MyGame.cs index b3ca4880..29395ca2 100644 --- a/examples/Exomia.Framework.Example.Canvas/MyGame.cs +++ b/examples/Exomia.Framework.Example.Canvas/MyGame.cs @@ -10,7 +10,6 @@ using Exomia.Framework.Components; using Exomia.Framework.Game; -using Exomia.Framework.Graphics; using SharpDX; namespace Exomia.Framework.Example.Canvas @@ -20,7 +19,7 @@ namespace Exomia.Framework.Example.Canvas /// sealed class MyGame : Game.Game { - private SpriteBatch _spriteBatch = null!; + private Graphics.Canvas _canvas = null!; /// /// Initializes a new instance of the class. @@ -55,7 +54,7 @@ protected override void OnInitializeGameGraphicsParameters(ref GameGraphicsParam protected override void OnInitialize() { Content.RootDirectory = "Content"; - _spriteBatch = ToDispose(new SpriteBatch(GraphicsDevice)); + _canvas = ToDispose(new Graphics.Canvas(GraphicsDevice)); /* * TODO: Add your initialization logic here @@ -97,9 +96,9 @@ protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); - /* - * TODO: Add your drawing code here - */ + _canvas.Begin(); + _canvas.DrawFillRectangle(new RectangleF(50, 50, 100, 100), Color.Red, 0, Vector2.Zero, 1); + _canvas.End(); base.Draw(gameTime); } diff --git a/src/Exomia.Framework/ContentSerialization/Compression/ContentCompressor.cs b/src/Exomia.Framework/ContentSerialization/Compression/ContentCompressor.cs index c5ff1675..79f9c2de 100644 --- a/src/Exomia.Framework/ContentSerialization/Compression/ContentCompressor.cs +++ b/src/Exomia.Framework/ContentSerialization/Compression/ContentCompressor.cs @@ -114,7 +114,7 @@ public static bool DecompressStream(Stream stream, out Stream streamOut) } #region GZIP - + private static void GzipCompress(Stream stream, Stream streamOut) { using (GZipStream gs = new GZipStream(streamOut, CompressionLevel.Optimal, true)) @@ -128,7 +128,7 @@ private static void GzipCompress(Stream stream, Stream streamOut) } streamOut.Position = 0; } - + private static void GzipDecompress(Stream stream, out Stream streamOut) { streamOut = new MemoryStream(); diff --git a/src/Exomia.Framework/ContentSerialization/ContentSerializableAttribute.cs b/src/Exomia.Framework/ContentSerialization/ContentSerializableAttribute.cs index 1b8ce50e..8115289a 100644 --- a/src/Exomia.Framework/ContentSerialization/ContentSerializableAttribute.cs +++ b/src/Exomia.Framework/ContentSerialization/ContentSerializableAttribute.cs @@ -33,14 +33,18 @@ public sealed class ContentSerializableAttribute : Attribute /// The writer. /// internal IContentSerializationWriter Writer { get; } - + /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// the content reader type - /// - /// the content writer type - /// + /// + /// the content reader type + /// + /// + /// + /// the content writer type + /// + /// /// Thrown when a Type Load error condition occurs. public ContentSerializableAttribute(Type reader, Type writer) { diff --git a/src/Exomia.Framework/ContentSerialization/ContentSerializationContext.cs b/src/Exomia.Framework/ContentSerialization/ContentSerializationContext.cs index 82a4843a..bb3d9478 100644 --- a/src/Exomia.Framework/ContentSerialization/ContentSerializationContext.cs +++ b/src/Exomia.Framework/ContentSerialization/ContentSerializationContext.cs @@ -71,7 +71,7 @@ internal void Set(string key, object obj, Type type) } } } - + struct ContentSerializationContextValue { public Type Type; diff --git a/src/Exomia.Framework/ContentSerialization/ContentSerializer.cs b/src/Exomia.Framework/ContentSerialization/ContentSerializer.cs index f5c0472b..16954bbc 100644 --- a/src/Exomia.Framework/ContentSerialization/ContentSerializer.cs +++ b/src/Exomia.Framework/ContentSerialization/ContentSerializer.cs @@ -17,6 +17,7 @@ using Exomia.Framework.ContentSerialization.Types; using Exomia.Framework.ContentSerialization.Writers; using SharpDX; + #if NETSTANDARD2_0 using Exomia.Framework.Extensions; #endif diff --git a/src/Exomia.Framework/Exomia.Framework.csproj b/src/Exomia.Framework/Exomia.Framework.csproj index 24acde4f..755ef0e2 100644 --- a/src/Exomia.Framework/Exomia.Framework.csproj +++ b/src/Exomia.Framework/Exomia.Framework.csproj @@ -100,6 +100,7 @@ + @@ -148,6 +149,7 @@ $(MSBuildProjectName).Resources.fonts.arial.arial_38px.e1 + diff --git a/src/Exomia.Framework/Game/RenderForm.Events.cs b/src/Exomia.Framework/Game/RenderForm.Events.cs index d5515971..ef7437dc 100644 --- a/src/Exomia.Framework/Game/RenderForm.Events.cs +++ b/src/Exomia.Framework/Game/RenderForm.Events.cs @@ -183,7 +183,7 @@ private unsafe IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lPara int wheelDelta = HighWord(m.wParam); for (int i = 0; i < _mouseWheelPipe.Count; i++) { - if (_mouseWheelPipe[i].Invoke(new MouseEventArgs(x, y, mouseButtons, 2, wheelDelta)) == + if (_mouseWheelPipe[i].Invoke(new MouseEventArgs(x, y, mouseButtons, 2, wheelDelta)) == EventAction.StopPropagation) { break; @@ -294,7 +294,8 @@ private void RawMouseDown(ref Message m, MouseButtons buttons) int high = HighWord(m.lParam); for (int i = 0; i < _mouseDownPipe.Count; i++) { - if (_mouseDownPipe[i].Invoke(new MouseEventArgs(low, high, buttons, 1, 0)) == EventAction.StopPropagation) + if (_mouseDownPipe[i].Invoke(new MouseEventArgs(low, high, buttons, 1, 0)) == + EventAction.StopPropagation) { break; } @@ -311,7 +312,7 @@ private void RawMouseUp(ref Message m, MouseButtons buttons) int clicks = (_state & 0x4000000) == 0x4000000 ? 2 : 1; for (int i = 0; i < _mouseClickPipe.Count; i++) { - if (_mouseClickPipe[i].Invoke(new MouseEventArgs(low, high, buttons, clicks, 0)) == + if (_mouseClickPipe[i].Invoke(new MouseEventArgs(low, high, buttons, clicks, 0)) == EventAction.StopPropagation) { break; @@ -359,7 +360,7 @@ private void RawMouseInput(in RAWINPUTMOUSE e) } for (int i = 0; i < _mouseRawInputPipe.Count; i++) { - if (_mouseRawInputPipe[i].Invoke(new MouseEventArgs(e.LastX, e.LastY, buttons, clicks, e.ButtonData)) == + if (_mouseRawInputPipe[i].Invoke(new MouseEventArgs(e.LastX, e.LastY, buttons, clicks, e.ButtonData)) == EventAction.StopPropagation) { break; diff --git a/src/Exomia.Framework/Graphics/Canvas.cs b/src/Exomia.Framework/Graphics/Canvas.cs index 6d6a4912..7290159e 100644 --- a/src/Exomia.Framework/Graphics/Canvas.cs +++ b/src/Exomia.Framework/Graphics/Canvas.cs @@ -9,8 +9,15 @@ #endregion using System; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; using System.Text; +using Exomia.Framework.Graphics.Buffers; +using Exomia.Framework.Graphics.Shader; +using Exomia.Framework.Resources; using SharpDX; +using SharpDX.Direct3D; using SharpDX.Direct3D11; namespace Exomia.Framework.Graphics @@ -20,21 +27,212 @@ namespace Exomia.Framework.Graphics /// public sealed class Canvas : IDisposable { - private static readonly Vector2 s_vector2Zero = Vector2.Zero; - private static readonly Rectangle? s_nullRectangle = null; - private readonly Device5 _device; - private readonly DeviceContext4 _context; + private const int MAX_BATCH_SIZE = 1 << 13; + private const int INITIAL_QUEUE_SIZE = 1 << 7; + private const int VERTICES_PER_SPRITE = 4; + private const int INDICES_PER_SPRITE = 6; + private const int MAX_VERTEX_COUNT = MAX_BATCH_SIZE * VERTICES_PER_SPRITE; + private const int MAX_INDEX_COUNT = MAX_BATCH_SIZE * INDICES_PER_SPRITE; + private const int BATCH_SEQUENTIAL_THRESHOLD = 1 << 9; + private const int VERTEX_STRIDE = sizeof(float) * 11; + + private static readonly ushort[] s_indices; + private static readonly Vector2 s_vector2Zero = Vector2.Zero; + private static readonly Rectangle? s_nullRectangle = null; + + private static readonly Vector2[] + s_cornerOffsets = { Vector2.Zero, Vector2.UnitX, Vector2.One, Vector2.UnitY }; + + private readonly Device5 _device; + private readonly DeviceContext4 _context; + + private readonly InputLayout _vertexInputLayout; + + private readonly IndexBuffer _indexBuffer; + private readonly VertexBuffer _vertexBuffer; + private readonly ConstantBuffer _perFrameBuffer; + + private readonly Shader.Shader _shader; + private readonly PixelShader _pixelShader; + private readonly VertexShader _vertexShader; + private readonly Texture _whiteTexture; + + private readonly BlendState _defaultBlendState; + private readonly DepthStencilState _defaultDepthStencilState; + private readonly RasterizerState _defaultRasterizerState; + private readonly RasterizerState _defaultRasterizerScissorEnabledState; + private readonly SamplerState _defaultSamplerState; + private BlendState? _blendState; + private DepthStencilState? _depthStencilState; + private RasterizerState? _rasterizerState; + private SamplerState? _samplerState; + + private bool _isBeginCalled, _isScissorEnabled; + private Rectangle _scissorRectangle; + + private Matrix _projectionMatrix, _viewMatrix, _transformMatrix; + + /// + /// Initializes static members of the class. + /// + /// + /// Thrown when one or more arguments are outside + /// the required range. + /// + static Canvas() + { + if (MAX_INDEX_COUNT > ushort.MaxValue) +#pragma warning disable 162 + { + // ReSharper disable once NotResolvedInText + throw new ArgumentOutOfRangeException("MAX_INDEX_COUNT->MAX_BATCH_SIZE"); + } +#pragma warning restore 162 + s_indices = new ushort[MAX_INDEX_COUNT]; + for (int i = 0, k = 0; i < MAX_INDEX_COUNT; i += INDICES_PER_SPRITE, k += VERTICES_PER_SPRITE) + { + s_indices[i + 0] = (ushort)(k + 0); + s_indices[i + 1] = (ushort)(k + 1); + s_indices[i + 2] = (ushort)(k + 2); + s_indices[i + 3] = (ushort)(k + 0); + s_indices[i + 4] = (ushort)(k + 2); + s_indices[i + 5] = (ushort)(k + 3); + } + } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// Zero-based index of the device. - public Canvas(IGraphicsDevice iDevice) + /// The graphics device. + /// Thrown when a value was unexpectedly null. + public Canvas(IGraphicsDevice graphicsDevice) { - _device = iDevice.Device; - _context = iDevice.DeviceContext; + _device = graphicsDevice.Device; + _context = graphicsDevice.DeviceContext; + + _defaultBlendState = graphicsDevice.BlendStates.AlphaBlend; + _defaultSamplerState = graphicsDevice.SamplerStates.LinearWrap; + _defaultDepthStencilState = graphicsDevice.DepthStencilStates.None; + _defaultRasterizerState = graphicsDevice.RasterizerStates.CullBackDepthClipOff; + _defaultRasterizerScissorEnabledState = graphicsDevice.RasterizerStates.CullBackDepthClipOffScissorEnabled; + + _whiteTexture = graphicsDevice.Textures.White; + + _indexBuffer = IndexBuffer.Create(graphicsDevice, s_indices); + + Assembly assembly = Assembly.GetExecutingAssembly(); + using (Stream stream = + assembly.GetManifestResourceStream($"{assembly.GetName().Name}.{Shaders.CANVAS}") ?? + throw new NullReferenceException($"{assembly.GetName().Name}.{Shaders.CANVAS}")) + { + Shader.Shader.Group group = + (_shader = ShaderFileLoader.FromStream(graphicsDevice, stream) ?? + throw new NullReferenceException(nameof(ShaderFileLoader.FromStream)))["DEFAULT"]; - iDevice.ResizeFinished += IDevice_onResizeFinished; + _vertexShader = group; + _pixelShader = group; + + _vertexInputLayout = group.CreateInputLayout(graphicsDevice, Shader.Shader.Type.VertexShader); + } + + _vertexBuffer = VertexBuffer.Create(graphicsDevice, MAX_VERTEX_COUNT); + _perFrameBuffer = ConstantBuffer.Create(graphicsDevice); + + graphicsDevice.ResizeFinished += IDevice_onResizeFinished; + + Resize(graphicsDevice.Viewport); + } + + /// + /// Resizes. + /// + /// The size. + public void Resize(Size2F size) + { + Resize(size.Width, size.Height); + } + + /// + /// Resizes. + /// + /// The viewport. + public void Resize(ViewportF viewport) + { + Resize(viewport.Width, viewport.Height); + } + + /// + /// Resizes. + /// + /// The width. + /// The height. + public void Resize(float width, float height) + { + float xRatio = width > 0 ? 1f / width : 0f; + float yRatio = height > 0 ? -1f / height : 0f; + + _projectionMatrix = new Matrix + { + M11 = xRatio * 2f, + M22 = yRatio * 2f, + M33 = 1f, + M44 = 1f, + M41 = -1f, + M42 = 1f + }; + } + + /// + /// Begins. + /// + /// Thrown when the requested operation is invalid. + /// (Optional) State of the blend. + /// (Optional) State of the sampler. + /// (Optional) State of the depth stencil. + /// (Optional) State of the rasterizer. + /// (Optional) The transform matrix. + /// (Optional) The view matrix. + /// (Optional) The scissor rectangle. + public void Begin(BlendState? blendState = null, + SamplerState? samplerState = null, + DepthStencilState? depthStencilState = null, + RasterizerState? rasterizerState = null, + Matrix? transformMatrix = null, + Matrix? viewMatrix = null, + Rectangle? scissorRectangle = null) + { + if (_isBeginCalled) + { + throw new InvalidOperationException("End must be called before begin"); + } + + _blendState = blendState; + _samplerState = samplerState; + _depthStencilState = depthStencilState; + _rasterizerState = rasterizerState; + _transformMatrix = transformMatrix ?? Matrix.Identity; + _viewMatrix = viewMatrix ?? Matrix.Identity; + + _isScissorEnabled = scissorRectangle.HasValue; + _scissorRectangle = scissorRectangle ?? Rectangle.Empty; + + _isBeginCalled = true; + } + + /// + /// Ends this object. + /// + /// Thrown when the requested operation is invalid. + public void End() + { + if (!_isBeginCalled) + { + throw new InvalidOperationException("Begin must be called before End"); + } + + PrepareForRendering(); + + _isBeginCalled = false; } #region Line @@ -62,12 +260,80 @@ public void DrawLine(in Vector2 point1, #endregion + private void PrepareForRendering() + { + _context.VertexShader.Set(_vertexShader); + _context.PixelShader.Set(_pixelShader); + + _context.OutputMerger.SetBlendState(_blendState ?? _defaultBlendState); + _context.OutputMerger.SetDepthStencilState(_depthStencilState ?? _defaultDepthStencilState); + + _context.Rasterizer.State = _rasterizerState ?? _defaultRasterizerState; + + if (_isScissorEnabled) + { + _context.Rasterizer.State = _rasterizerState ?? _defaultRasterizerScissorEnabledState; + _context.Rasterizer.SetScissorRectangle( + _scissorRectangle.Left, _scissorRectangle.Top, _scissorRectangle.Right, + _scissorRectangle.Bottom); + } + + _context.PixelShader.SetSampler(0, _samplerState ?? _defaultSamplerState); + + _context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + _context.InputAssembler.InputLayout = _vertexInputLayout; + + Matrix worldViewProjection = Matrix.Transpose(_transformMatrix * _viewMatrix * _projectionMatrix); + _context.UpdateSubresource(ref worldViewProjection, _perFrameBuffer); + _context.VertexShader.SetConstantBuffer(0, _perFrameBuffer); + + _context.InputAssembler.SetIndexBuffer(_indexBuffer, _indexBuffer.Format, 0); + _context.InputAssembler.SetVertexBuffers(0, _vertexBuffer); + } + /// /// Device on resize finished. /// /// The viewport. private static void IDevice_onResizeFinished(ViewportF viewport) { } + [StructLayout(LayoutKind.Explicit, Size = VERTEX_STRIDE)] + private struct VertexPositionColorTexture + { + [FieldOffset(0)] + public readonly float X; + + [FieldOffset(4)] + public readonly float Y; + + [FieldOffset(8)] + public readonly float Z; + + [FieldOffset(12)] + public readonly float W; + + [FieldOffset(16)] + public readonly float R; + + [FieldOffset(20)] + public readonly float G; + + [FieldOffset(24)] + public readonly float B; + + [FieldOffset(28)] + public readonly float A; + + [FieldOffset(32)] + public readonly float U; + + [FieldOffset(36)] + public readonly float V; + + [FieldOffset(40)] + public readonly float M; + } + #region Triangle /// @@ -655,7 +921,20 @@ private void Dispose(bool disposing) { if (!_disposed) { - if (disposing) { } + if (disposing) + { + Utilities.Dispose(ref _blendState); + Utilities.Dispose(ref _rasterizerState); + Utilities.Dispose(ref _samplerState); + Utilities.Dispose(ref _depthStencilState); + + _vertexBuffer.Dispose(); + _indexBuffer.Dispose(); + _perFrameBuffer.Dispose(); + + _shader.Dispose(); + _vertexInputLayout.Dispose(); + } _disposed = true; } diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.cs b/src/Exomia.Framework/Graphics/SpriteBatch.cs index 6df60af8..5ba195a7 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.cs @@ -61,20 +61,23 @@ private static readonly Vector2[] private readonly VertexBuffer _vertexBuffer; private readonly ConstantBuffer _perFrameBuffer; - private readonly Shader.Shader _shader; - private readonly PixelShader _pixelShader; - private readonly VertexShader _vertexShader; - private readonly Texture _whiteTexture; - private readonly bool _center; - private BlendState? _defaultBlendState, _blendState; - private DepthStencilState? _defaultDepthStencilState, _depthStencilState; - - private RasterizerState? _defaultRasterizerState, - _defaultRasterizerScissorEnabledState, - _rasterizerState; - - private SamplerState? _defaultSamplerState, _samplerState; - private bool _isBeginCalled, _isScissorEnabled; + private readonly Shader.Shader _shader; + private readonly PixelShader _pixelShader; + private readonly VertexShader _vertexShader; + private readonly Texture _whiteTexture; + private readonly bool _center; + + private readonly BlendState _defaultBlendState; + private readonly DepthStencilState _defaultDepthStencilState; + private readonly RasterizerState _defaultRasterizerState; + private readonly RasterizerState _defaultRasterizerScissorEnabledState; + private readonly SamplerState _defaultSamplerState; + private BlendState? _blendState; + private DepthStencilState? _depthStencilState; + private RasterizerState? _rasterizerState; + private SamplerState? _samplerState; + + private bool _isBeginCalled, _isScissorEnabled; private Rectangle _scissorRectangle; private SpriteSortMode _spriteSortMode; private int[] _sortIndices; @@ -119,24 +122,26 @@ static SpriteBatch() /// The graphics device. /// (Optional) True to center the coordinate system in the viewport. /// (Optional) The sort algorithm. - /// Thrown when one or more arguments have unsupported or - /// illegal values. + /// + /// Thrown when one or more arguments have unsupported or + /// illegal values. + /// /// Thrown when a value was unexpectedly null. - public SpriteBatch(IGraphicsDevice graphicsDevice, - bool center = false, + public SpriteBatch(IGraphicsDevice graphicsDevice, + bool center = false, SpriteSortAlgorithm sortAlgorithm = SpriteSortAlgorithm.MergeSort) { _device = graphicsDevice.Device; _context = graphicsDevice.DeviceContext; - + _center = center; - + _spriteSort = sortAlgorithm switch { SpriteSortAlgorithm.MergeSort => new SpriteMergeSort(), _ => throw new ArgumentException($"invalid sort algorithm ({sortAlgorithm})", nameof(sortAlgorithm)) }; - + _defaultBlendState = graphicsDevice.BlendStates.AlphaBlend; _defaultSamplerState = graphicsDevice.SamplerStates.LinearWrap; _defaultDepthStencilState = graphicsDevice.DepthStencilStates.None; @@ -177,15 +182,7 @@ public SpriteBatch(IGraphicsDevice graphicsDevice, } /// - /// Finalizes an instance of the class. - /// - ~SpriteBatch() - { - Dispose(false); - } - - /// - /// Begins. + /// Begins a new batch. /// /// Thrown when the requested operation is invalid. /// (Optional) The sort mode. @@ -225,7 +222,7 @@ public void Begin(SpriteSortMode sortMode = SpriteSortMode.Deferred } /// - /// Ends this object. + /// Ends the current batch. /// /// Thrown when the requested operation is invalid. public void End() @@ -284,13 +281,6 @@ public void Resize(float width, float height) }; } - /// - /// Draw batch per texture. - /// - /// [in,out] The texture. - /// The sprites. - /// The offset. - /// Number of. private unsafe void DrawBatchPerTexture(ref TextureInfo texture, SpriteInfo[] sprites, int offset, int count) { _context.PixelShader.SetShaderResource(0, texture.View); @@ -304,60 +294,52 @@ private unsafe void DrawBatchPerTexture(ref TextureInfo texture, SpriteInfo[] sp { batchSize = MAX_BATCH_SIZE; } - lock (_device) - { - DataBox box = _context.MapSubresource( - _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); - VertexPositionColorTexture* vpctPtr = (VertexPositionColorTexture*)box.DataPointer; - if (batchSize > BATCH_SEQUENTIAL_THRESHOLD) - { - int middle = batchSize >> 1; - Parallel.Invoke( - () => + DataBox box = _context.MapSubresource( + _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); + VertexPositionColorTexture* vpctPtr = (VertexPositionColorTexture*)box.DataPointer; + + if (batchSize > BATCH_SEQUENTIAL_THRESHOLD) + { + int middle = batchSize >> 1; + Parallel.Invoke( + () => + { + for (int i = 0; i < middle; i++) { - for (int i = 0; i < middle; i++) - { - UpdateVertexFromSpriteInfo( - - // ReSharper disable once AccessToModifiedClosure - ref sprites[i + offset], vpctPtr + (i << 2), deltaX, deltaY); - } - }, - () => + UpdateVertexFromSpriteInfo( + + // ReSharper disable once AccessToModifiedClosure + ref sprites[i + offset], vpctPtr + (i << 2), deltaX, deltaY); + } + }, + () => + { + for (int i = middle; i < batchSize; i++) { - for (int i = middle; i < batchSize; i++) - { - UpdateVertexFromSpriteInfo( - - // ReSharper disable once AccessToModifiedClosure - ref sprites[i + offset], vpctPtr + (i << 2), deltaX, deltaY); - } - }); - } - else + UpdateVertexFromSpriteInfo( + + // ReSharper disable once AccessToModifiedClosure + ref sprites[i + offset], vpctPtr + (i << 2), deltaX, deltaY); + } + }); + } + else + { + for (int i = 0; i < batchSize; i++) { - for (int i = 0; i < batchSize; i++) - { - UpdateVertexFromSpriteInfo( - ref sprites[i + offset], vpctPtr + (i << 2), deltaX, deltaY); - } + UpdateVertexFromSpriteInfo( + ref sprites[i + offset], vpctPtr + (i << 2), deltaX, deltaY); } - _context.UnmapSubresource(_vertexBuffer, 0); - _context.DrawIndexed(INDICES_PER_SPRITE * batchSize, 0, 0); } + _context.UnmapSubresource(_vertexBuffer, 0); + _context.DrawIndexed(INDICES_PER_SPRITE * batchSize, 0, 0); + offset += batchSize; count -= batchSize; } } - /// - /// Flushes the batch. - /// - /// - /// Thrown when an Invalid Enum Argument error - /// condition occurs. - /// private void FlushBatch() { SpriteInfo[] spriteQueueForBatch; @@ -425,18 +407,11 @@ private void FlushBatch() _spriteQueueCount = 0; } - /// - /// Device on resize finished. - /// - /// The viewport. private void IDevice_onResizeFinished(ViewportF viewport) { Resize(viewport); } - /// - /// Prepare for rendering. - /// private void PrepareForRendering() { _context.VertexShader.Set(_vertexShader); @@ -468,13 +443,6 @@ private void PrepareForRendering() _context.InputAssembler.SetVertexBuffers(0, _vertexBuffer); } - /// - /// Updates the vertex from sprite information. - /// - /// [in,out] Information describing the sprite. - /// [in,out] If non-null, the vpct pointer. - /// The delta x coordinate. - /// The delta y coordinate. private static unsafe void UpdateVertexFromSpriteInfo(ref SpriteInfo spriteInfo, VertexPositionColorTexture* vpctPtr, float deltaX, @@ -639,12 +607,6 @@ private void Dispose(bool disposing) Utilities.Dispose(ref _samplerState); Utilities.Dispose(ref _depthStencilState); - Utilities.Dispose(ref _defaultBlendState); - Utilities.Dispose(ref _defaultRasterizerState); - Utilities.Dispose(ref _defaultSamplerState); - Utilities.Dispose(ref _defaultRasterizerScissorEnabledState); - Utilities.Dispose(ref _defaultDepthStencilState); - _vertexBuffer.Dispose(); _indexBuffer.Dispose(); _perFrameBuffer.Dispose(); @@ -657,6 +619,14 @@ private void Dispose(bool disposing) } } + /// + /// Finalizes an instance of the class. + /// + ~SpriteBatch() + { + Dispose(false); + } + /// public void Dispose() { diff --git a/src/Exomia.Framework/IDrawable.cs b/src/Exomia.Framework/IDrawable.cs index 4230cddc..5045703a 100644 --- a/src/Exomia.Framework/IDrawable.cs +++ b/src/Exomia.Framework/IDrawable.cs @@ -38,7 +38,7 @@ public interface IDrawable /// /// Gets a value indicating whether the method should be called by - /// . + /// the . /// /// /// true if this drawable component is visible; otherwise, false. diff --git a/src/Exomia.Framework/Input/InputState.cs b/src/Exomia.Framework/Input/InputState.cs index e2baaa1b..11063622 100644 --- a/src/Exomia.Framework/Input/InputState.cs +++ b/src/Exomia.Framework/Input/InputState.cs @@ -1,4 +1,14 @@ -namespace Exomia.Framework.Input +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +namespace Exomia.Framework.Input { /// /// Values that represent EventAction. @@ -9,9 +19,10 @@ public enum EventAction /// An enum constant representing the continue option. /// Continue = 0, + /// /// An enum constant representing the stop propagation option. /// StopPropagation = 1, } -} +} \ No newline at end of file diff --git a/src/Exomia.Framework/Input/KeyEventHandler.cs b/src/Exomia.Framework/Input/KeyEventHandler.cs index 28b18948..357c7d63 100644 --- a/src/Exomia.Framework/Input/KeyEventHandler.cs +++ b/src/Exomia.Framework/Input/KeyEventHandler.cs @@ -18,7 +18,7 @@ namespace Exomia.Framework.Input /// The key value. /// The modifiers. /// - /// An . + /// An . /// public delegate EventAction KeyEventHandler(int keyValue, KeyModifier modifiers); @@ -27,7 +27,7 @@ namespace Exomia.Framework.Input /// /// The key. /// - /// An . + /// An . /// public delegate EventAction KeyPressEventHandler(char key); @@ -36,7 +36,7 @@ namespace Exomia.Framework.Input /// /// The message. /// - /// An . + /// An . /// public delegate EventAction RawKeyEventHandler(in Message message); } \ No newline at end of file diff --git a/src/Exomia.Framework/Input/MouseEventHandler.cs b/src/Exomia.Framework/Input/MouseEventHandler.cs index 39401528..c7d25cb6 100644 --- a/src/Exomia.Framework/Input/MouseEventHandler.cs +++ b/src/Exomia.Framework/Input/MouseEventHandler.cs @@ -15,7 +15,7 @@ namespace Exomia.Framework.Input /// /// In mouse event information. /// - /// An . + /// An . /// public delegate EventAction MouseEventHandler(in MouseEventArgs mouseEventArgs); } \ No newline at end of file diff --git a/src/Exomia.Framework/Mathematics/Line2.cs b/src/Exomia.Framework/Mathematics/Line2.cs index 36a2425f..5c1c026f 100644 --- a/src/Exomia.Framework/Mathematics/Line2.cs +++ b/src/Exomia.Framework/Mathematics/Line2.cs @@ -27,17 +27,17 @@ namespace Exomia.Framework.Mathematics /// The first x value. /// public readonly float X1; - + /// /// The second x value. /// public readonly float X2; - + /// /// The first y value. /// public readonly float Y1; - + /// /// The second y value. /// diff --git a/src/Exomia.Framework/Resources/shaders/canvas.ehlsl b/src/Exomia.Framework/Resources/shaders/canvas.ehlsl index 99186dc2..daffd152 100644 --- a/src/Exomia.Framework/Resources/shaders/canvas.ehlsl +++ b/src/Exomia.Framework/Resources/shaders/canvas.ehlsl @@ -10,9 +10,6 @@ SamplerState g_Sampler : register(s0); cbuffer PerFrame : register(b0) { - float4x4 g_WorldMatrix; - float4x4 g_ViewMatrix; - float4x4 g_ProjectionMatrix; float4x4 g_WorldViewProjectionMatrix; }; @@ -21,13 +18,15 @@ struct VS_INPUT float4 p : SV_POSITION0; float4 c : COLOR0; float2 uv : TEXCOORD0; + float m : TEXCOORD1; }; struct PS_INPUT { float4 p : SV_POSITION0; float4 c : COLOR0; - float2 uv : TEXCOORD0; + float2 uv : TEXCOORD0; + float m : TEXCOORD1; }; PS_INPUT VSMain(VS_INPUT input) @@ -35,7 +34,8 @@ PS_INPUT VSMain(VS_INPUT input) PS_INPUT output = (PS_INPUT)0; output.p = mul(input.p, g_WorldViewProjectionMatrix); output.c = input.c / 255; - output.uv = input.uv; + output.uv = input.uv; + output.m = input.m; return output; } @@ -43,6 +43,13 @@ float4 PSMain(PS_INPUT input) : SV_TARGET { //discard; //clip(-1); - return g_Texture.Sample(g_Sampler, input.uv) * input.c; + switch (input.m) + { + default: + case 0: // texture mode + return g_Texture.Sample(g_Sampler, input.uv) * input.c; + case 0: // color mode + return input.c; + } } From 73d9db23562df5ca425df9866b4c7a8addbca60a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=A4tz?= Date: Wed, 18 Nov 2020 15:27:32 +0100 Subject: [PATCH 30/44] ref --- .../Exomia.Framework.Example.Canvas/MyGame.cs | 43 +- .../Content/ContentManager.cs | 1 - src/Exomia.Framework/DrawableComparer.cs | 10 - src/Exomia.Framework/Exomia.Framework.csproj | 9 +- src/Exomia.Framework/Graphics/Canvas.Arc.cs | 81 ++ src/Exomia.Framework/Graphics/Canvas.Line.cs | 120 +++ .../Graphics/Canvas.Polygon.cs | 138 +++ .../Graphics/Canvas.Rectangle.cs | 158 +++ .../Graphics/Canvas.SpriteFont.cs | 269 +++++ .../Graphics/Canvas.Texture.cs | 183 ++++ .../Graphics/Canvas.Triangle.cs | 240 +++++ .../Canvas.VertexPositionColorTexture.cs | 54 + src/Exomia.Framework/Graphics/Canvas.cs | 655 +----------- .../Graphics/SpriteBatch.Arc.cs | 119 +++ .../Graphics/SpriteBatch.Drawing.cs | 950 ------------------ .../Graphics/SpriteBatch.Line.cs | 106 ++ .../Graphics/SpriteBatch.Polygon.cs | 38 + .../Graphics/SpriteBatch.Rectangle.cs | 157 +++ .../Graphics/SpriteBatch.SpriteFont.cs | 313 ++++++ .../Graphics/SpriteBatch.Structs.cs | 81 ++ .../Graphics/SpriteBatch.Texture.cs | 338 +++++++ src/Exomia.Framework/Graphics/SpriteBatch.cs | 75 +- src/Exomia.Framework/Mathematics/Arc2.cs | 203 ++++ src/Exomia.Framework/Mathematics/Circle2.cs | 162 +++ src/Exomia.Framework/Mathematics/Line2.cs | 95 +- src/Exomia.Framework/Mathematics/Triangle2.cs | 226 +++++ .../Resources/shaders/canvas.ehlsl | 15 +- src/Exomia.Framework/UpdateableComparer.cs | 10 - src/Exomia.Framework/VectorI2.cs | 6 +- src/Exomia.Framework/VectorI3.cs | 6 +- 30 files changed, 3147 insertions(+), 1714 deletions(-) create mode 100644 src/Exomia.Framework/Graphics/Canvas.Arc.cs create mode 100644 src/Exomia.Framework/Graphics/Canvas.Line.cs create mode 100644 src/Exomia.Framework/Graphics/Canvas.Polygon.cs create mode 100644 src/Exomia.Framework/Graphics/Canvas.Rectangle.cs create mode 100644 src/Exomia.Framework/Graphics/Canvas.SpriteFont.cs create mode 100644 src/Exomia.Framework/Graphics/Canvas.Texture.cs create mode 100644 src/Exomia.Framework/Graphics/Canvas.Triangle.cs create mode 100644 src/Exomia.Framework/Graphics/Canvas.VertexPositionColorTexture.cs create mode 100644 src/Exomia.Framework/Graphics/SpriteBatch.Arc.cs delete mode 100644 src/Exomia.Framework/Graphics/SpriteBatch.Drawing.cs create mode 100644 src/Exomia.Framework/Graphics/SpriteBatch.Line.cs create mode 100644 src/Exomia.Framework/Graphics/SpriteBatch.Polygon.cs create mode 100644 src/Exomia.Framework/Graphics/SpriteBatch.Rectangle.cs create mode 100644 src/Exomia.Framework/Graphics/SpriteBatch.SpriteFont.cs create mode 100644 src/Exomia.Framework/Graphics/SpriteBatch.Structs.cs create mode 100644 src/Exomia.Framework/Graphics/SpriteBatch.Texture.cs create mode 100644 src/Exomia.Framework/Mathematics/Arc2.cs create mode 100644 src/Exomia.Framework/Mathematics/Circle2.cs create mode 100644 src/Exomia.Framework/Mathematics/Triangle2.cs diff --git a/examples/Exomia.Framework.Example.Canvas/MyGame.cs b/examples/Exomia.Framework.Example.Canvas/MyGame.cs index 29395ca2..bde0ae92 100644 --- a/examples/Exomia.Framework.Example.Canvas/MyGame.cs +++ b/examples/Exomia.Framework.Example.Canvas/MyGame.cs @@ -10,6 +10,7 @@ using Exomia.Framework.Components; using Exomia.Framework.Game; +using Exomia.Framework.Mathematics; using SharpDX; namespace Exomia.Framework.Example.Canvas @@ -21,6 +22,8 @@ sealed class MyGame : Game.Game { private Graphics.Canvas _canvas = null!; + private float k; + /// /// Initializes a new instance of the class. /// @@ -44,9 +47,11 @@ public MyGame() /// protected override void OnInitializeGameGraphicsParameters(ref GameGraphicsParameters parameters) { - parameters.IsMouseVisible = true; - parameters.Width = 1024; - parameters.Height = 786; + parameters.IsMouseVisible = true; + parameters.Width = 1600; + parameters.Height = 1024; + parameters.EnableMultiSampling = false; + parameters.MultiSampleCount = MultiSampleCount.MsaaX8; } /// @@ -97,7 +102,37 @@ protected override void Draw(GameTime gameTime) GraphicsDevice.Clear(Color.CornflowerBlue); _canvas.Begin(); - _canvas.DrawFillRectangle(new RectangleF(50, 50, 100, 100), Color.Red, 0, Vector2.Zero, 1); + + k += gameTime.DeltaTimeS / 2; + _canvas.DrawFillTriangle(new Triangle2(100, 50, 150, 100, 50, 100), Color.Red, 0, Vector2.Zero, 1.0f); + _canvas.DrawTriangle(new Triangle2(100, 50, 150, 100, 50, 100), Color.Green, 5.0f, 0, Vector2.Zero, 1.0f); + _canvas.DrawFillTriangle( + new Triangle2(100, 50, 150, 100, 50, 100), Color.Yellow, k, new Vector2(100, 50), 1.0f); + _canvas.DrawTriangle( + new Triangle2(100, 50, 150, 100, 50, 100), Color.Green, 5.0f, k, new Vector2(100, 50), 1.0f); + + _canvas.DrawFillRectangle(new RectangleF(200, 200, 100, 50), Color.Red, 0, Vector2.Zero, 1.0f); + _canvas.DrawRectangle(new RectangleF(200, 200, 100, 50), Color.Green, 5.0f, 0, Vector2.Zero, 1.0f); + _canvas.DrawFillRectangle(new RectangleF(200, 200, 100, 50), Color.Yellow, k, Vector2.Zero, 1.0f); + + _canvas.DrawLine(new Line2(300, 400, 345, 400), Color.Red, 5.0f, 1.0f); + _canvas.DrawLine(new Line2(400, 400, 450, 450), Color.Red, 5.0f, 1.0f); + _canvas.DrawLine(new Line2(300, 450, 345, 450), Color.Yellow, 5.0f, 1.0f); + _canvas.DrawLine(new Line2(400, 450, 450, 400), Color.Yellow, 5.0f, 1.0f); + + _canvas.DrawFillPolygon( + new[] + { + new Vector2(600, 600), new Vector2(650, 610), new Vector2(650, 720), new Vector2(450, 750), + new Vector2(400, 630) + }, Color.Red, 1.0f); + _canvas.DrawPolygon( + new[] + { + new Vector2(600, 600), new Vector2(650, 610), new Vector2(650, 720), new Vector2(450, 750), + new Vector2(400, 630) + }, Color.Yellow, 5.0f, 1.0f); + _canvas.End(); base.Draw(gameTime); diff --git a/src/Exomia.Framework/Content/ContentManager.cs b/src/Exomia.Framework/Content/ContentManager.cs index 07e3799e..b4fc52d3 100644 --- a/src/Exomia.Framework/Content/ContentManager.cs +++ b/src/Exomia.Framework/Content/ContentManager.cs @@ -521,7 +521,6 @@ public bool Equals(AssetKey other) /// public override bool Equals(object obj) { - if (obj is null) { return false; } return obj is AssetKey key && Equals(key); } diff --git a/src/Exomia.Framework/DrawableComparer.cs b/src/Exomia.Framework/DrawableComparer.cs index 1e6d1dcd..82420035 100644 --- a/src/Exomia.Framework/DrawableComparer.cs +++ b/src/Exomia.Framework/DrawableComparer.cs @@ -30,16 +30,6 @@ public int Compare(IDrawable left, IDrawable right) return 0; } - if (left == null) - { - return 1; - } - - if (right == null) - { - return -1; - } - return left.DrawOrder < right.DrawOrder ? 1 : -1; } } diff --git a/src/Exomia.Framework/Exomia.Framework.csproj b/src/Exomia.Framework/Exomia.Framework.csproj index 755ef0e2..5d66170a 100644 --- a/src/Exomia.Framework/Exomia.Framework.csproj +++ b/src/Exomia.Framework/Exomia.Framework.csproj @@ -62,7 +62,7 @@ - 1701;1702;IDE0063 + 1701;1702;IDE0063;IDE0079 NU1605 false logo_x192_Hcn_icon.ico @@ -195,6 +195,13 @@ + + + + Canvas.cs + + + diff --git a/src/Exomia.Framework/Graphics/Canvas.Arc.cs b/src/Exomia.Framework/Graphics/Canvas.Arc.cs new file mode 100644 index 00000000..5f4f3b43 --- /dev/null +++ b/src/Exomia.Framework/Graphics/Canvas.Arc.cs @@ -0,0 +1,81 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using Exomia.Framework.Mathematics; +using SharpDX; + +namespace Exomia.Framework.Graphics +{ + public sealed partial class Canvas + { + /// + /// Draws an arc. + /// + /// The center. + /// The radius. + /// The start. + /// The end. + /// The color. + /// The width of the line. + /// The opacity. + /// The segments. + public void DrawArc(in Vector2 center, + float radius, + float start, + float end, + in Color color, + float lineWidth, + float opacity) + { + DrawArc(new Arc2(center, radius, start, end), in color, lineWidth, opacity); + } + + /// + /// Draws an arc. + /// + /// The arc. + /// The color. + /// The width of the line. + /// The opacity. + public void DrawArc(in Arc2 arc, + in Color color, + float lineWidth, + float opacity) { } + + /// + /// Draws a filled arc. + /// + /// The center. + /// The radius. + /// The start. + /// The end. + /// The color. + /// The opacity. + public void DrawFillArc(in Vector2 center, + float radius, + float start, + float end, + in Color color, + float opacity) + { + DrawFillArc(new Arc2(center, radius, start, end), in color, opacity); + } + + /// + /// Draws a filled arc. + /// + /// The arc. + /// The color. + /// The opacity. + public void DrawFillArc(in Arc2 arc, + in Color color, + float opacity) { } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.Line.cs b/src/Exomia.Framework/Graphics/Canvas.Line.cs new file mode 100644 index 00000000..95f8791e --- /dev/null +++ b/src/Exomia.Framework/Graphics/Canvas.Line.cs @@ -0,0 +1,120 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using System.Runtime.CompilerServices; +using Exomia.Framework.Mathematics; +using SharpDX; +using SharpDX.Direct3D11; + +namespace Exomia.Framework.Graphics +{ + public sealed unsafe partial class Canvas + { + /// + /// Draw a line from to . + /// + /// The first point. + /// The second point. + /// The color. + /// The width of the line. + /// The opacity. + /// (Optional) The length factor. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawLine(in Vector2 point1, + in Vector2 point2, + in Color color, + float lineWidth, + float opacity, + float lengthFactor = 1.0f) + { + DrawLine(new Line2(point1, point2), color, lineWidth, opacity, lengthFactor); + } + + /// + /// Draw a line. + /// + /// The line. + /// The color. + /// The width of the line. + /// The opacity. + /// (Optional) The length factor. + public void DrawLine(in Line2 line, + in Color color, + float lineWidth, + float opacity, + float lengthFactor = 1.0f) + { + float dx = line.X2 - line.X1; + float dy = line.Y2 - line.Y1; + + double dl = Math.Sqrt((dx * dx) + (dy * dy)); + float nx = (float)((dy / dl) * lineWidth); + float ny = (float)((dx / dl) * lineWidth); + + DataBox box = _context.MapSubresource( + _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); + VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)box.DataPointer; + + // p1 + vertex->X = line.X1; + vertex->Y = line.Y1; + + vertex->R = color.R * opacity; + vertex->G = color.G * opacity; + vertex->B = color.B * opacity; + vertex->A = color.A * opacity; + + vertex->M = 0.0f; + vertex++; + + // p2 + vertex->X = line.X2; + vertex->Y = line.Y2; + + vertex->R = color.R * opacity; + vertex->G = color.G * opacity; + vertex->B = color.B * opacity; + vertex->A = color.A * opacity; + + vertex->M = 0.0f; + vertex++; + + // p2' + vertex->X = line.X2 - nx; + vertex->Y = line.Y2 + ny; + + vertex->R = color.R * opacity; + vertex->G = color.G * opacity; + vertex->B = color.B * opacity; + vertex->A = color.A * opacity; + + vertex->M = 0.0f; + vertex++; + + // p1' + vertex->X = line.X1 - nx; + vertex->Y = line.Y1 + ny; + + vertex->R = color.R * opacity; + vertex->G = color.G * opacity; + vertex->B = color.B * opacity; + vertex->A = color.A * opacity; + + vertex->M = 0.0f; + + _context.UnmapSubresource(_vertexBuffer, 0); + + PrepareForRendering(); + _context.PixelShader.SetShaderResource(0, _whiteTexture.TextureView); + _context.DrawIndexed(6, 0, 0); + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.Polygon.cs b/src/Exomia.Framework/Graphics/Canvas.Polygon.cs new file mode 100644 index 00000000..562cbbc2 --- /dev/null +++ b/src/Exomia.Framework/Graphics/Canvas.Polygon.cs @@ -0,0 +1,138 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using System.Collections.Generic; +using Exomia.Framework.Mathematics; +using SharpDX; +using SharpDX.Direct3D11; + +namespace Exomia.Framework.Graphics +{ + public sealed unsafe partial class Canvas + { + /// + /// Draws a polygon. + /// + /// he vertices. + /// The color. + /// The width of the line. + /// The opacity. + public void DrawPolygon(Vector2[] vertices, in Color color, float lineWidth, float opacity) + { + if (vertices.Length < 2) { throw new ArgumentOutOfRangeException(nameof(vertices.Length)); } + + Color scaledColor = color * opacity; + + DataBox box = _context.MapSubresource( + _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); + VertexPositionColorTextureMode* vpctmPtr = (VertexPositionColorTextureMode*)box.DataPointer; + + Line2 previous = new Line2(vertices[vertices.Length - 1], vertices[0]); + Line2 perpendicularPrevious = previous.GetPerpendicular(lineWidth); + + Line2 current = new Line2(vertices[0], vertices[1]); + Line2 perpendicularCurrent = current.GetPerpendicular(lineWidth); + + if (!perpendicularPrevious.IntersectWith(perpendicularCurrent, out Vector2 ipE)) + { + ipE = new Vector2(perpendicularCurrent.X1, perpendicularCurrent.Y1); + } + + Vector2 ip1 = ipE; + int indexCount = 0; + for (int i = 1; i < vertices.Length - 1; i++) + { + Line2 next = new Line2(vertices[i], vertices[i + 1]); + Line2 perpendicularNext = next.GetPerpendicular(lineWidth); + + if (!perpendicularCurrent.IntersectWith(perpendicularNext, out Vector2 ip2)) + { + ip2 = new Vector2(perpendicularNext.X1, perpendicularNext.Y1); + } + + DrawRect(ref vpctmPtr, current, new Line2(ip1.X, ip1.Y, ip2.X, ip2.Y), in scaledColor); + indexCount++; + + current = next; + perpendicularCurrent = perpendicularNext; + ip1 = ip2; + } + + if (!perpendicularCurrent.IntersectWith(perpendicularPrevious, out Vector2 ip3)) + { + ip3 = new Vector2(perpendicularPrevious.X1, perpendicularPrevious.Y1); + } + + DrawRect(ref vpctmPtr, current, new Line2(ip1.X, ip1.Y, ip3.X, ip3.Y), in scaledColor); + DrawRect(ref vpctmPtr, previous, new Line2(ip3.X, ip3.Y, ipE.X, ipE.Y), in scaledColor); + + indexCount += 2; + + _context.UnmapSubresource(_vertexBuffer, 0); + + PrepareForRendering(); + _context.PixelShader.SetShaderResource(0, _whiteTexture.TextureView); + _context.DrawIndexed(indexCount * 6, 0, 0); + } + + /// + /// Draws a filled polygon. + /// + /// The vertices. + /// The color. + /// The opacity. + public void DrawFillPolygon(Vector2[] vertices, in Color color, float opacity) + { + if (vertices.Length < 3) { throw new ArgumentOutOfRangeException(nameof(vertices.Length)); } + + DataBox box = _context.MapSubresource( + _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); + VertexPositionColorTextureMode* vpctPtr = (VertexPositionColorTextureMode*)box.DataPointer; + + // TODO: refactor; remove list; place directly into _vertexBuffer + List vs = new List(); + int indexCount = 0; + for (int i = 1; i < vertices.Length; i += 2) + { + indexCount++; + vs.Add(vertices[0]); + vs.Add(vertices[i]); + vs.Add(vertices[i + 1]); + if (i + 2 < vertices.Length) + { + indexCount++; + vs.Add(vertices[i + 2]); + } + } + + for (int j = 0; j < vs.Count; j++) + { + VertexPositionColorTextureMode* vertex = vpctPtr + j; + + vertex->X = vs[j].X; + vertex->Y = vs[j].Y; + + vertex->R = color.R * opacity; + vertex->G = color.G * opacity; + vertex->B = color.B * opacity; + vertex->A = color.A * opacity; + + vertex->M = 0.0f; + } + + _context.UnmapSubresource(_vertexBuffer, 0); + + PrepareForRendering(); + _context.PixelShader.SetShaderResource(0, _whiteTexture.TextureView); + _context.DrawIndexed(indexCount * 3, 0, 0); + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs b/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs new file mode 100644 index 00000000..ed76d507 --- /dev/null +++ b/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs @@ -0,0 +1,158 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using Exomia.Framework.Mathematics; +using SharpDX; +using SharpDX.Direct3D11; + +namespace Exomia.Framework.Graphics +{ + public sealed unsafe partial class Canvas + { + /// + /// Draw rectangle. + /// + /// The destination rectangle. + /// The color. + /// The width of the line. + /// The rotation. + /// The origin. + /// The opacity. + public void DrawRectangle(in RectangleF destinationRectangle, + in Color color, + float lineWidth, + float rotation, + in Vector2 origin, + float opacity) { } + + /// + /// Draw fill rectangle. + /// + /// The destination rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + public void DrawFillRectangle(in RectangleF destinationRectangle, + in Color color, + float rotation, + in Vector2 origin, + float opacity) + { + DataBox box = _context.MapSubresource( + _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); + VertexPositionColorTextureMode* vpctmPtr = (VertexPositionColorTextureMode*)box.DataPointer; + + if (rotation == 0f) + { + for (int j = 0; j < 4; j++) + { + VertexPositionColorTextureMode* vertex = vpctmPtr + j; + + Vector2 corner = s_cornerOffsets[j]; + float posX = (corner.X - origin.X) * destinationRectangle.Width; + float posY = (corner.Y - origin.Y) * destinationRectangle.Height; + + vertex->X = destinationRectangle.X + posX; + vertex->Y = destinationRectangle.Y + posY; + + vertex->R = color.R * opacity; + vertex->G = color.G * opacity; + vertex->B = color.B * opacity; + vertex->A = color.A * opacity; + + vertex->M = 0.0f; + } + } + else + { + float cos = (float)Math.Cos(rotation); + float sin = (float)Math.Sin(rotation); + + for (int j = 0; j < 4; j++) + { + VertexPositionColorTextureMode* vertex = vpctmPtr + j; + + Vector2 corner = s_cornerOffsets[j]; + float posX = (corner.X - origin.X) * destinationRectangle.Width; + float posY = (corner.Y - origin.Y) * destinationRectangle.Height; + + vertex->X = (destinationRectangle.X + (posX * cos)) - (posY * sin); + vertex->Y = destinationRectangle.Y + (posX * sin) + (posY * cos); + + vertex->R = color.R * opacity; + vertex->G = color.G * opacity; + vertex->B = color.B * opacity; + vertex->A = color.A * opacity; + + vertex->M = 0.0f; + } + } + + _context.UnmapSubresource(_vertexBuffer, 0); + + PrepareForRendering(); + _context.PixelShader.SetShaderResource(0, _whiteTexture.TextureView); + _context.DrawIndexed(6, 0, 0); + } + + private static void DrawRect(ref VertexPositionColorTextureMode* v, in Line2 lineA, in Line2 lineB, in Color c) + { + // p1 + v->X = lineA.X1; + v->Y = lineA.Y1; + + v->R = c.R; + v->G = c.G; + v->B = c.B; + v->A = c.A; + + v->M = 0.0f; + v++; + + // p2 + v->X = lineA.X2; + v->Y = lineA.Y2; + + v->R = c.R; + v->G = c.G; + v->B = c.B; + v->A = c.A; + + v->M = 0.0f; + v++; + + // p2' + v->X = lineB.X2; + v->Y = lineB.Y2; + + v->R = c.R; + v->G = c.G; + v->B = c.B; + v->A = c.A; + + v->M = 0.0f; + v++; + + // p1' + v->X = lineB.X1; + v->Y = lineB.Y1; + + v->R = c.R; + v->G = c.G; + v->B = c.B; + v->A = c.A; + + v->M = 0.0f; + v++; + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.SpriteFont.cs b/src/Exomia.Framework/Graphics/Canvas.SpriteFont.cs new file mode 100644 index 00000000..73f6c91f --- /dev/null +++ b/src/Exomia.Framework/Graphics/Canvas.SpriteFont.cs @@ -0,0 +1,269 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System.Runtime.CompilerServices; +using System.Text; +using SharpDX; + +namespace Exomia.Framework.Graphics +{ + public sealed partial class Canvas + { + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, string text, in Vector2 position, in Color color) + { + font.Draw(DrawTextInternal, text, position, color, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0f); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + /// The rotation. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, string text, in Vector2 position, in Color color, float rotation) + { + font.Draw(DrawTextInternal, text, position, color, rotation, Vector2.Zero, 1.0f, SpriteEffects.None, 0f); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + string text, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects) + { + font.Draw(DrawTextInternal, text, position, color, rotation, origin, opacity, effects, 0f); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The start. + /// The end. + /// The position. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + string text, + int start, + int end, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects) + { + font.Draw(DrawTextInternal, text, start, end, position, color, rotation, origin, opacity, effects, 0f); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The start. + /// The end. + /// The position. + /// The dimension. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + string text, + int start, + int end, + in Vector2 position, + in Size2F dimension, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects) + { + font.Draw( + DrawTextInternal, text, start, end, position, dimension, color, rotation, origin, opacity, effects, 0f); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + /// The rotation. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, in Color color, float rotation) + { + font.Draw(DrawTextInternal, text, position, color, rotation, Vector2.Zero, 1.0f, SpriteEffects.None, 0f); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + StringBuilder text, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects) + { + font.Draw(DrawTextInternal, text, position, color, rotation, origin, opacity, effects, 0f); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The start. + /// The end. + /// The position. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + StringBuilder text, + int start, + int end, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects) + { + font.Draw(DrawTextInternal, text, start, end, position, color, rotation, origin, opacity, effects, 0f); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The start. + /// The end. + /// The position. + /// The dimension. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + StringBuilder text, + int start, + int end, + in Vector2 position, + in Size2F dimension, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects) + { + font.Draw( + DrawTextInternal, text, start, end, position, dimension, color, rotation, origin, opacity, effects, 0f); + } + + /// + /// Draw text internal. + /// + /// The texture. + /// The position. + /// The source rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The scale. + /// The opacity. + /// The effects. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void DrawTextInternal(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float scale, + float opacity, + SpriteEffects effects, + float layerDepth) + { + DrawSprite( + texture, new RectangleF(position.X, position.Y, scale, scale), true, sourceRectangle, color, + rotation, origin, opacity, effects); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, in Color color) + { + font.Draw(DrawTextInternal, text, position, color, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0f); + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.Texture.cs b/src/Exomia.Framework/Graphics/Canvas.Texture.cs new file mode 100644 index 00000000..51081ee8 --- /dev/null +++ b/src/Exomia.Framework/Graphics/Canvas.Texture.cs @@ -0,0 +1,183 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System.Runtime.CompilerServices; +using SharpDX; + +namespace Exomia.Framework.Graphics +{ + public sealed partial class Canvas + { + /// + /// Draws. + /// + /// The texture. + /// The position. + /// The color. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Draw(Texture texture, in Vector2 position, in Color color) + { + DrawSprite( + texture, new RectangleF(position.X, position.Y, 1f, 1f), true, + s_nullRectangle, color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None); + } + + /// + /// Draws. + /// + /// The texture. + /// The destination rectangle. + /// The color. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Draw(Texture texture, in RectangleF destinationRectangle, in Color color) + { + DrawSprite( + texture, destinationRectangle, false, + s_nullRectangle, color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None); + } + + /// + /// Draws. + /// + /// The texture. + /// The position. + /// The source rectangle. + /// The color. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Draw(Texture texture, in Vector2 position, in Rectangle? sourceRectangle, in Color color) + { + DrawSprite( + texture, new RectangleF(position.X, position.Y, 1f, 1f), true, + sourceRectangle, color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None); + } + + /// + /// Draws. + /// + /// The texture. + /// The destination rectangle. + /// The source rectangle. + /// The color. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Draw(Texture texture, + in RectangleF destinationRectangle, + in Rectangle? sourceRectangle, + in Color color) + { + DrawSprite( + texture, destinationRectangle, false, + sourceRectangle, color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None); + } + + /// + /// Draws. + /// + /// The texture. + /// The destination rectangle. + /// The source rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Draw(Texture texture, + in RectangleF destinationRectangle, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects) + { + DrawSprite( + texture, destinationRectangle, false, + sourceRectangle, color, rotation, origin, opacity, effects); + } + + /// + /// Draws. + /// + /// The texture. + /// The position. + /// The source rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The scale. + /// The opacity. + /// The effects. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Draw(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float scale, + float opacity, + SpriteEffects effects) + { + DrawSprite( + texture, new RectangleF(position.X, position.Y, scale, scale), true, + sourceRectangle, color, rotation, origin, opacity, effects); + } + + /// + /// Draws. + /// + /// The texture. + /// The position. + /// The source rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The scale. + /// The opacity. + /// The effects. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Draw(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + in Vector2 scale, + float opacity, + SpriteEffects effects) + { + DrawSprite( + texture, new RectangleF(position.X, position.Y, scale.X, scale.Y), true, + sourceRectangle, color, rotation, origin, opacity, effects); + } + + /// + /// Draw sprite. + /// + /// The texture. + /// Destination for the. + /// True to scale destination. + /// The source rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + private void DrawSprite(Texture texture, + in RectangleF destination, + bool scaleDestination, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects) { } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.Triangle.cs b/src/Exomia.Framework/Graphics/Canvas.Triangle.cs new file mode 100644 index 00000000..98d2590a --- /dev/null +++ b/src/Exomia.Framework/Graphics/Canvas.Triangle.cs @@ -0,0 +1,240 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using System.Runtime.CompilerServices; +using Exomia.Framework.Mathematics; +using SharpDX; +using SharpDX.Direct3D11; + +namespace Exomia.Framework.Graphics +{ + public sealed unsafe partial class Canvas + { + /// + /// Draws a triangle. + /// + /// The first point. + /// The second point. + /// The third point. + /// The color. + /// The width of the line. + /// The rotation. + /// The origin. + /// The opacity. + /// + /// The points 1 to 3 have to match the , + /// so for default, with is set, + /// the points have to use one of the following winding order: + /// p1 p2 p3 + /// /\ /\ /\ + /// / \ / \ / \ + /// /____\ /____\ /____\ + /// p3 p2 p1 p3 p2 p1. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawTriangle(in Vector2 point1, + in Vector2 point2, + in Vector2 point3, + in Color color, + float lineWidth, + float rotation, + in Vector2 origin, + float opacity) + { + DrawTriangle(new Triangle2(point1, point2, point3), color, lineWidth, rotation, in origin, opacity); + } + + /// + /// Draws a triangle. + /// + /// The triangle. + /// The color. + /// The width of the line. + /// The rotation. + /// The origin. + /// The opacity. + /// Thrown when one or more arguments have unsupported or illegal values. + /// + /// The points 1 to 3 have to match the , + /// so for default, with is set, + /// the points have to use one of the following winding order: + /// p1 p2 p3 + /// /\ /\ /\ + /// / \ / \ / \ + /// /____\ /____\ /____\ + /// p3 p2 p1 p3 p2 p1. + /// + public void DrawTriangle(in Triangle2 triangle, + in Color color, + float lineWidth, + float rotation, + in Vector2 origin, + float opacity) + { + Triangle2 t = rotation == 0.0 ? triangle : Triangle2.RotateAround(triangle, rotation, origin); + Color scaledColor = color * opacity; + + DataBox box = _context.MapSubresource( + _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); + VertexPositionColorTextureMode* vpctmPtr = (VertexPositionColorTextureMode*)box.DataPointer; + + Line2 a = new Line2(t.X1, t.Y1, t.X2, t.Y2); + Line2 perpendicularA = a.GetPerpendicular(lineWidth); + + Line2 b = new Line2(t.X2, t.Y2, t.X3, t.Y3); + Line2 perpendicularB = b.GetPerpendicular(lineWidth); + + Line2 c = new Line2(t.X3, t.Y3, t.X1, t.Y1); + Line2 perpendicularC = c.GetPerpendicular(lineWidth); + + if (!perpendicularA.IntersectWith(perpendicularB, out Vector2 ipAb)) + { + throw new ArgumentException("The lines a and b are parallel to each other! Check the triangle points!"); + } + + if (!perpendicularB.IntersectWith(perpendicularC, out Vector2 ipBc)) + { + throw new ArgumentException("The lines b and c are parallel to each other! Check the triangle points!"); + } + + if (!perpendicularC.IntersectWith(perpendicularA, out Vector2 ipCa)) + { + throw new ArgumentException("The lines c and a are parallel to each other! Check the triangle points!"); + } + + DrawRect(ref vpctmPtr, a, new Line2(ipCa.X, ipCa.Y, ipAb.X, ipAb.Y), in scaledColor); + DrawRect(ref vpctmPtr, b, new Line2(ipAb.X, ipAb.Y, ipBc.X, ipBc.Y), in scaledColor); + DrawRect(ref vpctmPtr, c, new Line2(ipBc.X, ipBc.Y, ipCa.X, ipCa.Y), in scaledColor); + + _context.UnmapSubresource(_vertexBuffer, 0); + + PrepareForRendering(); + _context.PixelShader.SetShaderResource(0, _whiteTexture.TextureView); + _context.DrawIndexed(18, 0, 0); + } + + /// + /// Draws a filled triangle. + /// + /// The first point. + /// The second point. + /// The third point. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// + /// The points 1 to 3 have to match the , + /// so for default, with is set, + /// the points have to use one of the following winding order: + /// p1 p2 p3 + /// /\ /\ /\ + /// / \ / \ / \ + /// /____\ /____\ /____\ + /// p3 p2 p1 p3 p2 p1. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawFillTriangle(in Vector2 point1, + in Vector2 point2, + in Vector2 point3, + in Color color, + float rotation, + in Vector2 origin, + float opacity) + { + DrawFillTriangle(new Triangle2(point1, point2, point3), color, rotation, origin, opacity); + } + + /// + /// Draws a filled triangle. + /// + /// The triangle. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// + /// The points 1 to 3 from the have to match the + /// , + /// so for default, with is set, + /// the points have to use one of the following winding order: + /// p1 p2 p3 + /// /\ /\ /\ + /// / \ / \ / \ + /// /____\ /____\ /____\ + /// p3 p2 p1 p3 p2 p1. + /// + public void DrawFillTriangle(in Triangle2 triangle, + in Color color, + float rotation, + in Vector2 origin, + float opacity) + { + DataBox box = _context.MapSubresource( + _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); + VertexPositionColorTextureMode* vpctmPtr = (VertexPositionColorTextureMode*)box.DataPointer; + + if (rotation == 0.0f) + { + for (int i = 0; i < 3; i++) + { + VertexPositionColorTextureMode* vertex = vpctmPtr + i; + + fixed (Triangle2* t = &triangle) + { + float* tf = (float*)t; + vertex->X = *(tf + (i << 1)); + vertex->Y = *(tf + (i << 1) + 1); + } + + vertex->R = color.R * opacity; + vertex->G = color.G * opacity; + vertex->B = color.B * opacity; + vertex->A = color.A * opacity; + + vertex->M = 0.0f; + } + } + else + { + float cos = (float)Math.Cos(rotation); + float sin = (float)Math.Sin(rotation); + + for (int i = 0; i < 3; i++) + { + VertexPositionColorTextureMode* vertex = vpctmPtr + i; + + fixed (Triangle2* t = &triangle) + { + float* tf = (float*)t; + float x = *(tf + (i << 1)) - origin.X; + float y = *(tf + (i << 1) + 1) - origin.Y; + vertex->X = ((cos * x) - (sin * y)) + origin.X; + vertex->Y = (sin * x) + (cos * y) + origin.Y; + } + + vertex->R = color.R * opacity; + vertex->G = color.G * opacity; + vertex->B = color.B * opacity; + vertex->A = color.A * opacity; + + vertex->M = 0.0f; + } + } + + _context.UnmapSubresource(_vertexBuffer, 0); + + PrepareForRendering(); + _context.PixelShader.SetShaderResource(0, _whiteTexture.TextureView); + _context.DrawIndexed(3, 0, 0); + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.VertexPositionColorTexture.cs b/src/Exomia.Framework/Graphics/Canvas.VertexPositionColorTexture.cs new file mode 100644 index 00000000..d9c6b84d --- /dev/null +++ b/src/Exomia.Framework/Graphics/Canvas.VertexPositionColorTexture.cs @@ -0,0 +1,54 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System.Runtime.InteropServices; + +namespace Exomia.Framework.Graphics +{ + public sealed partial class Canvas + { + [StructLayout(LayoutKind.Explicit, Size = VERTEX_STRIDE)] + private struct VertexPositionColorTextureMode + { + [FieldOffset(0)] + public float X; + + [FieldOffset(4)] + public float Y; + + [FieldOffset(8)] + public readonly float Z; + + [FieldOffset(12)] + public readonly float W; + + [FieldOffset(16)] + public float R; + + [FieldOffset(20)] + public float G; + + [FieldOffset(24)] + public float B; + + [FieldOffset(28)] + public float A; + + [FieldOffset(8)] + public readonly float U; + + [FieldOffset(12)] + public readonly float V; + + [FieldOffset(32)] + public float M; + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.cs b/src/Exomia.Framework/Graphics/Canvas.cs index 7290159e..7260ec9e 100644 --- a/src/Exomia.Framework/Graphics/Canvas.cs +++ b/src/Exomia.Framework/Graphics/Canvas.cs @@ -11,8 +11,6 @@ using System; using System.IO; using System.Reflection; -using System.Runtime.InteropServices; -using System.Text; using Exomia.Framework.Graphics.Buffers; using Exomia.Framework.Graphics.Shader; using Exomia.Framework.Resources; @@ -25,16 +23,14 @@ namespace Exomia.Framework.Graphics /// /// A canvas. This class cannot be inherited. /// - public sealed class Canvas : IDisposable + public sealed partial class Canvas : IDisposable { private const int MAX_BATCH_SIZE = 1 << 13; private const int INITIAL_QUEUE_SIZE = 1 << 7; - private const int VERTICES_PER_SPRITE = 4; - private const int INDICES_PER_SPRITE = 6; - private const int MAX_VERTEX_COUNT = MAX_BATCH_SIZE * VERTICES_PER_SPRITE; - private const int MAX_INDEX_COUNT = MAX_BATCH_SIZE * INDICES_PER_SPRITE; + private const int MAX_VERTEX_COUNT = MAX_BATCH_SIZE * 4; + private const int MAX_INDEX_COUNT = MAX_BATCH_SIZE * 6; private const int BATCH_SEQUENTIAL_THRESHOLD = 1 << 9; - private const int VERTEX_STRIDE = sizeof(float) * 11; + private const int VERTEX_STRIDE = sizeof(float) * 9; private static readonly ushort[] s_indices; private static readonly Vector2 s_vector2Zero = Vector2.Zero; @@ -84,12 +80,14 @@ static Canvas() if (MAX_INDEX_COUNT > ushort.MaxValue) #pragma warning disable 162 { +#pragma warning restore IDE0079 // Remove unnecessary suppression + // ReSharper disable once NotResolvedInText throw new ArgumentOutOfRangeException("MAX_INDEX_COUNT->MAX_BATCH_SIZE"); } #pragma warning restore 162 s_indices = new ushort[MAX_INDEX_COUNT]; - for (int i = 0, k = 0; i < MAX_INDEX_COUNT; i += INDICES_PER_SPRITE, k += VERTICES_PER_SPRITE) + for (int i = 0, k = 0; i < MAX_INDEX_COUNT; i += 6, k += 4) { s_indices[i + 0] = (ushort)(k + 0); s_indices[i + 1] = (ushort)(k + 1); @@ -110,7 +108,7 @@ public Canvas(IGraphicsDevice graphicsDevice) _device = graphicsDevice.Device; _context = graphicsDevice.DeviceContext; - _defaultBlendState = graphicsDevice.BlendStates.AlphaBlend; + _defaultBlendState = graphicsDevice.BlendStates.Default; _defaultSamplerState = graphicsDevice.SamplerStates.LinearWrap; _defaultDepthStencilState = graphicsDevice.DepthStencilStates.None; _defaultRasterizerState = graphicsDevice.RasterizerStates.CullBackDepthClipOff; @@ -135,10 +133,10 @@ public Canvas(IGraphicsDevice graphicsDevice) _vertexInputLayout = group.CreateInputLayout(graphicsDevice, Shader.Shader.Type.VertexShader); } - _vertexBuffer = VertexBuffer.Create(graphicsDevice, MAX_VERTEX_COUNT); + _vertexBuffer = VertexBuffer.Create(graphicsDevice, MAX_VERTEX_COUNT); _perFrameBuffer = ConstantBuffer.Create(graphicsDevice); - graphicsDevice.ResizeFinished += IDevice_onResizeFinished; + graphicsDevice.ResizeFinished += GraphicsDeviceOnResizeFinished; Resize(graphicsDevice.Viewport); } @@ -183,7 +181,7 @@ public void Resize(float width, float height) } /// - /// Begins. + /// Begins a new batch. /// /// Thrown when the requested operation is invalid. /// (Optional) State of the blend. @@ -220,7 +218,7 @@ public void Begin(BlendState? blendState = null, } /// - /// Ends this object. + /// Ends the current batch. /// /// Thrown when the requested operation is invalid. public void End() @@ -230,36 +228,16 @@ public void End() throw new InvalidOperationException("Begin must be called before End"); } - PrepareForRendering(); + //PrepareForRendering(); _isBeginCalled = false; } - #region Line - - /// - /// Draw line. - /// - /// The first point. - /// The second point. - /// The color. - /// Width of the line. - /// The opacity. - /// (Optional) The length factor. - public void DrawLine(in Vector2 point1, - in Vector2 point2, - in Color color, - float lineWidth, - float opacity, - float lengthFactor = 1.0f) + private void GraphicsDeviceOnResizeFinished(ViewportF viewport) { - DrawFillRectangle( - new RectangleF(point1.X, point1.Y, Vector2.Distance(point1, point2) * lengthFactor, lineWidth), color, - (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X), s_vector2Zero, opacity); + Resize(viewport); } - #endregion - private void PrepareForRendering() { _context.VertexShader.Set(_vertexShader); @@ -291,609 +269,6 @@ private void PrepareForRendering() _context.InputAssembler.SetVertexBuffers(0, _vertexBuffer); } - /// - /// Device on resize finished. - /// - /// The viewport. - private static void IDevice_onResizeFinished(ViewportF viewport) { } - - [StructLayout(LayoutKind.Explicit, Size = VERTEX_STRIDE)] - private struct VertexPositionColorTexture - { - [FieldOffset(0)] - public readonly float X; - - [FieldOffset(4)] - public readonly float Y; - - [FieldOffset(8)] - public readonly float Z; - - [FieldOffset(12)] - public readonly float W; - - [FieldOffset(16)] - public readonly float R; - - [FieldOffset(20)] - public readonly float G; - - [FieldOffset(24)] - public readonly float B; - - [FieldOffset(28)] - public readonly float A; - - [FieldOffset(32)] - public readonly float U; - - [FieldOffset(36)] - public readonly float V; - - [FieldOffset(40)] - public readonly float M; - } - - #region Triangle - - /// - /// Draw triangle. - /// - /// The first point. - /// The second point. - /// The third point. - /// The color. - /// Width of the line. - /// The opacity. - public void DrawTriangle(in Vector2 point1, - in Vector2 point2, - in Vector2 point3, - in Color color, - float lineWidth, - float opacity) { } - - /// - /// Draw fill triangle. - /// - /// The first point. - /// The second point. - /// The third point. - /// The color. - /// Width of the line. - /// The opacity. - public void DrawFillTriangle(in Vector2 point1, - in Vector2 point2, - in Vector2 point3, - in Color color, - float lineWidth, - float opacity) { } - - #endregion - - #region Rectangle - - /// - /// Draw rectangle. - /// - /// Destination rectangle. - /// The color. - /// Width of the line. - /// The rotation. - /// The origin. - /// The opacity. - public void DrawRectangle(in RectangleF destinationRectangle, - in Color color, - float lineWidth, - float rotation, - in Vector2 origin, - float opacity) { } - - /// - /// Draw fill rectangle. - /// - /// Destination rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - public void DrawFillRectangle(in RectangleF destinationRectangle, - in Color color, - float rotation, - in Vector2 origin, - float opacity) { } - - #endregion - - #region Arc - - /// - /// Draw arc. - /// - /// The center. - /// The radius. - /// The start. - /// The end. - /// The width. - /// The height. - /// The color. - /// Width of the line. - /// The opacity. - /// The segments. - public void DrawArc(in Vector2 center, - float radius, - float start, - float end, - float width, - float height, - in Color color, - float lineWidth, - float opacity, - int segments) { } - - /// - /// Draw fill arc. - /// - /// The center. - /// The radius. - /// The start. - /// The end. - /// The width. - /// The height. - /// The color. - /// Width of the line. - /// The opacity. - /// The segments. - public void DrawFillArc(in Vector2 center, - float radius, - float start, - float end, - float width, - float height, - in Color color, - float lineWidth, - float opacity, - int segments) { } - - #endregion - - #region Polygon - - /// - /// Draw polygon. - /// - /// The vertex. - /// The color. - /// Width of the line. - /// The opacity. - public void DrawPolygon(Vector2[] vertex, in Color color, float lineWidth, float opacity) - { - if (vertex.Length > 1) - { - int l = vertex.Length - 1; - for (int i = 0; i < l; i++) - { - DrawLine(vertex[i], vertex[i + 1], color, lineWidth, opacity); - } - DrawLine(vertex[l], vertex[0], color, lineWidth, opacity); - } - } - - /// - /// Draw fill polygon. - /// - /// The vertex. - /// The color. - /// Width of the line. - /// The opacity. - public void DrawFillPolygon(Vector2[] vertex, in Color color, float lineWidth, float opacity) { } - - #endregion - - #region Texture - - /// - /// Draws. - /// - /// The texture. - /// The position. - /// The color. - public void Draw(Texture texture, in Vector2 position, in Color color) - { - DrawSprite( - texture, new RectangleF(position.X, position.Y, 1f, 1f), true, - s_nullRectangle, color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None); - } - - /// - /// Draws. - /// - /// The texture. - /// Destination rectangle. - /// The color. - public void Draw(Texture texture, in RectangleF destinationRectangle, in Color color) - { - DrawSprite( - texture, destinationRectangle, false, - s_nullRectangle, color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None); - } - - /// - /// Draws. - /// - /// The texture. - /// The position. - /// Source rectangle. - /// The color. - public void Draw(Texture texture, in Vector2 position, in Rectangle? sourceRectangle, in Color color) - { - DrawSprite( - texture, new RectangleF(position.X, position.Y, 1f, 1f), true, - sourceRectangle, color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None); - } - - /// - /// Draws. - /// - /// The texture. - /// Destination rectangle. - /// Source rectangle. - /// The color. - public void Draw(Texture texture, - in RectangleF destinationRectangle, - in Rectangle? sourceRectangle, - in Color color) - { - DrawSprite( - texture, destinationRectangle, false, - sourceRectangle, color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None); - } - - /// - /// Draws. - /// - /// The texture. - /// Destination rectangle. - /// Source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - public void Draw(Texture texture, - in RectangleF destinationRectangle, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects) - { - DrawSprite( - texture, destinationRectangle, false, - sourceRectangle, color, rotation, origin, opacity, effects); - } - - /// - /// Draws. - /// - /// The texture. - /// The position. - /// Source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The scale. - /// The opacity. - /// The effects. - public void Draw(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float scale, - float opacity, - SpriteEffects effects) - { - DrawSprite( - texture, new RectangleF(position.X, position.Y, scale, scale), true, - sourceRectangle, color, rotation, origin, opacity, effects); - } - - /// - /// Draws. - /// - /// The texture. - /// The position. - /// Source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The scale. - /// The opacity. - /// The effects. - public void Draw(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - in Vector2 scale, - float opacity, - SpriteEffects effects) - { - DrawSprite( - texture, new RectangleF(position.X, position.Y, scale.X, scale.Y), true, - sourceRectangle, color, rotation, origin, opacity, effects); - } - - /// - /// Draw sprite. - /// - /// The texture. - /// Destination for the. - /// True to scale destination. - /// Source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - private void DrawSprite(Texture texture, - in RectangleF destination, - bool scaleDestination, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects) { } - - #endregion - - #region SpiteFont - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - public void DrawText(SpriteFont font, string text, in Vector2 position, in Color color) - { - font.Draw(DrawTextInternal, text, position, color, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0f); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. - public void DrawText(SpriteFont font, string text, in Vector2 position, in Color color, float rotation) - { - font.Draw(DrawTextInternal, text, position, color, rotation, Vector2.Zero, 1.0f, SpriteEffects.None, 0f); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - public void DrawText(SpriteFont font, - string text, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects) - { - font.Draw(DrawTextInternal, text, position, color, rotation, origin, opacity, effects, 0f); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The start. - /// The end. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - public void DrawText(SpriteFont font, - string text, - int start, - int end, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects) - { - font.Draw(DrawTextInternal, text, start, end, position, color, rotation, origin, opacity, effects, 0f); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The start. - /// The end. - /// The position. - /// The dimension. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - public void DrawText(SpriteFont font, - string text, - int start, - int end, - in Vector2 position, - in Size2F dimension, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects) - { - font.Draw( - DrawTextInternal, text, start, end, position, dimension, color, rotation, origin, opacity, effects, 0f); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - public void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, in Color color) - { - font.Draw(DrawTextInternal, text, position, color, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0f); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. - public void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, in Color color, float rotation) - { - font.Draw(DrawTextInternal, text, position, color, rotation, Vector2.Zero, 1.0f, SpriteEffects.None, 0f); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - public void DrawText(SpriteFont font, - StringBuilder text, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects) - { - font.Draw(DrawTextInternal, text, position, color, rotation, origin, opacity, effects, 0f); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The start. - /// The end. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - public void DrawText(SpriteFont font, - StringBuilder text, - int start, - int end, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects) - { - font.Draw(DrawTextInternal, text, start, end, position, color, rotation, origin, opacity, effects, 0f); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The start. - /// The end. - /// The position. - /// The dimension. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - public void DrawText(SpriteFont font, - StringBuilder text, - int start, - int end, - in Vector2 position, - in Size2F dimension, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects) - { - font.Draw( - DrawTextInternal, text, start, end, position, dimension, color, rotation, origin, opacity, effects, 0f); - } - - /// - /// Draw text internal. - /// - /// The texture. - /// The position. - /// Source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The scale. - /// The opacity. - /// The effects. - /// Depth of the layer. - internal void DrawTextInternal(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float scale, - float opacity, - SpriteEffects effects, - float layerDepth) - { - DrawSprite( - texture, new RectangleF(position.X, position.Y, scale, scale), true, sourceRectangle, color, - rotation, origin, opacity, effects); - } - - #endregion - #region IDisposable Support /// diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.Arc.cs b/src/Exomia.Framework/Graphics/SpriteBatch.Arc.cs new file mode 100644 index 00000000..3933d096 --- /dev/null +++ b/src/Exomia.Framework/Graphics/SpriteBatch.Arc.cs @@ -0,0 +1,119 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using System.Runtime.CompilerServices; +using Exomia.Framework.Mathematics; +using SharpDX; + +namespace Exomia.Framework.Graphics +{ + public sealed partial class SpriteBatch + { + /// + /// Draws a circle. + /// + /// The center. + /// The radius. + /// The color. + /// The width of the line. + /// The opacity. + /// The segments. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawCircle(in Vector2 center, + float radius, + in Color color, + float lineWidth, + float opacity, + int segments, + float layerDepth) + { + DrawArc(new Arc2(center, radius), color, lineWidth, opacity, segments, layerDepth); + } + + /// + /// Draws a circle. + /// + /// The circle. + /// The color. + /// The width of the line. + /// The opacity. + /// The segments. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawCircle(in Circle2 circle, + in Color color, + float lineWidth, + float opacity, + int segments, + float layerDepth) + { + DrawArc(new Arc2(circle.X, circle.Y, circle.Radius), color, lineWidth, opacity, segments, layerDepth); + } + + /// + /// Draws a circle. + /// + /// The center. + /// The radius. + /// The start. + /// The end. + /// The color. + /// The width of the line. + /// The opacity. + /// The segments. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawArc(in Vector2 center, + float radius, + float start, + float end, + in Color color, + float lineWidth, + float opacity, + int segments, + float layerDepth) + { + DrawArc(new Arc2(center, radius, start, end), in color, lineWidth, opacity, segments, layerDepth); + } + + /// + /// Draws a circle. + /// + /// The arc. + /// The color. + /// The width of the line. + /// The opacity. + /// The segments. + /// The depth of the layer. + public void DrawArc(in Arc2 arc, + in Color color, + float lineWidth, + float opacity, + int segments, + float layerDepth) + { + Vector2[] vertex = new Vector2[segments]; + + float increment = (arc.End - arc.Start) / segments; + float theta = arc.Start; + + for (int i = 0; i < segments; i++) + { + vertex[i].X = arc.X + (arc.Radius * (float)Math.Cos(theta)); + vertex[i].Y = arc.Y + (arc.Radius * (float)Math.Sin(theta)); + theta += increment; + } + + DrawPolygon(vertex, color, lineWidth, opacity, layerDepth); + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.Drawing.cs b/src/Exomia.Framework/Graphics/SpriteBatch.Drawing.cs deleted file mode 100644 index 4c240a16..00000000 --- a/src/Exomia.Framework/Graphics/SpriteBatch.Drawing.cs +++ /dev/null @@ -1,950 +0,0 @@ -#region License - -// Copyright (c) 2018-2020, exomia -// All rights reserved. -// -// This source code is licensed under the BSD-style license found in the -// LICENSE file in the root directory of this source tree. - -#endregion - -using System; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading; -using Exomia.Framework.Mathematics; -using SharpDX; - -namespace Exomia.Framework.Graphics -{ - public sealed partial class SpriteBatch - { - #region Defaults - - /// - /// Draw rectangle. - /// - /// Destination rectangle. - /// The color. - /// Width of the line. - /// The rotation. - /// The opacity. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawRectangle(in RectangleF destinationRectangle, - in Color color, - float lineWidth, - float rotation, - float opacity, - float layerDepth) - { - DrawRectangle(destinationRectangle, color, lineWidth, rotation, s_vector2Zero, opacity, layerDepth); - } - - /// - /// Draw rectangle. - /// - /// Destination rectangle. - /// The color. - /// Width of the line. - /// The rotation. - /// The origin. - /// The opacity. - /// Depth of the layer. - public void DrawRectangle(in RectangleF destinationRectangle, - in Color color, - float lineWidth, - float rotation, - in Vector2 origin, - float opacity, - float layerDepth) - { - Vector2[] vertex; - - // ReSharper disable once CompareOfFloatsByEqualityOperator - if (rotation == 0.0f) - { - vertex = new[] - { - destinationRectangle.TopLeft, destinationRectangle.TopRight, destinationRectangle.BottomRight, - destinationRectangle.BottomLeft - }; - } - else - { - vertex = new Vector2[4]; - - Vector2 o = origin; - - // ReSharper disable once CompareOfFloatsByEqualityOperator - if (destinationRectangle.Width != 0f) - { - o.X /= destinationRectangle.Width; - } - - // ReSharper disable once CompareOfFloatsByEqualityOperator - if (destinationRectangle.Height != 0f) - { - o.Y /= destinationRectangle.Height; - } - - float cos = (float)Math.Cos(rotation); - float sin = (float)Math.Sin(rotation); - for (int j = 0; j < VERTICES_PER_SPRITE; j++) - { - Vector2 corner = s_cornerOffsets[j]; - float posX = (corner.X - o.X) * destinationRectangle.Width; - float posY = (corner.Y - o.Y) * destinationRectangle.Height; - - vertex[j] = new Vector2( - (destinationRectangle.X + (posX * cos)) - (posY * sin), - destinationRectangle.Y + (posX * sin) + (posY * cos)); - } - } - - DrawPolygon(vertex, color, lineWidth, opacity, layerDepth); - } - - /// - /// Draw fill rectangle. - /// - /// Destination rectangle. - /// The color. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawFillRectangle(in RectangleF destinationRectangle, in Color color, float layerDepth) - { - DrawSprite( - _whiteTexture, destinationRectangle, false, s_nullRectangle, - color, 0.0f, s_vector2Zero, 1.0f, SpriteEffects.None, layerDepth); - } - - /// - /// Draw fill rectangle. - /// - /// Destination rectangle. - /// The color. - /// The opacity. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawFillRectangle(in RectangleF destinationRectangle, - in Color color, - float opacity, - float layerDepth) - { - DrawSprite( - _whiteTexture, destinationRectangle, false, s_nullRectangle, - color, 0.0f, s_vector2Zero, opacity, SpriteEffects.None, layerDepth); - } - - /// - /// Draw fill rectangle. - /// - /// Destination rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawFillRectangle(in RectangleF destinationRectangle, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - float layerDepth) - { - DrawSprite( - _whiteTexture, destinationRectangle, false, s_nullRectangle, - color, rotation, origin, opacity, SpriteEffects.None, layerDepth); - } - - /// - /// Draw line. - /// - /// The first point. - /// The second point. - /// The color. - /// Width of the line. - /// The opacity. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawLine(in Vector2 point1, - in Vector2 point2, - in Color color, - float lineWidth, - float opacity, - float layerDepth) - { - DrawLine(point1, point2, color, lineWidth, opacity, 1.0f, layerDepth); - } - - /// - /// Draw line. - /// - /// The line. - /// The color. - /// Width of the line. - /// The opacity. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawLine(in Line2 line, - in Color color, - float lineWidth, - float opacity, - float layerDepth) - { - DrawLine(in line, color, lineWidth, opacity, 1.0f, layerDepth); - } - - /// - /// Draw line. - /// - /// The first point. - /// The second point. - /// The color. - /// Width of the line. - /// The opacity. - /// The length factor. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawLine(in Vector2 point1, - in Vector2 point2, - in Color color, - float lineWidth, - float opacity, - float lengthFactor, - float layerDepth) - { - DrawLine(new Line2(point1, point2), color, lineWidth, opacity, lengthFactor, layerDepth); - } - - /// - /// Draw line. - /// - /// The line. - /// The color. - /// Width of the line. - /// The opacity. - /// The length factor. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawLine(in Line2 line, - in Color color, - float lineWidth, - float opacity, - float lengthFactor, - float layerDepth) - { - float dx = line.X2 - line.X1; - float dy = line.Y2 - line.Y1; - DrawSprite( - _whiteTexture, new RectangleF( - line.X1, line.Y1, (float)Math.Sqrt((dx * dx) + (dy * dy)) * lengthFactor, lineWidth), false, - s_nullRectangle, color, (float)Math.Atan2(dy, dx), - s_vector2Zero, opacity, SpriteEffects.None, layerDepth); - } - - /// - /// Draw polygon. - /// - /// The vertex. - /// The color. - /// Width of the line. - /// The opacity. - /// Depth of the layer. - public void DrawPolygon(Vector2[] vertex, in Color color, float lineWidth, float opacity, float layerDepth) - { - if (vertex.Length > 1) - { - int l = vertex.Length - 1; - for (int i = 0; i < l; i++) - { - DrawLine(vertex[i], vertex[i + 1], color, lineWidth, opacity, layerDepth); - } - DrawLine(vertex[l], vertex[0], color, lineWidth, opacity, layerDepth); - } - } - - /// - /// Draw circle. - /// - /// The center. - /// The radius. - /// The color. - /// Width of the line. - /// The opacity. - /// The segments. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawCircle(in Vector2 center, - float radius, - in Color color, - float lineWidth, - float opacity, - int segments, - float layerDepth) - { - DrawCircle(center, radius, 0, MathUtil.TwoPi, color, lineWidth, opacity, segments, layerDepth); - } - - /// - /// Draw circle. - /// - /// The center. - /// The radius. - /// The start. - /// The end. - /// The color. - /// Width of the line. - /// The opacity. - /// The segments. - /// Depth of the layer. - public void DrawCircle(in Vector2 center, - float radius, - float start, - float end, - in Color color, - float lineWidth, - float opacity, - int segments, - float layerDepth) - { - Vector2[] vertex = new Vector2[segments]; - - float increment = (end - start) / segments; - float theta = start; - - for (int i = 0; i < segments; i++) - { - vertex[i].X = center.X + (radius * (float)Math.Cos(theta)); - vertex[i].Y = center.Y + (radius * (float)Math.Sin(theta)); - theta += increment; - } - - DrawPolygon(vertex, color, lineWidth, opacity, layerDepth); - } - - #endregion - - #region Texture - - /// - /// Draws a texture to the screen. - /// - /// The texture. - /// The position. - /// The color. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Draw(Texture texture, in Vector2 position, in Color color) - { - DrawSprite( - texture, new RectangleF(position.X, position.Y, 1f, 1f), true, s_nullRectangle, - color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); - } - - /// - /// Draws a texture to the screen. - /// - /// The texture. - /// Destination rectangle. - /// The color. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Draw(Texture texture, in RectangleF destinationRectangle, in Color color) - { - DrawSprite( - texture, destinationRectangle, false, s_nullRectangle, - color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); - } - - /// - /// Draws a texture to the screen. - /// - /// The texture. - /// The position. - /// Source rectangle. - /// The color. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Draw(Texture texture, in Vector2 position, in Rectangle? sourceRectangle, in Color color) - { - DrawSprite( - texture, new RectangleF(position.X, position.Y, 1f, 1f), true, sourceRectangle, - color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); - } - - /// - /// Draws a texture to the screen. - /// - /// The texture. - /// Destination rectangle. - /// Source rectangle. - /// The color. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Draw(Texture texture, - in RectangleF destinationRectangle, - in Rectangle? sourceRectangle, - in Color color) - { - DrawSprite( - texture, destinationRectangle, false, sourceRectangle, - color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); - } - - /// - /// Draws a texture to the screen. - /// - /// The texture. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// (Optional) Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Draw(Texture texture, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float layerDepth = 0f) - { - DrawSprite( - texture, new RectangleF(position.X, position.Y, 1f, 1f), true, s_nullRectangle, - color, rotation, origin, 1.0f, SpriteEffects.None, layerDepth); - } - - /// - /// Draws a texture to the screen. - /// - /// The texture. - /// Destination rectangle. - /// The color. - /// The rotation. - /// The origin. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Draw(Texture texture, - in RectangleF destinationRectangle, - in Color color, - float rotation, - in Vector2 origin, - float layerDepth = 0f) - { - DrawSprite( - texture, destinationRectangle, false, s_nullRectangle, - color, rotation, origin, 1.0f, SpriteEffects.None, layerDepth); - } - - /// - /// Draws a texture to the screen. - /// - /// The texture. - /// Destination rectangle. - /// Source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Draw(Texture texture, - in RectangleF destinationRectangle, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) - { - DrawSprite( - texture, destinationRectangle, false, sourceRectangle, - color, rotation, origin, opacity, effects, layerDepth); - } - - /// - /// Draws a texture to the screen. - /// - /// The texture. - /// The position. - /// Source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The scale. - /// The opacity. - /// The effects. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Draw(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float scale, - float opacity, - SpriteEffects effects, - float layerDepth) - { - DrawSprite( - texture, new RectangleF(position.X, position.Y, scale, scale), true, sourceRectangle, - color, rotation, origin, opacity, effects, layerDepth); - } - - /// - /// Draws a texture to the screen. - /// - /// The texture. - /// The position. - /// Source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The scale. - /// The opacity. - /// The effects. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Draw(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - in Vector2 scale, - float opacity, - SpriteEffects effects, - float layerDepth) - { - DrawSprite( - texture, new RectangleF(position.X, position.Y, scale.X, scale.Y), true, sourceRectangle, - color, rotation, origin, opacity, effects, layerDepth); - } - - private unsafe void DrawSprite(Texture texture, - in RectangleF destination, - bool scaleDestination, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float depth) - { - if (!_isBeginCalled) - { - throw new InvalidOperationException("Begin must be called before draw"); - } - - if (texture.TexturePointer == IntPtr.Zero) - { - throw new ArgumentNullException(nameof(texture)); - } - - if (_spriteQueueCount >= _spriteQueue.Length) - { - bool lockTaken = false; - try - { - _spinLock.Enter(ref lockTaken); - - int size = _spriteQueue.Length * 2; - _sortIndices = new int[size]; - _sortedSprites = new SpriteInfo[size]; - Array.Resize(ref _spriteQueue, size); - Array.Resize(ref _spriteTextures, size); - } - finally - { - if (lockTaken) - { - _spinLock.Exit(false); - } - } - } - - if (!_textureInfos.TryGetValue(texture.TexturePointer, out TextureInfo textureInfo)) - { - bool lockTaken = false; - try - { - _spinLock.Enter(ref lockTaken); - if (!_textureInfos.TryGetValue(texture.TexturePointer, out textureInfo)) - { - textureInfo = new TextureInfo(texture.TextureView, texture.Width, texture.Height); - _textureInfos.Add(texture.TexturePointer, textureInfo); - } - } - finally - { - if (lockTaken) - { - _spinLock.Exit(false); - } - } - } - - int spriteQueueCount = Interlocked.Increment(ref _spriteQueueCount) - 1; - fixed (SpriteInfo* spriteInfo = &_spriteQueue[spriteQueueCount]) - { - float width; - float height; - if (sourceRectangle.HasValue) - { - Rectangle rectangle = sourceRectangle.Value; - spriteInfo->Source.X = rectangle.X; - spriteInfo->Source.Y = rectangle.Y; - width = rectangle.Width; - height = rectangle.Height; - } - else - { - spriteInfo->Source.X = 0; - spriteInfo->Source.Y = 0; - width = texture.Width; - height = texture.Height; - } - - spriteInfo->Source.Width = width; - spriteInfo->Source.Height = height; - - spriteInfo->Destination.X = destination.X; - spriteInfo->Destination.Y = destination.Y; - - if (scaleDestination) - { - spriteInfo->Destination.Width = destination.Width * width; - spriteInfo->Destination.Height = destination.Height * height; - } - else - { - spriteInfo->Destination.Width = destination.Width; - spriteInfo->Destination.Height = destination.Height; - } - - if (spriteInfo->Destination.Width < 0) - { - spriteInfo->Destination.X += spriteInfo->Destination.Width; - spriteInfo->Destination.Width = -spriteInfo->Destination.Width; - } - - if (spriteInfo->Destination.Height < 0) - { - spriteInfo->Destination.Y += spriteInfo->Destination.Height; - spriteInfo->Destination.Height = -spriteInfo->Destination.Height; - } - - spriteInfo->Origin = origin; - spriteInfo->Rotation = rotation; - spriteInfo->Depth = depth; - spriteInfo->SpriteEffects = effects; - spriteInfo->Color = color; - spriteInfo->Opacity = opacity; - } - - _spriteTextures[spriteQueueCount] = textureInfo; - } - - #endregion - - #region SpiteFont - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, string text, in Vector2 position, in Color color, float layerDepth) - { - font.Draw( - DrawTextInternal, text, position, - color, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - string text, - in Vector2 position, - in Color color, - float rotation, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, position, - color, rotation, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - string text, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, position, - color, rotation, origin, opacity, effects, layerDepth); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The start. - /// The end. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - string text, - int start, - int end, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, start, end, position, - color, rotation, origin, opacity, effects, layerDepth); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The start. - /// The end. - /// The position. - /// The dimension. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - string text, - int start, - int end, - in Vector2 position, - in Size2F dimension, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, start, end, position, dimension, - color, rotation, origin, opacity, effects, layerDepth); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, in Color color, float layerDepth) - { - font.Draw( - DrawTextInternal, text, position, - color, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - StringBuilder text, - in Vector2 position, - in Color color, - float rotation, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, position, - color, rotation, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - StringBuilder text, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, position, - color, rotation, origin, opacity, effects, layerDepth); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The start. - /// The end. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - StringBuilder text, - int start, - int end, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, start, end, position, - color, rotation, origin, opacity, effects, layerDepth); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The start. - /// The end. - /// The position. - /// The dimension. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - StringBuilder text, - int start, - int end, - in Vector2 position, - in Size2F dimension, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, start, end, position, dimension, - color, rotation, origin, opacity, effects, layerDepth); - } - - /// - /// Draw text internal. - /// - /// The texture. - /// The position. - /// Source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The scale. - /// The opacity. - /// The effects. - /// Depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void DrawTextInternal(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float scale, - float opacity, - SpriteEffects effects, - float layerDepth) - { - DrawSprite( - texture, new RectangleF(position.X, position.Y, scale, scale), true, sourceRectangle, - color, rotation, origin, opacity, effects, layerDepth); - } - - #endregion - } -} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.Line.cs b/src/Exomia.Framework/Graphics/SpriteBatch.Line.cs new file mode 100644 index 00000000..debce03c --- /dev/null +++ b/src/Exomia.Framework/Graphics/SpriteBatch.Line.cs @@ -0,0 +1,106 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using System.Runtime.CompilerServices; +using Exomia.Framework.Mathematics; +using SharpDX; + +namespace Exomia.Framework.Graphics +{ + public sealed partial class SpriteBatch + { + /// + /// Draw line. + /// + /// The first point. + /// The second point. + /// The color. + /// The width of the line. + /// The opacity. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawLine(in Vector2 point1, + in Vector2 point2, + in Color color, + float lineWidth, + float opacity, + float layerDepth) + { + DrawLine(point1, point2, color, lineWidth, opacity, 1.0f, layerDepth); + } + + /// + /// Draw line. + /// + /// The line. + /// The color. + /// The width of the line. + /// The opacity. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawLine(in Line2 line, + in Color color, + float lineWidth, + float opacity, + float layerDepth) + { + DrawLine(in line, color, lineWidth, opacity, 1.0f, layerDepth); + } + + /// + /// Draw line. + /// + /// The first point. + /// The second point. + /// The color. + /// The width of the line. + /// The opacity. + /// The length factor. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawLine(in Vector2 point1, + in Vector2 point2, + in Color color, + float lineWidth, + float opacity, + float lengthFactor, + float layerDepth) + { + DrawLine(new Line2(point1, point2), color, lineWidth, opacity, lengthFactor, layerDepth); + } + + /// + /// Draw line. + /// + /// The line. + /// The color. + /// The width of the line. + /// The opacity. + /// The length factor. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawLine(in Line2 line, + in Color color, + float lineWidth, + float opacity, + float lengthFactor, + float layerDepth) + { + float dx = line.X2 - line.X1; + float dy = line.Y2 - line.Y1; + DrawSprite( + _whiteTexture, new RectangleF( + line.X1, line.Y1, (float)Math.Sqrt((dx * dx) + (dy * dy)) * lengthFactor, lineWidth), false, + s_nullRectangle, color, (float)Math.Atan2(dy, dx), + s_vector2Zero, opacity, SpriteEffects.None, layerDepth); + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.Polygon.cs b/src/Exomia.Framework/Graphics/SpriteBatch.Polygon.cs new file mode 100644 index 00000000..48ce9c1b --- /dev/null +++ b/src/Exomia.Framework/Graphics/SpriteBatch.Polygon.cs @@ -0,0 +1,38 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using SharpDX; + +namespace Exomia.Framework.Graphics +{ + public sealed partial class SpriteBatch + { + /// + /// Draw polygon. + /// + /// The vertex. + /// The color. + /// The width of the line. + /// The opacity. + /// The depth of the layer. + public void DrawPolygon(Vector2[] vertex, in Color color, float lineWidth, float opacity, float layerDepth) + { + if (vertex.Length > 1) + { + int l = vertex.Length - 1; + for (int i = 0; i < l; i++) + { + DrawLine(vertex[i], vertex[i + 1], color, lineWidth, opacity, layerDepth); + } + DrawLine(vertex[l], vertex[0], color, lineWidth, opacity, layerDepth); + } + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.Rectangle.cs b/src/Exomia.Framework/Graphics/SpriteBatch.Rectangle.cs new file mode 100644 index 00000000..d177c1e6 --- /dev/null +++ b/src/Exomia.Framework/Graphics/SpriteBatch.Rectangle.cs @@ -0,0 +1,157 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using System.Runtime.CompilerServices; +using SharpDX; + +namespace Exomia.Framework.Graphics +{ + public sealed partial class SpriteBatch + { + /// + /// Draw rectangle. + /// + /// The destination rectangle. + /// The color. + /// The width of the line. + /// The rotation. + /// The opacity. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawRectangle(in RectangleF destinationRectangle, + in Color color, + float lineWidth, + float rotation, + float opacity, + float layerDepth) + { + DrawRectangle(destinationRectangle, color, lineWidth, rotation, s_vector2Zero, opacity, layerDepth); + } + + /// + /// Draw rectangle. + /// + /// The destination rectangle. + /// The color. + /// The width of the line. + /// The rotation. + /// The origin. + /// The opacity. + /// The depth of the layer. + public void DrawRectangle(in RectangleF destinationRectangle, + in Color color, + float lineWidth, + float rotation, + in Vector2 origin, + float opacity, + float layerDepth) + { + Vector2[] vertex; + + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (rotation == 0.0f) + { + vertex = new[] + { + destinationRectangle.TopLeft, destinationRectangle.TopRight, destinationRectangle.BottomRight, + destinationRectangle.BottomLeft + }; + } + else + { + vertex = new Vector2[4]; + + Vector2 o = origin; + + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (destinationRectangle.Width != 0f) + { + o.X /= destinationRectangle.Width; + } + + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (destinationRectangle.Height != 0f) + { + o.Y /= destinationRectangle.Height; + } + + float cos = (float)Math.Cos(rotation); + float sin = (float)Math.Sin(rotation); + for (int j = 0; j < VERTICES_PER_SPRITE; j++) + { + Vector2 corner = s_cornerOffsets[j]; + float posX = (corner.X - o.X) * destinationRectangle.Width; + float posY = (corner.Y - o.Y) * destinationRectangle.Height; + + vertex[j] = new Vector2( + (destinationRectangle.X + (posX * cos)) - (posY * sin), + destinationRectangle.Y + (posX * sin) + (posY * cos)); + } + } + + DrawPolygon(vertex, color, lineWidth, opacity, layerDepth); + } + + /// + /// Draw fill rectangle. + /// + /// The destination rectangle. + /// The color. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawFillRectangle(in RectangleF destinationRectangle, in Color color, float layerDepth) + { + DrawSprite( + _whiteTexture, destinationRectangle, false, s_nullRectangle, + color, 0.0f, s_vector2Zero, 1.0f, SpriteEffects.None, layerDepth); + } + + /// + /// Draw fill rectangle. + /// + /// The destination rectangle. + /// The color. + /// The opacity. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawFillRectangle(in RectangleF destinationRectangle, + in Color color, + float opacity, + float layerDepth) + { + DrawSprite( + _whiteTexture, destinationRectangle, false, s_nullRectangle, + color, 0.0f, s_vector2Zero, opacity, SpriteEffects.None, layerDepth); + } + + /// + /// Draw fill rectangle. + /// + /// The destination rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawFillRectangle(in RectangleF destinationRectangle, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + float layerDepth) + { + DrawSprite( + _whiteTexture, destinationRectangle, false, s_nullRectangle, + color, rotation, origin, opacity, SpriteEffects.None, layerDepth); + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.SpriteFont.cs b/src/Exomia.Framework/Graphics/SpriteBatch.SpriteFont.cs new file mode 100644 index 00000000..e14e9ffc --- /dev/null +++ b/src/Exomia.Framework/Graphics/SpriteBatch.SpriteFont.cs @@ -0,0 +1,313 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System.Runtime.CompilerServices; +using System.Text; +using SharpDX; + +namespace Exomia.Framework.Graphics +{ + public sealed partial class SpriteBatch + { + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, string text, in Vector2 position, in Color color, float layerDepth) + { + font.Draw( + DrawTextInternal, text, position, + color, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + /// The rotation. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + string text, + in Vector2 position, + in Color color, + float rotation, + float layerDepth) + { + font.Draw( + DrawTextInternal, text, position, + color, rotation, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + string text, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects, + float layerDepth) + { + font.Draw( + DrawTextInternal, text, position, + color, rotation, origin, opacity, effects, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The start. + /// The end. + /// The position. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + string text, + int start, + int end, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects, + float layerDepth) + { + font.Draw( + DrawTextInternal, text, start, end, position, + color, rotation, origin, opacity, effects, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The start. + /// The end. + /// The position. + /// The dimension. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + string text, + int start, + int end, + in Vector2 position, + in Size2F dimension, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects, + float layerDepth) + { + font.Draw( + DrawTextInternal, text, start, end, position, dimension, + color, rotation, origin, opacity, effects, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, in Color color, float layerDepth) + { + font.Draw( + DrawTextInternal, text, position, + color, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + /// The rotation. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + StringBuilder text, + in Vector2 position, + in Color color, + float rotation, + float layerDepth) + { + font.Draw( + DrawTextInternal, text, position, + color, rotation, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The position. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + StringBuilder text, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects, + float layerDepth) + { + font.Draw( + DrawTextInternal, text, position, + color, rotation, origin, opacity, effects, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The start. + /// The end. + /// The position. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + StringBuilder text, + int start, + int end, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects, + float layerDepth) + { + font.Draw( + DrawTextInternal, text, start, end, position, + color, rotation, origin, opacity, effects, layerDepth); + } + + /// + /// Draw text. + /// + /// The font. + /// The text. + /// The start. + /// The end. + /// The position. + /// The dimension. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + StringBuilder text, + int start, + int end, + in Vector2 position, + in Size2F dimension, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects, + float layerDepth) + { + font.Draw( + DrawTextInternal, text, start, end, position, dimension, + color, rotation, origin, opacity, effects, layerDepth); + } + + /// + /// Draw text internal. + /// + /// The texture. + /// The position. + /// The source rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The scale. + /// The opacity. + /// The effects. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void DrawTextInternal(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float scale, + float opacity, + SpriteEffects effects, + float layerDepth) + { + DrawSprite( + texture, new RectangleF(position.X, position.Y, scale, scale), true, sourceRectangle, + color, rotation, origin, opacity, effects, layerDepth); + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.Structs.cs b/src/Exomia.Framework/Graphics/SpriteBatch.Structs.cs new file mode 100644 index 00000000..8a46ea7d --- /dev/null +++ b/src/Exomia.Framework/Graphics/SpriteBatch.Structs.cs @@ -0,0 +1,81 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System.Runtime.InteropServices; +using SharpDX; +using SharpDX.Direct3D11; + +namespace Exomia.Framework.Graphics +{ + public sealed partial class SpriteBatch + { + internal struct SpriteInfo + { + public RectangleF Source; + public RectangleF Destination; + public Vector2 Origin; + public float Rotation; + public float Depth; + public SpriteEffects SpriteEffects; + public Color Color; + public float Opacity; + } + + internal readonly struct TextureInfo + { + public readonly ShaderResourceView View; + public readonly int Width; + public readonly int Height; + public readonly long Ptr64; + + public TextureInfo(ShaderResourceView view, int width, int height) + { + View = view; + Width = width; + Height = height; + Ptr64 = view.NativePointer.ToInt64(); + } + } + + [StructLayout(LayoutKind.Explicit, Size = VERTEX_STRIDE)] + private struct VertexPositionColorTexture + { + [FieldOffset(0)] + public float X; + + [FieldOffset(4)] + public float Y; + + [FieldOffset(8)] + public float Z; + + [FieldOffset(12)] + public float W; + + [FieldOffset(16)] + public float R; + + [FieldOffset(20)] + public float G; + + [FieldOffset(24)] + public float B; + + [FieldOffset(28)] + public float A; + + [FieldOffset(32)] + public float U; + + [FieldOffset(36)] + public float V; + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.Texture.cs b/src/Exomia.Framework/Graphics/SpriteBatch.Texture.cs new file mode 100644 index 00000000..af6b759a --- /dev/null +++ b/src/Exomia.Framework/Graphics/SpriteBatch.Texture.cs @@ -0,0 +1,338 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using System.Runtime.CompilerServices; +using System.Threading; +using SharpDX; + +namespace Exomia.Framework.Graphics +{ + public sealed partial class SpriteBatch + { + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// The position. + /// The color. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Draw(Texture texture, in Vector2 position, in Color color) + { + DrawSprite( + texture, new RectangleF(position.X, position.Y, 1f, 1f), true, s_nullRectangle, + color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); + } + + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// The destination rectangle. + /// The color. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Draw(Texture texture, in RectangleF destinationRectangle, in Color color) + { + DrawSprite( + texture, destinationRectangle, false, s_nullRectangle, + color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); + } + + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// The position. + /// The source rectangle. + /// The color. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Draw(Texture texture, in Vector2 position, in Rectangle? sourceRectangle, in Color color) + { + DrawSprite( + texture, new RectangleF(position.X, position.Y, 1f, 1f), true, sourceRectangle, + color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); + } + + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// The destination rectangle. + /// The source rectangle. + /// The color. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Draw(Texture texture, + in RectangleF destinationRectangle, + in Rectangle? sourceRectangle, + in Color color) + { + DrawSprite( + texture, destinationRectangle, false, sourceRectangle, + color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); + } + + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// The position. + /// The color. + /// The rotation. + /// The origin. + /// (Optional) The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Draw(Texture texture, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float layerDepth = 0f) + { + DrawSprite( + texture, new RectangleF(position.X, position.Y, 1f, 1f), true, s_nullRectangle, + color, rotation, origin, 1.0f, SpriteEffects.None, layerDepth); + } + + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// The destination rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Draw(Texture texture, + in RectangleF destinationRectangle, + in Color color, + float rotation, + in Vector2 origin, + float layerDepth = 0f) + { + DrawSprite( + texture, destinationRectangle, false, s_nullRectangle, + color, rotation, origin, 1.0f, SpriteEffects.None, layerDepth); + } + + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// The destination rectangle. + /// The source rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Draw(Texture texture, + in RectangleF destinationRectangle, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects, + float layerDepth) + { + DrawSprite( + texture, destinationRectangle, false, sourceRectangle, + color, rotation, origin, opacity, effects, layerDepth); + } + + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// The position. + /// The source rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The scale. + /// The opacity. + /// The effects. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Draw(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float scale, + float opacity, + SpriteEffects effects, + float layerDepth) + { + DrawSprite( + texture, new RectangleF(position.X, position.Y, scale, scale), true, sourceRectangle, + color, rotation, origin, opacity, effects, layerDepth); + } + + /// + /// Draws a texture to the screen. + /// + /// The texture. + /// The position. + /// The source rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The scale. + /// The opacity. + /// The effects. + /// The depth of the layer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Draw(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + in Vector2 scale, + float opacity, + SpriteEffects effects, + float layerDepth) + { + DrawSprite( + texture, new RectangleF(position.X, position.Y, scale.X, scale.Y), true, sourceRectangle, + color, rotation, origin, opacity, effects, layerDepth); + } + + private unsafe void DrawSprite(Texture texture, + in RectangleF destination, + bool scaleDestination, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + SpriteEffects effects, + float depth) + { + if (!_isBeginCalled) + { + throw new InvalidOperationException("Begin must be called before draw"); + } + + if (texture.TexturePointer == IntPtr.Zero) + { + throw new ArgumentNullException(nameof(texture)); + } + + if (_spriteQueueCount >= _spriteQueue.Length) + { + bool lockTaken = false; + try + { + _spinLock.Enter(ref lockTaken); + + int size = _spriteQueue.Length * 2; + _sortIndices = new int[size]; + _sortedSprites = new SpriteInfo[size]; + Array.Resize(ref _spriteQueue, size); + Array.Resize(ref _spriteTextures, size); + } + finally + { + if (lockTaken) + { + _spinLock.Exit(false); + } + } + } + + if (!_textureInfos.TryGetValue(texture.TexturePointer, out TextureInfo textureInfo)) + { + bool lockTaken = false; + try + { + _spinLock.Enter(ref lockTaken); + if (!_textureInfos.TryGetValue(texture.TexturePointer, out textureInfo)) + { + textureInfo = new TextureInfo(texture.TextureView, texture.Width, texture.Height); + _textureInfos.Add(texture.TexturePointer, textureInfo); + } + } + finally + { + if (lockTaken) + { + _spinLock.Exit(false); + } + } + } + + int spriteQueueCount = Interlocked.Increment(ref _spriteQueueCount) - 1; + fixed (SpriteInfo* spriteInfo = &_spriteQueue[spriteQueueCount]) + { + float width; + float height; + if (sourceRectangle.HasValue) + { + Rectangle rectangle = sourceRectangle.Value; + spriteInfo->Source.X = rectangle.X; + spriteInfo->Source.Y = rectangle.Y; + width = rectangle.Width; + height = rectangle.Height; + } + else + { + spriteInfo->Source.X = 0; + spriteInfo->Source.Y = 0; + width = texture.Width; + height = texture.Height; + } + + spriteInfo->Source.Width = width; + spriteInfo->Source.Height = height; + + spriteInfo->Destination.X = destination.X; + spriteInfo->Destination.Y = destination.Y; + + if (scaleDestination) + { + spriteInfo->Destination.Width = destination.Width * width; + spriteInfo->Destination.Height = destination.Height * height; + } + else + { + spriteInfo->Destination.Width = destination.Width; + spriteInfo->Destination.Height = destination.Height; + } + + if (spriteInfo->Destination.Width < 0) + { + spriteInfo->Destination.X += spriteInfo->Destination.Width; + spriteInfo->Destination.Width = -spriteInfo->Destination.Width; + } + + if (spriteInfo->Destination.Height < 0) + { + spriteInfo->Destination.Y += spriteInfo->Destination.Height; + spriteInfo->Destination.Height = -spriteInfo->Destination.Height; + } + + spriteInfo->Origin = origin; + spriteInfo->Rotation = rotation; + spriteInfo->Depth = depth; + spriteInfo->SpriteEffects = effects; + spriteInfo->Color = color; + spriteInfo->Opacity = opacity; + } + + _spriteTextures[spriteQueueCount] = textureInfo; + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.cs b/src/Exomia.Framework/Graphics/SpriteBatch.cs index 5ba195a7..0c7bc920 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.cs @@ -14,7 +14,6 @@ using System.Diagnostics; using System.IO; using System.Reflection; -using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Exomia.Framework.Graphics.Buffers; @@ -176,7 +175,7 @@ public SpriteBatch(IGraphicsDevice graphicsDevice, _spriteQueue = new SpriteInfo[MAX_BATCH_SIZE]; _spriteTextures = new TextureInfo[MAX_BATCH_SIZE]; - graphicsDevice.ResizeFinished += IDevice_onResizeFinished; + graphicsDevice.ResizeFinished += GraphicsDeviceOnResizeFinished; Resize(graphicsDevice.Viewport); } @@ -281,6 +280,11 @@ public void Resize(float width, float height) }; } + private void GraphicsDeviceOnResizeFinished(ViewportF viewport) + { + Resize(viewport); + } + private unsafe void DrawBatchPerTexture(ref TextureInfo texture, SpriteInfo[] sprites, int offset, int count) { _context.PixelShader.SetShaderResource(0, texture.View); @@ -407,11 +411,6 @@ private void FlushBatch() _spriteQueueCount = 0; } - private void IDevice_onResizeFinished(ViewportF viewport) - { - Resize(viewport); - } - private void PrepareForRendering() { _context.VertexShader.Set(_vertexShader); @@ -517,68 +516,6 @@ private static unsafe void UpdateVertexFromSpriteInfo(ref SpriteInfo } } - internal struct SpriteInfo - { - public RectangleF Source; - public RectangleF Destination; - public Vector2 Origin; - public float Rotation; - public float Depth; - public SpriteEffects SpriteEffects; - public Color Color; - public float Opacity; - } - - internal readonly struct TextureInfo - { - public readonly ShaderResourceView View; - public readonly int Width; - public readonly int Height; - public readonly long Ptr64; - - public TextureInfo(ShaderResourceView view, int width, int height) - { - View = view; - Width = width; - Height = height; - Ptr64 = view.NativePointer.ToInt64(); - } - } - - [StructLayout(LayoutKind.Explicit, Size = VERTEX_STRIDE)] - private struct VertexPositionColorTexture - { - [FieldOffset(0)] - public float X; - - [FieldOffset(4)] - public float Y; - - [FieldOffset(8)] - public float Z; - - [FieldOffset(12)] - public float W; - - [FieldOffset(16)] - public float R; - - [FieldOffset(20)] - public float G; - - [FieldOffset(24)] - public float B; - - [FieldOffset(28)] - public float A; - - [FieldOffset(32)] - public float U; - - [FieldOffset(36)] - public float V; - } - #region IDisposable Support /// diff --git a/src/Exomia.Framework/Mathematics/Arc2.cs b/src/Exomia.Framework/Mathematics/Arc2.cs new file mode 100644 index 00000000..031e3625 --- /dev/null +++ b/src/Exomia.Framework/Mathematics/Arc2.cs @@ -0,0 +1,203 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using System.Globalization; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using SharpDX; + +namespace Exomia.Framework.Mathematics +{ + /// + /// A 2d arc. + /// + /// + [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 20)] + public readonly struct Arc2 : IFormattable + { + /// + /// The x value. + /// + public readonly float X; //Note: do not reorder this field, unless you know what you are doing. + + /// + /// The y value. + /// + public readonly float Y; //Note: do not reorder this field, unless you know what you are doing. + + /// + /// The radius. + /// + public readonly float Radius; //Note: do not reorder this field, unless you know what you are doing. + + /// + /// The start angle in radians. + /// + public readonly float Start; //Note: do not reorder this field, unless you know what you are doing. + + /// + /// The end angle in radians. + /// + public readonly float End; //Note: do not reorder this field, unless you know what you are doing. + + /// + /// Initializes a new instance of the struct. + /// + /// The x value. + /// The y value. + /// The radius. + /// + /// (Optional) + /// The start angle in radians. + /// + /// + /// (Optional) + /// The end angle in radians. + /// + public Arc2(float x, float y, float radius, float start = 0, float end = MathUtil.TwoPi) + { + X = x; + Y = y; + Radius = radius; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The center. + /// The radius. + /// + /// (Optional) + /// The start angle in radians. + /// + /// + /// (Optional) + /// The end angle in radians. + /// + public Arc2(VectorI2 center, float radius, float start = 0, float end = MathUtil.TwoPi) + : this(center.X, center.Y, radius, start, end) { } + + /// + /// Initializes a new instance of the struct. + /// + /// The center. + /// The radius. + /// + /// (Optional) + /// The start angle in radians. + /// + /// + /// (Optional) + /// The end angle in radians. + /// + public Arc2(Vector2 center, float radius, float start = 0, float end = MathUtil.TwoPi) + : this(center.X, center.Y, radius, start, end) { } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; false otherwise. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(in Arc2 other) + { + // ReSharper disable CompareOfFloatsByEqualityOperator + return + X == other.X && + Y == other.Y && + Radius == other.Radius && + Start == other.Start && + End == other.End; + + // ReSharper restore CompareOfFloatsByEqualityOperator + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override bool Equals(object value) + { + return value is Arc2 other && Equals(in other); + } + + /// + public override int GetHashCode() + { + return (((((((X.GetHashCode() * 307) ^ Y.GetHashCode()) * 521) ^ Radius.GetHashCode()) * 853) ^ + Start.GetHashCode()) * 443) ^ End.GetHashCode(); + } + + /// + public override string ToString() + { + return string.Format( + CultureInfo.CurrentCulture, + "X:{0} Y:{1} | Radius:{2}, Start:{3}, End:{4}", X, Y, Radius, Start, End); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string? format) + { + if (format == null) + { + return ToString(); + } + + return string.Format( + CultureInfo.CurrentCulture, + "X:{0} Y:{1} | Radius:{2}, Start:{3}, End:{4}", + X.ToString(format, CultureInfo.CurrentCulture), + Y.ToString(format, CultureInfo.CurrentCulture), + Radius.ToString(format, CultureInfo.CurrentCulture), + Start.ToString(format, CultureInfo.CurrentCulture), + End.ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format( + formatProvider, + "X:{0} Y:{1} | Radius:{2}, Start:{3}, End:{4}", X, Y, Radius, Start, End); + } + + /// + public string ToString(string? format, IFormatProvider formatProvider) + { + if (format == null) + { + return ToString(formatProvider); + } + + return string.Format( + formatProvider, + "X:{0} Y:{1} | Radius:{2}, Start:{3}, End:{4}", + X.ToString(format, formatProvider), + Y.ToString(format, formatProvider), + Radius.ToString(format, formatProvider), + Start.ToString(format, formatProvider), + End.ToString(format, formatProvider)); + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Mathematics/Circle2.cs b/src/Exomia.Framework/Mathematics/Circle2.cs new file mode 100644 index 00000000..35352916 --- /dev/null +++ b/src/Exomia.Framework/Mathematics/Circle2.cs @@ -0,0 +1,162 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using System.Globalization; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using SharpDX; + +namespace Exomia.Framework.Mathematics +{ + /// + /// A 2d circle. + /// + /// + [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 12)] + public readonly struct Circle2 : IFormattable + { + /// + /// The x value. + /// + public readonly float X; //Note: do not reorder this field, unless you know what you are doing. + + /// + /// The y value. + /// + public readonly float Y; //Note: do not reorder this field, unless you know what you are doing. + + /// + /// The radius. + /// + public readonly float Radius; //Note: do not reorder this field, unless you know what you are doing. + + /// + /// Initializes a new instance of the struct. + /// + /// The x value. + /// The y value. + /// The radius. + public Circle2(float x, float y, float radius) + { + X = x; + Y = y; + Radius = radius; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The center. + /// The radius. + public Circle2(VectorI2 center, float radius) + : this(center.X, center.Y, radius) { } + + /// + /// Initializes a new instance of the struct. + /// + /// The center. + /// The radius. + public Circle2(Vector2 center, float radius) + : this(center.X, center.Y, radius) { } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; false otherwise. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(in Circle2 other) + { + // ReSharper disable CompareOfFloatsByEqualityOperator + return + X == other.X && + Y == other.Y && + Radius == other.Radius; + + // ReSharper restore CompareOfFloatsByEqualityOperator + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override bool Equals(object value) + { + return value is Circle2 other && Equals(in other); + } + + /// + public override int GetHashCode() + { + return (((X.GetHashCode() * 307) ^ Y.GetHashCode()) * 521) ^ Radius.GetHashCode(); + } + + /// + public override string ToString() + { + return string.Format( + CultureInfo.CurrentCulture, + "X:{0} Y:{1} | Radius:{2}", X, Y, Radius); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string? format) + { + if (format == null) + { + return ToString(); + } + + return string.Format( + CultureInfo.CurrentCulture, + "X:{0} Y:{1} | Radius:{2}", + X.ToString(format, CultureInfo.CurrentCulture), + Y.ToString(format, CultureInfo.CurrentCulture), + Radius.ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format( + formatProvider, + "X:{0} Y:{1} | Radius:{2}", X, Y, Radius); + } + + /// + public string ToString(string? format, IFormatProvider formatProvider) + { + if (format == null) + { + return ToString(formatProvider); + } + + return string.Format( + formatProvider, + "X:{0} Y:{1} | Radius:{2}", + X.ToString(format, formatProvider), + Y.ToString(format, formatProvider), + Radius.ToString(format, formatProvider)); + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Mathematics/Line2.cs b/src/Exomia.Framework/Mathematics/Line2.cs index 5c1c026f..05c1cb5b 100644 --- a/src/Exomia.Framework/Mathematics/Line2.cs +++ b/src/Exomia.Framework/Mathematics/Line2.cs @@ -13,6 +13,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SharpDX; +using SharpDX.Direct3D9; namespace Exomia.Framework.Mathematics { @@ -26,22 +27,22 @@ namespace Exomia.Framework.Mathematics /// /// The first x value. /// - public readonly float X1; + public readonly float X1; //Note: do not reorder this field, unless you know what you are doing. /// - /// The second x value. + /// The first y value. /// - public readonly float X2; + public readonly float Y1; //Note: do not reorder this field, unless you know what you are doing. /// - /// The first y value. + /// The second x value. /// - public readonly float Y1; + public readonly float X2; //Note: do not reorder this field, unless you know what you are doing. /// /// The second y value. /// - public readonly float Y2; + public readonly float Y2; //Note: do not reorder this field, unless you know what you are doing. /// /// Initializes a new instance of the struct. @@ -98,11 +99,7 @@ public bool Equals(in Line2 other) [MethodImpl(MethodImplOptions.AggressiveInlining)] public override bool Equals(object value) { - if (value is Line2 other) - { - return Equals(in other); - } - return false; + return value is Line2 other && Equals(in other); } /// @@ -173,5 +170,81 @@ public string ToString(string? format, IFormatProvider formatProvider) X2.ToString(format, formatProvider), Y2.ToString(format, formatProvider)); } + + /// + /// Intersect with other . + /// + /// The to compare with this instance. + /// [out] The intersection point. + /// + /// True if it succeeds, false if it fails. + /// + public bool IntersectWith(in Line2 other, out Vector2 intersectionPoint) + { + float a1 = Y2 - Y1; + float b1 = X1 - X2; + float c1 = (a1 * X1) + (b1 * Y1); + + float a2 = other.Y2 - other.Y1; + float b2 = other.X1 - other.X2; + float c2 = (a2 * other.X1) + (b2 * other.Y1); + + float det = (a1 * b2) - (a2 * b1); + + if (det == 0.0f) + { + intersectionPoint = default; + return false; + } + + intersectionPoint.X = ((b2 * c1) - (b1 * c2)) / det; + intersectionPoint.Y = ((a1 * c2) - (a2 * c1)) / det; + return true; + } + + /// + /// Gets a perpendicular from this line. + /// + /// The offset. + /// + /// The perpendicular. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Line2 GetPerpendicular(float offset) + { + float dx = X2 - X1; + float dy = Y2 - Y1; + + double dl = Math.Sqrt((dx * dx) + (dy * dy)); + float nx = (float)((dy / dl) * offset); + float ny = (float)((dx / dl) * offset); + + return new Line2(X1 - nx, Y1 + ny, X2 - nx, Y2 + ny); + } + + /// + /// Rotates the line around the given . + /// + /// The line. + /// The rotation (in radians). + /// The origin. + /// + /// A new . + /// + public static Line2 RotateAround(in Line2 line, float rotation, in Vector2 origin) + { + double sin = Math.Sin(rotation); + double cos = Math.Cos(rotation); + + float x1 = line.X1 - origin.X; + float y1 = line.Y1 - origin.Y; + + float x2 = line.X2 - origin.X; + float y2 = line.Y2 - origin.Y; + + return new Line2( + (float)((x1 * cos) - (y1 * sin)) + origin.X, (float)((x1 * sin) + (y1 * cos)) + origin.Y, + (float)((x2 * cos) - (y2 * sin)) + origin.X, (float)((x2 * sin) + (y2 * cos)) + origin.Y); + } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Mathematics/Triangle2.cs b/src/Exomia.Framework/Mathematics/Triangle2.cs new file mode 100644 index 00000000..b3f3657e --- /dev/null +++ b/src/Exomia.Framework/Mathematics/Triangle2.cs @@ -0,0 +1,226 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using System.Globalization; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using SharpDX; + +namespace Exomia.Framework.Mathematics +{ + /// + /// A 2d triangle. + /// + /// + [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 24)] + public readonly struct Triangle2 : IFormattable + { + /// + /// The first x value. + /// + public readonly float X1; //Note: do not reorder this field, unless you know what you are doing. + + /// + /// The first y value. + /// + public readonly float Y1; //Note: do not reorder this field, unless you know what you are doing. + + /// + /// The second y value. + /// + public readonly float X2; //Note: do not reorder this field, unless you know what you are doing. + + /// + /// The second x value. + /// + public readonly float Y2; //Note: do not reorder this field, unless you know what you are doing. + + /// + /// The third x value. + /// + public readonly float X3; //Note: do not reorder this field, unless you know what you are doing. + + /// + /// The third y value. + /// + public readonly float Y3; //Note: do not reorder this field, unless you know what you are doing. + + /// + /// Initializes a new instance of the struct. + /// + /// The first x value. + /// The first y value. + /// The second x value. + /// The second y value. + /// The third x value. + /// The third y value. + public Triangle2(float x1, float y1, float x2, float y2, float x3, float y3) + { + X1 = x1; + Y1 = y1; + X2 = x2; + Y2 = y2; + X3 = x3; + Y3 = y3; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The VectorI2 to process. + /// The VectorI2 to process. + /// The VectorI2 to process. + public Triangle2(VectorI2 a, VectorI2 b, VectorI2 c) + : this(a.X, a.Y, b.X, b.Y, c.X, c.Y) { } + + /// + /// Initializes a new instance of the struct. + /// + /// The Vector2 to process. + /// The Vector2 to process. + /// The Vector2 to process. + public Triangle2(Vector2 a, Vector2 b, Vector2 c) + : this(a.X, a.Y, b.X, b.Y, c.X, c.Y) { } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; false otherwise. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(in Triangle2 other) + { + // ReSharper disable CompareOfFloatsByEqualityOperator + return + X1 == other.X1 && + Y1 == other.Y1 && + X2 == other.X2 && + Y2 == other.Y2 && + X3 == other.X3 && + Y3 == other.Y3; + + // ReSharper restore CompareOfFloatsByEqualityOperator + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override bool Equals(object value) + { + return value is Triangle2 other && Equals(in other); + } + + /// + public override int GetHashCode() + { + return (((((((((X1.GetHashCode() * 307) ^ Y1.GetHashCode()) * 521) ^ X2.GetHashCode()) * 853) ^ + Y2.GetHashCode()) * 443) ^ X3.GetHashCode()) * 937) ^ Y3.GetHashCode(); + } + + /// + public override string ToString() + { + return string.Format( + CultureInfo.CurrentCulture, + "X1:{0} Y1:{1} | X2:{2} Y2:{3} | X3:{4} Y3:{5}", + X1, Y1, X2, Y2, X3, Y3); + } + + /// + /// Returns a that represents this instance. + /// + /// The format. + /// + /// A that represents this instance. + /// + public string ToString(string? format) + { + if (format == null) + { + return ToString(); + } + + return string.Format( + CultureInfo.CurrentCulture, + "X1:{0} Y1:{1} | X2:{2} Y2:{3} | X3:{4} Y3:{5}", + X1.ToString(format, CultureInfo.CurrentCulture), + Y1.ToString(format, CultureInfo.CurrentCulture), + X2.ToString(format, CultureInfo.CurrentCulture), + Y2.ToString(format, CultureInfo.CurrentCulture), + X3.ToString(format, CultureInfo.CurrentCulture), + Y3.ToString(format, CultureInfo.CurrentCulture)); + } + + /// + /// Returns a that represents this instance. + /// + /// The format provider. + /// + /// A that represents this instance. + /// + public string ToString(IFormatProvider formatProvider) + { + return string.Format( + formatProvider, + "X1:{0} Y1:{1} | X2:{2} Y2:{3} | X3:{4} Y3:{5}", + X1, Y1, X2, Y2, X3, Y3); + } + + /// + public string ToString(string? format, IFormatProvider formatProvider) + { + if (format == null) + { + return ToString(formatProvider); + } + + return string.Format( + formatProvider, + "X1:{0} Y1:{1} | X2:{2} Y2:{3} | X3:{4} Y3:{5}", + X1.ToString(format, formatProvider), + Y1.ToString(format, formatProvider), + X2.ToString(format, formatProvider), + Y2.ToString(format, formatProvider), + X3.ToString(format, formatProvider), + Y3.ToString(format, formatProvider)); + } + + /// + /// Rotates the triangle around the given . + /// + /// The triangle. + /// The rotation (in radians). + /// The origin. + /// + /// A new . + /// + public static Triangle2 RotateAround(in Triangle2 triangle, float rotation, in Vector2 origin) + { + double sin = Math.Sin(rotation); + double cos = Math.Cos(rotation); + + float x1 = triangle.X1 - origin.X; + float y1 = triangle.Y1 - origin.Y; + + float x2 = triangle.X2 - origin.X; + float y2 = triangle.Y2 - origin.Y; + + float x3 = triangle.X3 - origin.X; + float y3 = triangle.Y3 - origin.Y; + + return new Triangle2( + (float)((x1 * cos) - (y1 * sin)) + origin.X, (float)((x1 * sin) + (y1 * cos)) + origin.Y, + (float)((x2 * cos) - (y2 * sin)) + origin.X, (float)((x2 * sin) + (y2 * cos)) + origin.Y, + (float)((x3 * cos) - (y3 * sin)) + origin.X, (float)((x3 * sin) + (y3 * cos)) + origin.Y); + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Resources/shaders/canvas.ehlsl b/src/Exomia.Framework/Resources/shaders/canvas.ehlsl index daffd152..8b82e4f0 100644 --- a/src/Exomia.Framework/Resources/shaders/canvas.ehlsl +++ b/src/Exomia.Framework/Resources/shaders/canvas.ehlsl @@ -17,7 +17,6 @@ struct VS_INPUT { float4 p : SV_POSITION0; float4 c : COLOR0; - float2 uv : TEXCOORD0; float m : TEXCOORD1; }; @@ -31,10 +30,10 @@ struct PS_INPUT PS_INPUT VSMain(VS_INPUT input) { - PS_INPUT output = (PS_INPUT)0; - output.p = mul(input.p, g_WorldViewProjectionMatrix); - output.c = input.c / 255; - output.uv = input.uv; + PS_INPUT output; + output.uv = input.p.wz; + output.p = mul(float4(input.p.xy, 0.0f, 1.0f), g_WorldViewProjectionMatrix); + output.c = input.c / 255.0f; output.m = input.m; return output; } @@ -46,10 +45,10 @@ float4 PSMain(PS_INPUT input) : SV_TARGET switch (input.m) { default: - case 0: // texture mode - return g_Texture.Sample(g_Sampler, input.uv) * input.c; - case 0: // color mode + case 0: // texture mode return input.c; + case 1: // color mode + return g_Texture.Sample(g_Sampler, input.uv) * input.c; } } diff --git a/src/Exomia.Framework/UpdateableComparer.cs b/src/Exomia.Framework/UpdateableComparer.cs index 3a05025a..aa935194 100644 --- a/src/Exomia.Framework/UpdateableComparer.cs +++ b/src/Exomia.Framework/UpdateableComparer.cs @@ -30,16 +30,6 @@ public int Compare(IUpdateable left, IUpdateable right) return 0; } - if (left == null) - { - return 1; - } - - if (right == null) - { - return -1; - } - return left.UpdateOrder < right.UpdateOrder ? 1 : -1; } } diff --git a/src/Exomia.Framework/VectorI2.cs b/src/Exomia.Framework/VectorI2.cs index d83c9ed6..9a15baad 100644 --- a/src/Exomia.Framework/VectorI2.cs +++ b/src/Exomia.Framework/VectorI2.cs @@ -93,11 +93,7 @@ public readonly bool Equals(in VectorI2 other) [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly bool Equals(object value) { - if (value is VectorI2 other) - { - return Equals(in other); - } - return false; + return value is VectorI2 other && Equals(in other); } /// diff --git a/src/Exomia.Framework/VectorI3.cs b/src/Exomia.Framework/VectorI3.cs index c04f45ad..173ab08b 100644 --- a/src/Exomia.Framework/VectorI3.cs +++ b/src/Exomia.Framework/VectorI3.cs @@ -120,11 +120,7 @@ public readonly bool Equals(in VectorI3 other) [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly bool Equals(object value) { - if (value is VectorI3 other) - { - return Equals(in other); - } - return false; + return value is VectorI3 other && Equals(in other); } /// From fc34a45eb14e4789ed39280f7d1423b03bcaa109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=A4tz?= Date: Thu, 19 Nov 2020 00:08:40 +0100 Subject: [PATCH 31/44] wip --- .../Exomia.Framework.Example.Canvas/MyGame.cs | 27 ++- src/Exomia.Framework/Graphics/Canvas.Arc.cs | 71 +++++++- src/Exomia.Framework/Graphics/Canvas.Line.cs | 10 +- .../Graphics/Canvas.Polygon.cs | 12 +- .../Graphics/Canvas.Rectangle.cs | 156 +++++++++++++++--- .../Graphics/Canvas.Triangle.cs | 24 +-- .../Canvas.VertexPositionColorTexture.cs | 17 +- src/Exomia.Framework/Graphics/Canvas.cs | 14 +- .../Graphics/RasterizerStates.cs | 2 +- src/Exomia.Framework/Mathematics/Arc2.cs | 2 + .../Resources/shaders/canvas.ehlsl | 64 ++++++- 11 files changed, 323 insertions(+), 76 deletions(-) diff --git a/examples/Exomia.Framework.Example.Canvas/MyGame.cs b/examples/Exomia.Framework.Example.Canvas/MyGame.cs index bde0ae92..088f5d77 100644 --- a/examples/Exomia.Framework.Example.Canvas/MyGame.cs +++ b/examples/Exomia.Framework.Example.Canvas/MyGame.cs @@ -8,9 +8,12 @@ #endregion +using System; using Exomia.Framework.Components; using Exomia.Framework.Game; +using Exomia.Framework.Graphics; using Exomia.Framework.Mathematics; +using Exomia.Framework.Mathematics.Extensions.Vector; using SharpDX; namespace Exomia.Framework.Example.Canvas @@ -20,6 +23,10 @@ namespace Exomia.Framework.Example.Canvas /// sealed class MyGame : Game.Game { +#pragma warning disable IDE0052 // Remove unread private members + private SpriteBatch _spriteBatch = null!; +#pragma warning restore IDE0052 // Remove unread private members + private Graphics.Canvas _canvas = null!; private float k; @@ -58,7 +65,8 @@ protected override void OnInitializeGameGraphicsParameters(ref GameGraphicsParam /// This is where you can query for any required services and load any non-graphic related content. protected override void OnInitialize() { - Content.RootDirectory = "Content"; + Content.RootDirectory = "Content"; + _spriteBatch = ToDispose(new SpriteBatch(GraphicsDevice)); _canvas = ToDispose(new Graphics.Canvas(GraphicsDevice)); /* @@ -100,12 +108,13 @@ protected override void Update(GameTime gameTime) protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); - + _canvas.Begin(); k += gameTime.DeltaTimeS / 2; _canvas.DrawFillTriangle(new Triangle2(100, 50, 150, 100, 50, 100), Color.Red, 0, Vector2.Zero, 1.0f); _canvas.DrawTriangle(new Triangle2(100, 50, 150, 100, 50, 100), Color.Green, 5.0f, 0, Vector2.Zero, 1.0f); + _canvas.DrawFillTriangle( new Triangle2(100, 50, 150, 100, 50, 100), Color.Yellow, k, new Vector2(100, 50), 1.0f); _canvas.DrawTriangle( @@ -113,10 +122,13 @@ protected override void Draw(GameTime gameTime) _canvas.DrawFillRectangle(new RectangleF(200, 200, 100, 50), Color.Red, 0, Vector2.Zero, 1.0f); _canvas.DrawRectangle(new RectangleF(200, 200, 100, 50), Color.Green, 5.0f, 0, Vector2.Zero, 1.0f); - _canvas.DrawFillRectangle(new RectangleF(200, 200, 100, 50), Color.Yellow, k, Vector2.Zero, 1.0f); + + _canvas.DrawFillRectangle(new RectangleF(200, 200, 100, 50), Color.Yellow, k, new Vector2(200, 200), 1.0f); + _canvas.DrawRectangle(new RectangleF(200, 200, 100, 50), Color.Green, 5.0f, k, new Vector2(200, 200), 1.0f); _canvas.DrawLine(new Line2(300, 400, 345, 400), Color.Red, 5.0f, 1.0f); _canvas.DrawLine(new Line2(400, 400, 450, 450), Color.Red, 5.0f, 1.0f); + _canvas.DrawLine(new Line2(300, 450, 345, 450), Color.Yellow, 5.0f, 1.0f); _canvas.DrawLine(new Line2(400, 450, 450, 400), Color.Yellow, 5.0f, 1.0f); @@ -132,6 +144,15 @@ protected override void Draw(GameTime gameTime) new Vector2(600, 600), new Vector2(650, 610), new Vector2(650, 720), new Vector2(450, 750), new Vector2(400, 630) }, Color.Yellow, 5.0f, 1.0f); + + Vector2 center = new Vector2(800, 400); + + _canvas.DrawRectangle(new RectangleF(center.X - 100, center.Y - 100, 200, 200), Color.Green, 5.0f, 0, Vector2.Zero, 1.0f); + _canvas.DrawFillArc(new Arc2(center, 100f), Color.Black, 1.0f); + + Vector2 center2 = new Vector2(1200, 400); + _canvas.DrawRectangle(new RectangleF(center2.X - 100, center.Y - 100, 200, 200), Color.Green, 5.0f, 0, Vector2.Zero, 1.0f); + _canvas.DrawFillArc(new Arc2(center2, 100f, -MathUtil.Pi / 2, -MathUtil.Pi / 4), Color.Blue, 1.0f); _canvas.End(); diff --git a/src/Exomia.Framework/Graphics/Canvas.Arc.cs b/src/Exomia.Framework/Graphics/Canvas.Arc.cs index 5f4f3b43..e137819e 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Arc.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Arc.cs @@ -8,13 +8,18 @@ #endregion +using System.Runtime.CompilerServices; using Exomia.Framework.Mathematics; using SharpDX; +using SharpDX.Direct3D11; namespace Exomia.Framework.Graphics { - public sealed partial class Canvas + public sealed unsafe partial class Canvas { + private static readonly Vector2[] + s_arcCornerOffsets = { new Vector2(-1, -1), new Vector2(1, -1), new Vector2(1, 1), new Vector2(-1, 1) }; + /// /// Draws an arc. /// @@ -25,7 +30,7 @@ public sealed partial class Canvas /// The color. /// The width of the line. /// The opacity. - /// The segments. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawArc(in Vector2 center, float radius, float start, @@ -58,6 +63,7 @@ public void DrawArc(in Arc2 arc, /// The end. /// The color. /// The opacity. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawFillArc(in Vector2 center, float radius, float start, @@ -76,6 +82,65 @@ public void DrawFillArc(in Vector2 center, /// The opacity. public void DrawFillArc(in Arc2 arc, in Color color, - float opacity) { } + float opacity) + { + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (arc.Start == arc.End) { return; } + + Color scaledColor = color * opacity; + + DataBox box = _context.MapSubresource( + _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); + VertexPositionColorTextureMode* vpctmPtr = (VertexPositionColorTextureMode*)box.DataPointer; + + for (int i = 0; i < 4; i++) + { + VertexPositionColorTextureMode* vertex = vpctmPtr + i; + + Vector2 corner = s_arcCornerOffsets[i]; + + vertex->X = arc.X + (corner.X * arc.Radius); + vertex->Y = arc.Y + (corner.Y * arc.Radius); + vertex->Z = arc.X; + vertex->W = arc.Y; + + vertex->R = scaledColor.R; + vertex->G = scaledColor.G; + vertex->B = scaledColor.B; + vertex->A = scaledColor.A; + + if (arc.End < 0) + { + vertex->U = MathUtil.TwoPi + (arc.Start > arc.End ? arc.End : arc.Start); + vertex->V = MathUtil.TwoPi + (arc.Start > arc.End ? arc.Start : arc.End); + } + else + { + vertex->U = arc.Start < arc.End ? arc.End: arc.Start; + vertex->V = arc.Start < arc.End ? arc.Start : arc.End; + } + + vertex->M = FILL_CIRCLE_ARC_MODE; + vertex->O = arc.Radius; + } + + _context.UnmapSubresource(_vertexBuffer, 0); + + //TODO: remove + //Vector4 pos = new Vector4(1600,0, 0, 1); + + //var m = Matrix.Transpose(_projectionMatrix); + + //var k = new Vector4( + // (pos * m.Row1).ToArray().Sum(), + // (pos * m.Row2).ToArray().Sum(), + // (pos * m.Row3).ToArray().Sum(), + // (pos * m.Row4).ToArray().Sum()); + //Console.WriteLine(k); + + PrepareForRendering(); + _context.PixelShader.SetShaderResource(0, _whiteTexture.TextureView); + _context.DrawIndexed(6, 0, 0); + } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.Line.cs b/src/Exomia.Framework/Graphics/Canvas.Line.cs index 95f8791e..b12e74cf 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Line.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Line.cs @@ -66,13 +66,13 @@ public void DrawLine(in Line2 line, // p1 vertex->X = line.X1; vertex->Y = line.Y1; - + vertex->R = color.R * opacity; vertex->G = color.G * opacity; vertex->B = color.B * opacity; vertex->A = color.A * opacity; - vertex->M = 0.0f; + vertex->M = COLOR_MODE; vertex++; // p2 @@ -84,7 +84,7 @@ public void DrawLine(in Line2 line, vertex->B = color.B * opacity; vertex->A = color.A * opacity; - vertex->M = 0.0f; + vertex->M = COLOR_MODE; vertex++; // p2' @@ -96,7 +96,7 @@ public void DrawLine(in Line2 line, vertex->B = color.B * opacity; vertex->A = color.A * opacity; - vertex->M = 0.0f; + vertex->M = COLOR_MODE; vertex++; // p1' @@ -108,7 +108,7 @@ public void DrawLine(in Line2 line, vertex->B = color.B * opacity; vertex->A = color.A * opacity; - vertex->M = 0.0f; + vertex->M = COLOR_MODE; _context.UnmapSubresource(_vertexBuffer, 0); diff --git a/src/Exomia.Framework/Graphics/Canvas.Polygon.cs b/src/Exomia.Framework/Graphics/Canvas.Polygon.cs index 562cbbc2..10498f8b 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Polygon.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Polygon.cs @@ -93,6 +93,8 @@ public void DrawFillPolygon(Vector2[] vertices, in Color color, float opacity) { if (vertices.Length < 3) { throw new ArgumentOutOfRangeException(nameof(vertices.Length)); } + Color scaledColor = color * opacity; + DataBox box = _context.MapSubresource( _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); VertexPositionColorTextureMode* vpctPtr = (VertexPositionColorTextureMode*)box.DataPointer; @@ -120,12 +122,12 @@ public void DrawFillPolygon(Vector2[] vertices, in Color color, float opacity) vertex->X = vs[j].X; vertex->Y = vs[j].Y; - vertex->R = color.R * opacity; - vertex->G = color.G * opacity; - vertex->B = color.B * opacity; - vertex->A = color.A * opacity; + vertex->R = scaledColor.R; + vertex->G = scaledColor.G; + vertex->B = scaledColor.B; + vertex->A = scaledColor.A; - vertex->M = 0.0f; + vertex->M = COLOR_MODE; } _context.UnmapSubresource(_vertexBuffer, 0); diff --git a/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs b/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs index ed76d507..89329463 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs @@ -17,6 +17,9 @@ namespace Exomia.Framework.Graphics { public sealed unsafe partial class Canvas { + private static readonly Vector2[] + s_rectangleCornerOffsets = { Vector2.Zero, Vector2.UnitX, Vector2.One, Vector2.UnitY }; + /// /// Draw rectangle. /// @@ -31,7 +34,106 @@ public void DrawRectangle(in RectangleF destinationRectangle, float lineWidth, float rotation, in Vector2 origin, - float opacity) { } + float opacity) + { + Color scaledColor = color * opacity; + + DataBox box = _context.MapSubresource( + _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); + VertexPositionColorTextureMode* vpctmPtr = (VertexPositionColorTextureMode*)box.DataPointer; + + Vector2 tl = new Vector2(destinationRectangle.Left + lineWidth, destinationRectangle.Top + lineWidth); + Vector2 tr = new Vector2(destinationRectangle.Right - lineWidth, destinationRectangle.Top + lineWidth); + Vector2 br = new Vector2(destinationRectangle.Right - lineWidth, destinationRectangle.Bottom - lineWidth); + Vector2 bl = new Vector2(destinationRectangle.Left + lineWidth, destinationRectangle.Bottom - lineWidth); + + if (rotation == 0f) + { + DrawRect( + ref vpctmPtr, + new Line2(destinationRectangle.TopLeft, destinationRectangle.TopRight), + new Line2(tl, tr), + in scaledColor); + + DrawRect( + ref vpctmPtr, + new Line2(destinationRectangle.TopRight, destinationRectangle.BottomRight), + new Line2(tr, br), + in scaledColor); + + DrawRect( + ref vpctmPtr, + new Line2(destinationRectangle.BottomRight, destinationRectangle.BottomLeft), + new Line2(br, bl), + in scaledColor); + + DrawRect( + ref vpctmPtr, + new Line2(destinationRectangle.BottomLeft, destinationRectangle.TopLeft), + new Line2(bl, tl), + in scaledColor); + } + else + { + double cos = Math.Cos(rotation); + double sin = Math.Sin(rotation); + + float tlx1 = destinationRectangle.Left - origin.X; + float tly1 = destinationRectangle.Top - origin.Y; + + float tlx2 = tl.X - origin.X; + float tly2 = tl.Y - origin.Y; + + float trx1 = destinationRectangle.Right - origin.X; + float try1 = destinationRectangle.Top - origin.Y; + + float trx2 = tr.X - origin.X; + float try2 = tr.Y - origin.Y; + + float brx1 = destinationRectangle.Right - origin.X; + float bry1 = destinationRectangle.Bottom - origin.Y; + + float brx2 = br.X - origin.X; + float bry2 = br.Y - origin.Y; + + float blx1 = destinationRectangle.Left - origin.X; + float bly1 = destinationRectangle.Bottom - origin.Y; + + float blx2 = bl.X - origin.X; + float bly2 = bl.Y - origin.Y; + + Vector2 tl1 = new Vector2( + (float)((tlx1 * cos) - (tly1 * sin)) + origin.X, (float)((tlx1 * sin) + (tly1 * cos)) + origin.Y); + Vector2 tl2 = new Vector2( + (float)((tlx2 * cos) - (tly2 * sin)) + origin.X, (float)((tlx2 * sin) + (tly2 * cos)) + origin.Y); + + Vector2 tr1 = new Vector2( + (float)((trx1 * cos) - (try1 * sin)) + origin.X, (float)((trx1 * sin) + (try1 * cos)) + origin.Y); + Vector2 tr2 = new Vector2( + (float)((trx2 * cos) - (try2 * sin)) + origin.X, (float)((trx2 * sin) + (try2 * cos)) + origin.Y); + + Vector2 br1 = new Vector2( + (float)((brx1 * cos) - (bry1 * sin)) + origin.X, (float)((brx1 * sin) + (bry1 * cos)) + origin.Y); + Vector2 br2 = new Vector2( + (float)((brx2 * cos) - (bry2 * sin)) + origin.X, (float)((brx2 * sin) + (bry2 * cos)) + origin.Y); + + Vector2 bl1 = new Vector2( + (float)((blx1 * cos) - (bly1 * sin)) + origin.X, (float)((blx1 * sin) + (bly1 * cos)) + origin.Y); + Vector2 bl2 = new Vector2( + (float)((blx2 * cos) - (bly2 * sin)) + origin.X, (float)((blx2 * sin) + (bly2 * cos)) + origin.Y); + + DrawRect(ref vpctmPtr, new Line2(tl1, tr1), new Line2(tl2, tr2), in scaledColor); + DrawRect(ref vpctmPtr, new Line2(tr1, br1), new Line2(tr2, br2), in scaledColor); + DrawRect(ref vpctmPtr, new Line2(br1, bl1), new Line2(br2, bl2), in scaledColor); + DrawRect(ref vpctmPtr, new Line2(bl1, tl1), new Line2(bl2, tl2), in scaledColor); + } + + _context.UnmapSubresource(_vertexBuffer, 0); + + PrepareForRendering(); + _context.PixelShader.SetShaderResource(0, _whiteTexture.TextureView); + _context.DrawIndexed(24, 0, 0); + } /// /// Draw fill rectangle. @@ -47,6 +149,8 @@ public void DrawFillRectangle(in RectangleF destinationRectangle, in Vector2 origin, float opacity) { + Color scaledColor = color * opacity; + DataBox box = _context.MapSubresource( _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); VertexPositionColorTextureMode* vpctmPtr = (VertexPositionColorTextureMode*)box.DataPointer; @@ -57,43 +161,41 @@ public void DrawFillRectangle(in RectangleF destinationRectangle, { VertexPositionColorTextureMode* vertex = vpctmPtr + j; - Vector2 corner = s_cornerOffsets[j]; - float posX = (corner.X - origin.X) * destinationRectangle.Width; - float posY = (corner.Y - origin.Y) * destinationRectangle.Height; + Vector2 corner = s_rectangleCornerOffsets[j]; - vertex->X = destinationRectangle.X + posX; - vertex->Y = destinationRectangle.Y + posY; + vertex->X = destinationRectangle.X + (corner.X * destinationRectangle.Width); + vertex->Y = destinationRectangle.Y + (corner.Y * destinationRectangle.Height); - vertex->R = color.R * opacity; - vertex->G = color.G * opacity; - vertex->B = color.B * opacity; - vertex->A = color.A * opacity; + vertex->R = scaledColor.R; + vertex->G = scaledColor.G; + vertex->B = scaledColor.B; + vertex->A = scaledColor.A; - vertex->M = 0.0f; + vertex->M = COLOR_MODE; } } else { - float cos = (float)Math.Cos(rotation); - float sin = (float)Math.Sin(rotation); + double cos = Math.Cos(rotation); + double sin = Math.Sin(rotation); for (int j = 0; j < 4; j++) { VertexPositionColorTextureMode* vertex = vpctmPtr + j; - Vector2 corner = s_cornerOffsets[j]; - float posX = (corner.X - origin.X) * destinationRectangle.Width; - float posY = (corner.Y - origin.Y) * destinationRectangle.Height; + Vector2 corner = s_rectangleCornerOffsets[j]; + float posX = (destinationRectangle.X - origin.X) + (corner.X * destinationRectangle.Width); + float posY = (destinationRectangle.Y - origin.Y) + (corner.Y * destinationRectangle.Height); - vertex->X = (destinationRectangle.X + (posX * cos)) - (posY * sin); - vertex->Y = destinationRectangle.Y + (posX * sin) + (posY * cos); + vertex->X = (float)((origin.X + (posX * cos)) - (posY * sin)); + vertex->Y = (float)(origin.Y + (posX * sin) + (posY * cos)); - vertex->R = color.R * opacity; - vertex->G = color.G * opacity; - vertex->B = color.B * opacity; - vertex->A = color.A * opacity; + vertex->R = scaledColor.R; + vertex->G = scaledColor.G; + vertex->B = scaledColor.B; + vertex->A = scaledColor.A; - vertex->M = 0.0f; + vertex->M = COLOR_MODE; } } @@ -115,7 +217,7 @@ private static void DrawRect(ref VertexPositionColorTextureMode* v, in Line2 lin v->B = c.B; v->A = c.A; - v->M = 0.0f; + v->M = COLOR_MODE; v++; // p2 @@ -127,7 +229,7 @@ private static void DrawRect(ref VertexPositionColorTextureMode* v, in Line2 lin v->B = c.B; v->A = c.A; - v->M = 0.0f; + v->M = COLOR_MODE; v++; // p2' @@ -139,7 +241,7 @@ private static void DrawRect(ref VertexPositionColorTextureMode* v, in Line2 lin v->B = c.B; v->A = c.A; - v->M = 0.0f; + v->M = COLOR_MODE; v++; // p1' @@ -151,7 +253,7 @@ private static void DrawRect(ref VertexPositionColorTextureMode* v, in Line2 lin v->B = c.B; v->A = c.A; - v->M = 0.0f; + v->M = COLOR_MODE; v++; } } diff --git a/src/Exomia.Framework/Graphics/Canvas.Triangle.cs b/src/Exomia.Framework/Graphics/Canvas.Triangle.cs index 98d2590a..48fcdc7d 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Triangle.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Triangle.cs @@ -178,6 +178,8 @@ public void DrawFillTriangle(in Triangle2 triangle, in Vector2 origin, float opacity) { + Color scaledColor = color * opacity; + DataBox box = _context.MapSubresource( _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); VertexPositionColorTextureMode* vpctmPtr = (VertexPositionColorTextureMode*)box.DataPointer; @@ -194,13 +196,13 @@ public void DrawFillTriangle(in Triangle2 triangle, vertex->X = *(tf + (i << 1)); vertex->Y = *(tf + (i << 1) + 1); } + + vertex->R = scaledColor.R; + vertex->G = scaledColor.G; + vertex->B = scaledColor.B; + vertex->A = scaledColor.A; - vertex->R = color.R * opacity; - vertex->G = color.G * opacity; - vertex->B = color.B * opacity; - vertex->A = color.A * opacity; - - vertex->M = 0.0f; + vertex->M = COLOR_MODE; } } else @@ -221,12 +223,12 @@ public void DrawFillTriangle(in Triangle2 triangle, vertex->Y = (sin * x) + (cos * y) + origin.Y; } - vertex->R = color.R * opacity; - vertex->G = color.G * opacity; - vertex->B = color.B * opacity; - vertex->A = color.A * opacity; + vertex->R = scaledColor.R; + vertex->G = scaledColor.G; + vertex->B = scaledColor.B; + vertex->A = scaledColor.A; - vertex->M = 0.0f; + vertex->M = COLOR_MODE; } } diff --git a/src/Exomia.Framework/Graphics/Canvas.VertexPositionColorTexture.cs b/src/Exomia.Framework/Graphics/Canvas.VertexPositionColorTexture.cs index d9c6b84d..17ff674a 100644 --- a/src/Exomia.Framework/Graphics/Canvas.VertexPositionColorTexture.cs +++ b/src/Exomia.Framework/Graphics/Canvas.VertexPositionColorTexture.cs @@ -24,10 +24,10 @@ private struct VertexPositionColorTextureMode public float Y; [FieldOffset(8)] - public readonly float Z; + public float Z; [FieldOffset(12)] - public readonly float W; + public float W; [FieldOffset(16)] public float R; @@ -41,14 +41,17 @@ private struct VertexPositionColorTextureMode [FieldOffset(28)] public float A; - [FieldOffset(8)] - public readonly float U; + [FieldOffset(32)] + public float U; - [FieldOffset(12)] - public readonly float V; + [FieldOffset(36)] + public float V; - [FieldOffset(32)] + [FieldOffset(40)] public float M; + + [FieldOffset(44)] + public float O; } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.cs b/src/Exomia.Framework/Graphics/Canvas.cs index 7260ec9e..e8123434 100644 --- a/src/Exomia.Framework/Graphics/Canvas.cs +++ b/src/Exomia.Framework/Graphics/Canvas.cs @@ -30,15 +30,17 @@ public sealed partial class Canvas : IDisposable private const int MAX_VERTEX_COUNT = MAX_BATCH_SIZE * 4; private const int MAX_INDEX_COUNT = MAX_BATCH_SIZE * 6; private const int BATCH_SEQUENTIAL_THRESHOLD = 1 << 9; - private const int VERTEX_STRIDE = sizeof(float) * 9; + private const int VERTEX_STRIDE = sizeof(float) * 12; + + private const float COLOR_MODE = 0.0f; + private const float TEXTURE_MODE = 1.0f; + private const float FILL_CIRCLE_MODE = 2.0f; + private const float FILL_CIRCLE_ARC_MODE = 3.0f; private static readonly ushort[] s_indices; private static readonly Vector2 s_vector2Zero = Vector2.Zero; private static readonly Rectangle? s_nullRectangle = null; - - private static readonly Vector2[] - s_cornerOffsets = { Vector2.Zero, Vector2.UnitX, Vector2.One, Vector2.UnitY }; - + private readonly Device5 _device; private readonly DeviceContext4 _context; @@ -111,6 +113,7 @@ public Canvas(IGraphicsDevice graphicsDevice) _defaultBlendState = graphicsDevice.BlendStates.Default; _defaultSamplerState = graphicsDevice.SamplerStates.LinearWrap; _defaultDepthStencilState = graphicsDevice.DepthStencilStates.None; + _defaultRasterizerState = graphicsDevice.RasterizerStates.CullBackDepthClipOff; _defaultRasterizerScissorEnabledState = graphicsDevice.RasterizerStates.CullBackDepthClipOffScissorEnabled; @@ -264,6 +267,7 @@ private void PrepareForRendering() Matrix worldViewProjection = Matrix.Transpose(_transformMatrix * _viewMatrix * _projectionMatrix); _context.UpdateSubresource(ref worldViewProjection, _perFrameBuffer); _context.VertexShader.SetConstantBuffer(0, _perFrameBuffer); + _context.PixelShader.SetConstantBuffer(0, _perFrameBuffer); _context.InputAssembler.SetIndexBuffer(_indexBuffer, _indexBuffer.Format, 0); _context.InputAssembler.SetVertexBuffers(0, _vertexBuffer); diff --git a/src/Exomia.Framework/Graphics/RasterizerStates.cs b/src/Exomia.Framework/Graphics/RasterizerStates.cs index 05e93ce9..1e484eca 100644 --- a/src/Exomia.Framework/Graphics/RasterizerStates.cs +++ b/src/Exomia.Framework/Graphics/RasterizerStates.cs @@ -59,7 +59,7 @@ public sealed class RasterizerStates : IDisposable /// . /// public readonly RasterizerState CullBackDepthClipOffScissorEnabled; - + /// /// Initializes a new instance of the class. /// diff --git a/src/Exomia.Framework/Mathematics/Arc2.cs b/src/Exomia.Framework/Mathematics/Arc2.cs index 031e3625..5543a59e 100644 --- a/src/Exomia.Framework/Mathematics/Arc2.cs +++ b/src/Exomia.Framework/Mathematics/Arc2.cs @@ -67,6 +67,8 @@ public Arc2(float x, float y, float radius, float start = 0, float end = MathUti X = x; Y = y; Radius = radius; + Start = start; + End = end; } /// diff --git a/src/Exomia.Framework/Resources/shaders/canvas.ehlsl b/src/Exomia.Framework/Resources/shaders/canvas.ehlsl index 8b82e4f0..706f344f 100644 --- a/src/Exomia.Framework/Resources/shaders/canvas.ehlsl +++ b/src/Exomia.Framework/Resources/shaders/canvas.ehlsl @@ -17,38 +17,84 @@ struct VS_INPUT { float4 p : SV_POSITION0; float4 c : COLOR0; - float m : TEXCOORD1; + float2 uv : TEXCOORD0; + float2 mo : TEXCOORD1; }; struct PS_INPUT { - float4 p : SV_POSITION0; + float4 p : SV_POSITION0; float4 c : COLOR0; float2 uv : TEXCOORD0; - float m : TEXCOORD1; + float2 mo : TEXCOORD1; + float2 zw : TEXCOORD2; }; PS_INPUT VSMain(VS_INPUT input) { - PS_INPUT output; - output.uv = input.p.wz; + PS_INPUT output = (PS_INPUT)0; + output.zw = input.p.zw; output.p = mul(float4(input.p.xy, 0.0f, 1.0f), g_WorldViewProjectionMatrix); output.c = input.c / 255.0f; - output.m = input.m; + output.uv = input.uv; + output.mo = input.mo; return output; } +#define COLOR_MODE 0.0f +#define TEXTURE_MODE 1.0f +#define FILL_CIRCLE_MODE 2.0f +#define FILL_CIRCLE_ARC_MODE 3.0f + +#define PI 3.141593f + float4 PSMain(PS_INPUT input) : SV_TARGET { //discard; //clip(-1); - switch (input.m) + switch (input.mo.x) { default: - case 0: // texture mode + case COLOR_MODE: return input.c; - case 1: // color mode + case TEXTURE_MODE: return g_Texture.Sample(g_Sampler, input.uv) * input.c; + case FILL_CIRCLE_MODE: + { + float2 p = input.p; + float2 center = input.zw; + float radius = input.mo.y; + + float2 d = center - p; + float ls = (d.x * d.x) + (d.y * d.y); + + if (ls > radius * radius) + discard; + + return input.c; + } + case FILL_CIRCLE_ARC_MODE: + { + float2 p = input.p; + float2 center = input.zw; + float radius = input.mo.y; + float start = input.uv.x; + float end = input.uv.y; + + float2 d = center - p; + float ls = (d.x * d.x) + (d.y * d.y); + + if (ls > radius * radius) + discard; + + float angle = PI + atan2(d.y, d.x); + + if (angle >= start && angle <= end) + return input.c; + discard; + return float4(0,0,0,0); + } } } + From 39c6800db5ce3e385c62f2a53c506acfdb316e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=A4tz?= Date: Sat, 21 Nov 2020 01:59:25 +0100 Subject: [PATCH 32/44] wip --- .../Exomia.Framework.Example.Canvas/MyGame.cs | 121 ++++++- src/Exomia.Framework/Graphics/Canvas.Arc.cs | 319 +++++++++++++++--- src/Exomia.Framework/Graphics/Canvas.Line.cs | 13 +- .../Graphics/Canvas.Polygon.cs | 48 +-- .../Graphics/Canvas.Rectangle.cs | 169 ++++------ .../Graphics/Canvas.SpriteFont.cs | 146 ++++---- .../Graphics/Canvas.Texture.cs | 198 ++++++++--- .../Graphics/Canvas.Triangle.cs | 36 +- .../Canvas.VertexPositionColorTexture.cs | 19 ++ src/Exomia.Framework/Graphics/Canvas.cs | 157 ++++++++- .../Graphics/RasterizerStates.cs | 37 +- .../Graphics/SpriteBatch.Line.cs | 2 +- .../Graphics/SpriteBatch.Rectangle.cs | 6 +- .../Graphics/SpriteBatch.SpriteFont.cs | 156 ++++----- .../Graphics/SpriteBatch.Structs.cs | 16 +- .../Graphics/SpriteBatch.Texture.cs | 90 ++--- src/Exomia.Framework/Graphics/SpriteBatch.cs | 1 + src/Exomia.Framework/Graphics/SpriteFont.cs | 148 ++++---- .../{SpriteEffects.cs => TextureEffects.cs} | 4 +- .../Resources/shaders/canvas.ehlsl | 99 +++++- src/Exomia.Framework/Win32/Mem.cs | 18 + 21 files changed, 1193 insertions(+), 610 deletions(-) rename src/Exomia.Framework/Graphics/{SpriteEffects.cs => TextureEffects.cs} (91%) diff --git a/examples/Exomia.Framework.Example.Canvas/MyGame.cs b/examples/Exomia.Framework.Example.Canvas/MyGame.cs index 088f5d77..e99e7ec6 100644 --- a/examples/Exomia.Framework.Example.Canvas/MyGame.cs +++ b/examples/Exomia.Framework.Example.Canvas/MyGame.cs @@ -8,12 +8,10 @@ #endregion -using System; using Exomia.Framework.Components; using Exomia.Framework.Game; using Exomia.Framework.Graphics; using Exomia.Framework.Mathematics; -using Exomia.Framework.Mathematics.Extensions.Vector; using SharpDX; namespace Exomia.Framework.Example.Canvas @@ -47,7 +45,7 @@ public MyGame() EnableTitleInformation = false, }); - IsFixedTimeStep = true; + IsFixedTimeStep = false; TargetElapsedTime = 1000f / 144f; //144fps } @@ -57,7 +55,7 @@ protected override void OnInitializeGameGraphicsParameters(ref GameGraphicsParam parameters.IsMouseVisible = true; parameters.Width = 1600; parameters.Height = 1024; - parameters.EnableMultiSampling = false; + parameters.EnableMultiSampling = true; parameters.MultiSampleCount = MultiSampleCount.MsaaX8; } @@ -65,8 +63,8 @@ protected override void OnInitializeGameGraphicsParameters(ref GameGraphicsParam /// This is where you can query for any required services and load any non-graphic related content. protected override void OnInitialize() { - Content.RootDirectory = "Content"; - _spriteBatch = ToDispose(new SpriteBatch(GraphicsDevice)); + Content.RootDirectory = "Content"; + _spriteBatch = ToDispose(new SpriteBatch(GraphicsDevice)); _canvas = ToDispose(new Graphics.Canvas(GraphicsDevice)); /* @@ -108,10 +106,11 @@ protected override void Update(GameTime gameTime) protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); - - _canvas.Begin(); + + _canvas.Begin(rasterizerState: GraphicsDevice.RasterizerStates.CullBackDepthClipOffMultiSampleOn); k += gameTime.DeltaTimeS / 2; + _canvas.DrawFillTriangle(new Triangle2(100, 50, 150, 100, 50, 100), Color.Red, 0, Vector2.Zero, 1.0f); _canvas.DrawTriangle(new Triangle2(100, 50, 150, 100, 50, 100), Color.Green, 5.0f, 0, Vector2.Zero, 1.0f); @@ -132,27 +131,121 @@ protected override void Draw(GameTime gameTime) _canvas.DrawLine(new Line2(300, 450, 345, 450), Color.Yellow, 5.0f, 1.0f); _canvas.DrawLine(new Line2(400, 450, 450, 400), Color.Yellow, 5.0f, 1.0f); + _canvas.DrawFillPolygon( + new[] + { + new Vector2(400, 300), new Vector2(550, 320), new Vector2(650, 520), new Vector2(520, 450) + }, Color.Red, 1.0f); + + _canvas.DrawPolygon( + new[] + { + new Vector2(400, 300), new Vector2(550, 320), new Vector2(650, 520), new Vector2(520, 450) + }, Color.Yellow, 15.0f, 1.0f); + _canvas.DrawFillPolygon( new[] { new Vector2(600, 600), new Vector2(650, 610), new Vector2(650, 720), new Vector2(450, 750), new Vector2(400, 630) }, Color.Red, 1.0f); + _canvas.DrawPolygon( new[] { new Vector2(600, 600), new Vector2(650, 610), new Vector2(650, 720), new Vector2(450, 750), + new Vector2(400, 630) }, Color.Yellow, 5.0f, 1.0f); - + Vector2 center = new Vector2(800, 400); - - _canvas.DrawRectangle(new RectangleF(center.X - 100, center.Y - 100, 200, 200), Color.Green, 5.0f, 0, Vector2.Zero, 1.0f); - _canvas.DrawFillArc(new Arc2(center, 100f), Color.Black, 1.0f); + + _canvas.DrawRectangle( + new RectangleF(center.X - 100, center.Y - 100, 200, 200), Color.Green, 2, 0, Vector2.Zero, 0.0f); + _canvas.DrawFillArc(new Arc2(center, 100f), Color.Black, 0, center, 1.0f); + + float l = 20; + float r = 100; + _canvas.DrawArc( + new Arc2(center, r, MathUtil.DegreesToRadians(90), MathUtil.DegreesToRadians(-45)), Color.Yellow, l, + 0, Vector2.Zero, 1.0f); + + float rr = (r - l) * 0.685f; + _canvas.DrawRectangle( + new RectangleF(center.X - rr, center.Y - rr, rr * 2, rr * 2), Color.Green, 2, 0, Vector2.Zero, 1.0f); Vector2 center2 = new Vector2(1200, 400); - _canvas.DrawRectangle(new RectangleF(center2.X - 100, center.Y - 100, 200, 200), Color.Green, 5.0f, 0, Vector2.Zero, 1.0f); - _canvas.DrawFillArc(new Arc2(center2, 100f, -MathUtil.Pi / 2, -MathUtil.Pi / 4), Color.Blue, 1.0f); + _canvas.DrawRectangle( + new RectangleF(center2.X - 50f, center2.Y - 50f, 100, 100), Color.Green, 2.0f, 0, Vector2.Zero, 1.0f); + _canvas.DrawFillArc( + new Arc2(center2, 50f, MathUtil.DegreesToRadians(80), MathUtil.DegreesToRadians(200)), Color.Blue, + 0.0f, Vector2.Zero, 1.0f); + + Vector2 center21 = new Vector2(1300, 400); + _canvas.DrawRectangle( + new RectangleF(center21.X - 50f, center21.Y - 50f, 100, 100), Color.Green, 2.0f, 0, Vector2.Zero, 1.0f); + _canvas.DrawFillArc( + new Arc2(center21, 50f, MathUtil.DegreesToRadians(80), MathUtil.DegreesToRadians(-10)), Color.Blue, + 0.0f, Vector2.Zero, 1.0f); + + Vector2 center3 = new Vector2(1200, 500); + _canvas.DrawRectangle( + new RectangleF(center3.X - 50f, center3.Y - 50f, 100, 100), Color.Green, 2.0f, 0, Vector2.Zero, 1.0f); + _canvas.DrawFillArc(new Arc2(center3, 50f, MathUtil.DegreesToRadians(80), 0), Color.Blue, 0.0f, Vector2.Zero, 1.0f); + + Vector2 center31 = new Vector2(1300, 500); + _canvas.DrawRectangle( + new RectangleF(center31.X - 50f, center31.Y - 50f, 100, 100), Color.Green, 2.0f, 0, Vector2.Zero, 1.0f); + _canvas.DrawFillArc( + new Arc2(center31, 50f, MathUtil.DegreesToRadians(-80), MathUtil.DegreesToRadians(200)), Color.Blue, + 0.0f, Vector2.Zero, 1.0f); + + Vector2 center4 = new Vector2(1200, 600); + _canvas.DrawRectangle( + new RectangleF(center4.X - 50f, center4.Y - 50f, 100, 100), Color.Green, 2.0f, 0, Vector2.Zero, 1.0f); + _canvas.DrawFillArc( + new Arc2(center4, 50f, MathUtil.DegreesToRadians(-80), MathUtil.DegreesToRadians(-200)), Color.Blue, + 0.0f, Vector2.Zero, 1.0f); + + Vector2 center41 = new Vector2(1300, 600); + _canvas.DrawRectangle( + new RectangleF(center41.X - 50f, center41.Y - 50f, 100, 100), Color.Green, 2.0f, 0, Vector2.Zero, 1.0f); + _canvas.DrawFillArc( + new Arc2(center41, 50f, MathUtil.DegreesToRadians(-80), MathUtil.DegreesToRadians(0)), Color.Blue, + 0.0f, Vector2.Zero, 1.0f); + + Vector2 center5 = new Vector2(1200, 700); + _canvas.DrawRectangle( + new RectangleF(center5.X - 50f, center5.Y - 50f, 100, 100), Color.Green, 2.0f, 0, Vector2.Zero, 1.0f); + _canvas.DrawFillArc( + new Arc2(center5, 50f, MathUtil.DegreesToRadians(0), MathUtil.DegreesToRadians(200)), Color.Blue, 0.0f, Vector2.Zero, 1.0f); + + Vector2 center51 = new Vector2(1300, 700); + _canvas.DrawRectangle( + new RectangleF(center51.X - 50f, center51.Y - 50f, 100, 100), Color.Green, 2.0f, 0, Vector2.Zero, 1.0f); + _canvas.DrawFillArc( + new Arc2(center51, 50f, MathUtil.DegreesToRadians(0), MathUtil.DegreesToRadians(-200)), Color.Blue, + 0.0f, Vector2.Zero, 1.0f); + + Vector2 center200 = new Vector2(1400, 400); + _canvas.DrawRectangle( + new RectangleF(center200.X - 50f, center200.Y - 50f, 100, 100), Color.Green, 2.0f, 0, Vector2.Zero, 1.0f); + _canvas.DrawFillArc( + new Arc2(center200, 50f, MathUtil.DegreesToRadians(80), MathUtil.DegreesToRadians(10)), Color.Blue, + 0.0f, Vector2.Zero, 1.0f); + _canvas.DrawFillArc( + new Arc2(center200, 50f, MathUtil.DegreesToRadians(80) + k, MathUtil.DegreesToRadians(10) + k), + Color.DeepPink, 0.0f, center200, 1.0f); + + Vector2 center400 = new Vector2(1400, 500); + _canvas.DrawRectangle( + new RectangleF(center400.X - 50f, center400.Y - 50f, 100, 100), Color.Green, 2.0f, 0, Vector2.Zero, + 1.0f); + _canvas.DrawFillArc( + new Arc2(center400, 50f, MathUtil.DegreesToRadians(-200), MathUtil.DegreesToRadians(-80)), Color.Blue, + 0.0f, Vector2.Zero, 1.0f); + + _canvas.Draw(GraphicsDevice.Textures.White, new RectangleF(1400,50, 200,200), Color.YellowGreen); _canvas.End(); diff --git a/src/Exomia.Framework/Graphics/Canvas.Arc.cs b/src/Exomia.Framework/Graphics/Canvas.Arc.cs index e137819e..8f94a695 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Arc.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Arc.cs @@ -8,10 +8,10 @@ #endregion +using System; using System.Runtime.CompilerServices; using Exomia.Framework.Mathematics; using SharpDX; -using SharpDX.Direct3D11; namespace Exomia.Framework.Graphics { @@ -19,7 +19,7 @@ public sealed unsafe partial class Canvas { private static readonly Vector2[] s_arcCornerOffsets = { new Vector2(-1, -1), new Vector2(1, -1), new Vector2(1, 1), new Vector2(-1, 1) }; - + /// /// Draws an arc. /// @@ -29,6 +29,8 @@ private static readonly Vector2[] /// The end. /// The color. /// The width of the line. + /// The rotation. + /// The origin. /// The opacity. [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawArc(in Vector2 center, @@ -37,9 +39,11 @@ public void DrawArc(in Vector2 center, float end, in Color color, float lineWidth, + float rotation, + in Vector2 origin, float opacity) { - DrawArc(new Arc2(center, radius, start, end), in color, lineWidth, opacity); + DrawArc(new Arc2(center, radius, start, end), in color, lineWidth, rotation, in origin, opacity); } /// @@ -48,99 +52,304 @@ public void DrawArc(in Vector2 center, /// The arc. /// The color. /// The width of the line. + /// The rotation. + /// The origin. /// The opacity. - public void DrawArc(in Arc2 arc, - in Color color, - float lineWidth, - float opacity) { } + public void DrawArc(in Arc2 arc, + in Color color, + float lineWidth, + float rotation, + in Vector2 origin, + float opacity) + { + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (arc.Start == arc.End) { return; } + + Color scaledColor = color * opacity; + + float r = arc.Radius; + float rh = (arc.Radius - lineWidth) * 0.685f; + float o = ((uint)(arc.Radius * 10.0f) << 16) | (uint)((arc.Radius - lineWidth) * 10.0f); + + float u = arc.Start; + float v = arc.End; + + if (u > MathUtil.TwoPi) + { + float times = (float)Math.Floor(u / MathUtil.TwoPi); + u -= times * MathUtil.TwoPi; + v -= times * MathUtil.TwoPi; + } + else if (u < -MathUtil.TwoPi) + { + float times = (float)Math.Floor((u + MathUtil.TwoPi) / MathUtil.TwoPi); + u -= times * MathUtil.TwoPi; + v -= times * MathUtil.TwoPi; + } + + if (v > MathUtil.TwoPi) + { + float times = (float)Math.Floor(v / MathUtil.TwoPi); + u -= times * MathUtil.TwoPi; + v -= times * MathUtil.TwoPi; + } + else if (v < -MathUtil.TwoPi) + { + float times = (float)Math.Floor((v + MathUtil.TwoPi) / MathUtil.TwoPi); + u -= times * MathUtil.TwoPi; + v -= times * MathUtil.TwoPi; + } + + if (v < u) + { + float t = u; + u = v; + v = t; + } + + if (u < 0 && v < 0) + { + u += MathUtil.TwoPi; + v += MathUtil.TwoPi; + } + + float x; + float y; + if (rotation == 0.0f) + { + x = arc.X; + y = arc.Y; + } + else + { + float cos = (float)Math.Cos(rotation); + float sin = (float)Math.Sin(rotation); + float dx = arc.X - origin.X; + float dy = arc.Y - origin.Y; + x = ((cos * dx) - (sin * dy)) + origin.X; + y = (sin * dx) + (cos * dy) + origin.Y; + } + + Item* ptr = Reserve(4); + DrawArcRect( + ptr + 0, + new Line2(x - r, y - r, x + r, y - r), + new Line2(x - rh, y - rh, x + rh, y - rh), + scaledColor, x, y, u, v, o); + + DrawArcRect( + ptr + 1, + new Line2(x + r, y - r, x + r, y + r), + new Line2(x + rh, y - rh, x + rh, y + rh), + scaledColor, x, y, u, v, o); + + DrawArcRect( + ptr + 2, + new Line2(x + r, y + r, x - r, y + r), + new Line2(x + rh, y + rh, x - rh, y + rh), + scaledColor, x, y, u, v, o); + + DrawArcRect( + ptr + 3, + new Line2(x - r, arc.Y + r, x - r, y - r), + new Line2(x - rh, arc.Y + rh, x - rh, y - rh), + scaledColor, x, y, u, v, o); + } /// /// Draws a filled arc. /// - /// The center. - /// The radius. - /// The start. - /// The end. - /// The color. - /// The opacity. + /// The center. + /// The radius. + /// The start. + /// The end. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawFillArc(in Vector2 center, float radius, float start, float end, in Color color, + float rotation, + in Vector2 origin, float opacity) { - DrawFillArc(new Arc2(center, radius, start, end), in color, opacity); + DrawFillArc(new Arc2(center, radius, start, end), in color, rotation, in origin, opacity); } /// /// Draws a filled arc. /// - /// The arc. - /// The color. - /// The opacity. - public void DrawFillArc(in Arc2 arc, - in Color color, - float opacity) + /// The arc. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + public void DrawFillArc(in Arc2 arc, + in Color color, + float rotation, + in Vector2 origin, + float opacity) { // ReSharper disable once CompareOfFloatsByEqualityOperator if (arc.Start == arc.End) { return; } Color scaledColor = color * opacity; - DataBox box = _context.MapSubresource( - _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); - VertexPositionColorTextureMode* vpctmPtr = (VertexPositionColorTextureMode*)box.DataPointer; - + float u = arc.Start; + float v = arc.End; + + if (u > MathUtil.TwoPi) + { + float times = (float)Math.Floor(u / MathUtil.TwoPi); + u -= times * MathUtil.TwoPi; + v -= times * MathUtil.TwoPi; + } + else if (u < -MathUtil.TwoPi) + { + float times = (float)Math.Floor((u + MathUtil.TwoPi) / MathUtil.TwoPi); + u -= times * MathUtil.TwoPi; + v -= times * MathUtil.TwoPi; + } + + if (v > MathUtil.TwoPi) + { + float times = (float)Math.Floor(v / MathUtil.TwoPi); + u -= times * MathUtil.TwoPi; + v -= times * MathUtil.TwoPi; + } + else if (v < -MathUtil.TwoPi) + { + float times = (float)Math.Floor((v + MathUtil.TwoPi) / MathUtil.TwoPi); + u -= times * MathUtil.TwoPi; + v -= times * MathUtil.TwoPi; + } + + if (v < u) + { + float t = u; + u = v; + v = t; + } + + if (u < 0 && v < 0) + { + u += MathUtil.TwoPi; + v += MathUtil.TwoPi; + } + + float x; + float y; + if (rotation == 0.0f) + { + x = arc.X; + y = arc.Y; + } + else + { + float cos = (float)Math.Cos(rotation); + float sin = (float)Math.Sin(rotation); + float dx = arc.X - origin.X; + float dy = arc.Y - origin.Y; + x = ((cos * dx) - (sin * dy)) + origin.X; + y = (sin * dx) + (cos * dy) + origin.Y; + } + + // ReSharper disable CompareOfFloatsByEqualityOperator + float m = u == 0.0f && v == MathUtil.TwoPi ? FILL_CIRCLE_MODE : FILL_CIRCLE_ARC_MODE; + // ReSharper enable CompareOfFloatsByEqualityOperator + + Item* ptr = Reserve(1); for (int i = 0; i < 4; i++) { - VertexPositionColorTextureMode* vertex = vpctmPtr + i; + VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)ptr + i; Vector2 corner = s_arcCornerOffsets[i]; - - vertex->X = arc.X + (corner.X * arc.Radius); - vertex->Y = arc.Y + (corner.Y * arc.Radius); - vertex->Z = arc.X; - vertex->W = arc.Y; + + vertex->X = x + (corner.X * arc.Radius); + vertex->Y = y + (corner.Y * arc.Radius); + vertex->Z = x; + vertex->W = y; vertex->R = scaledColor.R; vertex->G = scaledColor.G; vertex->B = scaledColor.B; vertex->A = scaledColor.A; - - if (arc.End < 0) + + vertex->U = u; + vertex->V = v; + + vertex->M = m; + vertex->O = arc.Radius; + } + } + + private static void DrawArcRect(Item* ptr, + in Line2 lineA, + in Line2 lineB, + in Color c, + float z, + float w, + float u, + float v, + float o) + { + // ReSharper disable CompareOfFloatsByEqualityOperator + float m = u == 0.0f && v == MathUtil.TwoPi ? BORDER_CIRCLE_MODE : BORDER_CIRCLE_ARC_MODE; + // ReSharper enable CompareOfFloatsByEqualityOperator + + for (int i = 0; i < 2; i++) + { + VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)ptr + i; + fixed (Line2* t = &lineA) { - vertex->U = MathUtil.TwoPi + (arc.Start > arc.End ? arc.End : arc.Start); - vertex->V = MathUtil.TwoPi + (arc.Start > arc.End ? arc.Start : arc.End); + float* lf = (float*)t; + vertex->X = *(lf + (i << 1)); + vertex->Y = *(lf + (i << 1) + 1); } - else + + vertex->Z = z; + vertex->W = w; + + vertex->R = c.R; + vertex->G = c.G; + vertex->B = c.B; + vertex->A = c.A; + + vertex->U = u; + vertex->V = v; + + vertex->M = m; + vertex->O = o; + } + + for (int i = 1; i >= 0; i--) + { + VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)ptr + 2 + (1 - i); + fixed (Line2* t = &lineB) { - vertex->U = arc.Start < arc.End ? arc.End: arc.Start; - vertex->V = arc.Start < arc.End ? arc.Start : arc.End; + float* lf = (float*)t; + vertex->X = *(lf + (i << 1)); + vertex->Y = *(lf + (i << 1) + 1); } - vertex->M = FILL_CIRCLE_ARC_MODE; - vertex->O = arc.Radius; - } - - _context.UnmapSubresource(_vertexBuffer, 0); + vertex->Z = z; + vertex->W = w; - //TODO: remove - //Vector4 pos = new Vector4(1600,0, 0, 1); + vertex->R = c.R; + vertex->G = c.G; + vertex->B = c.B; + vertex->A = c.A; - //var m = Matrix.Transpose(_projectionMatrix); - - //var k = new Vector4( - // (pos * m.Row1).ToArray().Sum(), - // (pos * m.Row2).ToArray().Sum(), - // (pos * m.Row3).ToArray().Sum(), - // (pos * m.Row4).ToArray().Sum()); - //Console.WriteLine(k); + vertex->U = u; + vertex->V = v; - PrepareForRendering(); - _context.PixelShader.SetShaderResource(0, _whiteTexture.TextureView); - _context.DrawIndexed(6, 0, 0); + vertex->M = m; + vertex->O = o; + } } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.Line.cs b/src/Exomia.Framework/Graphics/Canvas.Line.cs index b12e74cf..6a057290 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Line.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Line.cs @@ -12,7 +12,6 @@ using System.Runtime.CompilerServices; using Exomia.Framework.Mathematics; using SharpDX; -using SharpDX.Direct3D11; namespace Exomia.Framework.Graphics { @@ -59,14 +58,12 @@ public void DrawLine(in Line2 line, float nx = (float)((dy / dl) * lineWidth); float ny = (float)((dx / dl) * lineWidth); - DataBox box = _context.MapSubresource( - _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); - VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)box.DataPointer; + VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)Reserve(1); // p1 vertex->X = line.X1; vertex->Y = line.Y1; - + vertex->R = color.R * opacity; vertex->G = color.G * opacity; vertex->B = color.B * opacity; @@ -109,12 +106,6 @@ public void DrawLine(in Line2 line, vertex->A = color.A * opacity; vertex->M = COLOR_MODE; - - _context.UnmapSubresource(_vertexBuffer, 0); - - PrepareForRendering(); - _context.PixelShader.SetShaderResource(0, _whiteTexture.TextureView); - _context.DrawIndexed(6, 0, 0); } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.Polygon.cs b/src/Exomia.Framework/Graphics/Canvas.Polygon.cs index 10498f8b..b9ab9c5d 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Polygon.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Polygon.cs @@ -12,7 +12,6 @@ using System.Collections.Generic; using Exomia.Framework.Mathematics; using SharpDX; -using SharpDX.Direct3D11; namespace Exomia.Framework.Graphics { @@ -31,9 +30,7 @@ public void DrawPolygon(Vector2[] vertices, in Color color, float lineWidth, flo Color scaledColor = color * opacity; - DataBox box = _context.MapSubresource( - _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); - VertexPositionColorTextureMode* vpctmPtr = (VertexPositionColorTextureMode*)box.DataPointer; + Item* ptr = Reserve(vertices.Length); Line2 previous = new Line2(vertices[vertices.Length - 1], vertices[0]); Line2 perpendicularPrevious = previous.GetPerpendicular(lineWidth); @@ -46,8 +43,7 @@ public void DrawPolygon(Vector2[] vertices, in Color color, float lineWidth, flo ipE = new Vector2(perpendicularCurrent.X1, perpendicularCurrent.Y1); } - Vector2 ip1 = ipE; - int indexCount = 0; + Vector2 ip1 = ipE; for (int i = 1; i < vertices.Length - 1; i++) { Line2 next = new Line2(vertices[i], vertices[i + 1]); @@ -58,8 +54,7 @@ public void DrawPolygon(Vector2[] vertices, in Color color, float lineWidth, flo ip2 = new Vector2(perpendicularNext.X1, perpendicularNext.Y1); } - DrawRect(ref vpctmPtr, current, new Line2(ip1.X, ip1.Y, ip2.X, ip2.Y), in scaledColor); - indexCount++; + DrawRect(ptr + i, current, new Line2(ip1.X, ip1.Y, ip2.X, ip2.Y), in scaledColor); current = next; perpendicularCurrent = perpendicularNext; @@ -71,16 +66,8 @@ public void DrawPolygon(Vector2[] vertices, in Color color, float lineWidth, flo ip3 = new Vector2(perpendicularPrevious.X1, perpendicularPrevious.Y1); } - DrawRect(ref vpctmPtr, current, new Line2(ip1.X, ip1.Y, ip3.X, ip3.Y), in scaledColor); - DrawRect(ref vpctmPtr, previous, new Line2(ip3.X, ip3.Y, ipE.X, ipE.Y), in scaledColor); - - indexCount += 2; - - _context.UnmapSubresource(_vertexBuffer, 0); - - PrepareForRendering(); - _context.PixelShader.SetShaderResource(0, _whiteTexture.TextureView); - _context.DrawIndexed(indexCount * 6, 0, 0); + DrawRect(ptr, current, new Line2(ip1.X, ip1.Y, ip3.X, ip3.Y), in scaledColor); + DrawRect(ptr + (vertices.Length - 1), previous, new Line2(ip3.X, ip3.Y, ipE.X, ipE.Y), in scaledColor); } /// @@ -95,29 +82,24 @@ public void DrawFillPolygon(Vector2[] vertices, in Color color, float opacity) Color scaledColor = color * opacity; - DataBox box = _context.MapSubresource( - _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); - VertexPositionColorTextureMode* vpctPtr = (VertexPositionColorTextureMode*)box.DataPointer; - // TODO: refactor; remove list; place directly into _vertexBuffer - List vs = new List(); - int indexCount = 0; - for (int i = 1; i < vertices.Length; i += 2) + List vs = new List(); + for (int i = 1; i < vertices.Length - 1; i += 2) { - indexCount++; vs.Add(vertices[0]); vs.Add(vertices[i]); vs.Add(vertices[i + 1]); if (i + 2 < vertices.Length) { - indexCount++; vs.Add(vertices[i + 2]); } } + Item* ptr = Reserve((vs.Count + 1) / 4); + for (int j = 0; j < vs.Count; j++) { - VertexPositionColorTextureMode* vertex = vpctPtr + j; + VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)ptr + j; vertex->X = vs[j].X; vertex->Y = vs[j].Y; @@ -130,11 +112,11 @@ public void DrawFillPolygon(Vector2[] vertices, in Color color, float opacity) vertex->M = COLOR_MODE; } - _context.UnmapSubresource(_vertexBuffer, 0); - - PrepareForRendering(); - _context.PixelShader.SetShaderResource(0, _whiteTexture.TextureView); - _context.DrawIndexed(indexCount * 3, 0, 0); + if ((vs.Count & 1) == 1) + { + *((VertexPositionColorTextureMode*)ptr + vs.Count) = + *((VertexPositionColorTextureMode*)ptr + (vs.Count - 3)); + } } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs b/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs index 89329463..04968095 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs @@ -11,7 +11,6 @@ using System; using Exomia.Framework.Mathematics; using SharpDX; -using SharpDX.Direct3D11; namespace Exomia.Framework.Graphics { @@ -23,13 +22,13 @@ private static readonly Vector2[] /// /// Draw rectangle. /// - /// The destination rectangle. - /// The color. - /// The width of the line. - /// The rotation. - /// The origin. - /// The opacity. - public void DrawRectangle(in RectangleF destinationRectangle, + /// The destination rectangle. + /// The color. + /// The width of the line. + /// The rotation. + /// The origin. + /// The opacity. + public void DrawRectangle(in RectangleF destination, in Color color, float lineWidth, float rotation, @@ -38,38 +37,36 @@ public void DrawRectangle(in RectangleF destinationRectangle, { Color scaledColor = color * opacity; - DataBox box = _context.MapSubresource( - _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); - VertexPositionColorTextureMode* vpctmPtr = (VertexPositionColorTextureMode*)box.DataPointer; + Vector2 tl = new Vector2(destination.Left + lineWidth, destination.Top + lineWidth); + Vector2 tr = new Vector2(destination.Right - lineWidth, destination.Top + lineWidth); + Vector2 br = new Vector2(destination.Right - lineWidth, destination.Bottom - lineWidth); + Vector2 bl = new Vector2(destination.Left + lineWidth, destination.Bottom - lineWidth); - Vector2 tl = new Vector2(destinationRectangle.Left + lineWidth, destinationRectangle.Top + lineWidth); - Vector2 tr = new Vector2(destinationRectangle.Right - lineWidth, destinationRectangle.Top + lineWidth); - Vector2 br = new Vector2(destinationRectangle.Right - lineWidth, destinationRectangle.Bottom - lineWidth); - Vector2 bl = new Vector2(destinationRectangle.Left + lineWidth, destinationRectangle.Bottom - lineWidth); + Item* ptr = Reserve(4); if (rotation == 0f) { DrawRect( - ref vpctmPtr, - new Line2(destinationRectangle.TopLeft, destinationRectangle.TopRight), + ptr + 0, + new Line2(destination.TopLeft, destination.TopRight), new Line2(tl, tr), in scaledColor); DrawRect( - ref vpctmPtr, - new Line2(destinationRectangle.TopRight, destinationRectangle.BottomRight), + ptr + 1, + new Line2(destination.TopRight, destination.BottomRight), new Line2(tr, br), in scaledColor); DrawRect( - ref vpctmPtr, - new Line2(destinationRectangle.BottomRight, destinationRectangle.BottomLeft), + ptr + 2, + new Line2(destination.BottomRight, destination.BottomLeft), new Line2(br, bl), in scaledColor); DrawRect( - ref vpctmPtr, - new Line2(destinationRectangle.BottomLeft, destinationRectangle.TopLeft), + ptr + 3, + new Line2(destination.BottomLeft, destination.TopLeft), new Line2(bl, tl), in scaledColor); } @@ -78,26 +75,26 @@ public void DrawRectangle(in RectangleF destinationRectangle, double cos = Math.Cos(rotation); double sin = Math.Sin(rotation); - float tlx1 = destinationRectangle.Left - origin.X; - float tly1 = destinationRectangle.Top - origin.Y; + float tlx1 = destination.Left - origin.X; + float tly1 = destination.Top - origin.Y; float tlx2 = tl.X - origin.X; float tly2 = tl.Y - origin.Y; - float trx1 = destinationRectangle.Right - origin.X; - float try1 = destinationRectangle.Top - origin.Y; + float trx1 = destination.Right - origin.X; + float try1 = destination.Top - origin.Y; float trx2 = tr.X - origin.X; float try2 = tr.Y - origin.Y; - float brx1 = destinationRectangle.Right - origin.X; - float bry1 = destinationRectangle.Bottom - origin.Y; + float brx1 = destination.Right - origin.X; + float bry1 = destination.Bottom - origin.Y; float brx2 = br.X - origin.X; float bry2 = br.Y - origin.Y; - float blx1 = destinationRectangle.Left - origin.X; - float bly1 = destinationRectangle.Bottom - origin.Y; + float blx1 = destination.Left - origin.X; + float bly1 = destination.Bottom - origin.Y; float blx2 = bl.X - origin.X; float bly2 = bl.Y - origin.Y; @@ -122,28 +119,22 @@ public void DrawRectangle(in RectangleF destinationRectangle, Vector2 bl2 = new Vector2( (float)((blx2 * cos) - (bly2 * sin)) + origin.X, (float)((blx2 * sin) + (bly2 * cos)) + origin.Y); - DrawRect(ref vpctmPtr, new Line2(tl1, tr1), new Line2(tl2, tr2), in scaledColor); - DrawRect(ref vpctmPtr, new Line2(tr1, br1), new Line2(tr2, br2), in scaledColor); - DrawRect(ref vpctmPtr, new Line2(br1, bl1), new Line2(br2, bl2), in scaledColor); - DrawRect(ref vpctmPtr, new Line2(bl1, tl1), new Line2(bl2, tl2), in scaledColor); + DrawRect(ptr + 0, new Line2(tl1, tr1), new Line2(tl2, tr2), in scaledColor); + DrawRect(ptr + 1, new Line2(tr1, br1), new Line2(tr2, br2), in scaledColor); + DrawRect(ptr + 2, new Line2(br1, bl1), new Line2(br2, bl2), in scaledColor); + DrawRect(ptr + 3, new Line2(bl1, tl1), new Line2(bl2, tl2), in scaledColor); } - - _context.UnmapSubresource(_vertexBuffer, 0); - - PrepareForRendering(); - _context.PixelShader.SetShaderResource(0, _whiteTexture.TextureView); - _context.DrawIndexed(24, 0, 0); } /// /// Draw fill rectangle. /// - /// The destination rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - public void DrawFillRectangle(in RectangleF destinationRectangle, + /// The destination rectangle. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + public void DrawFillRectangle(in RectangleF destination, in Color color, float rotation, in Vector2 origin, @@ -151,20 +142,18 @@ public void DrawFillRectangle(in RectangleF destinationRectangle, { Color scaledColor = color * opacity; - DataBox box = _context.MapSubresource( - _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); - VertexPositionColorTextureMode* vpctmPtr = (VertexPositionColorTextureMode*)box.DataPointer; + Item* ptr = Reserve(1); if (rotation == 0f) { for (int j = 0; j < 4; j++) { - VertexPositionColorTextureMode* vertex = vpctmPtr + j; + VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)ptr + j; Vector2 corner = s_rectangleCornerOffsets[j]; - vertex->X = destinationRectangle.X + (corner.X * destinationRectangle.Width); - vertex->Y = destinationRectangle.Y + (corner.Y * destinationRectangle.Height); + vertex->X = destination.X + (corner.X * destination.Width); + vertex->Y = destination.Y + (corner.Y * destination.Height); vertex->R = scaledColor.R; vertex->G = scaledColor.G; @@ -181,11 +170,11 @@ public void DrawFillRectangle(in RectangleF destinationRectangle, for (int j = 0; j < 4; j++) { - VertexPositionColorTextureMode* vertex = vpctmPtr + j; + VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)ptr + j; Vector2 corner = s_rectangleCornerOffsets[j]; - float posX = (destinationRectangle.X - origin.X) + (corner.X * destinationRectangle.Width); - float posY = (destinationRectangle.Y - origin.Y) + (corner.Y * destinationRectangle.Height); + float posX = (destination.X - origin.X) + (corner.X * destination.Width); + float posY = (destination.Y - origin.Y) + (corner.Y * destination.Height); vertex->X = (float)((origin.X + (posX * cos)) - (posY * sin)); vertex->Y = (float)(origin.Y + (posX * sin) + (posY * cos)); @@ -198,63 +187,53 @@ public void DrawFillRectangle(in RectangleF destinationRectangle, vertex->M = COLOR_MODE; } } - - _context.UnmapSubresource(_vertexBuffer, 0); - - PrepareForRendering(); - _context.PixelShader.SetShaderResource(0, _whiteTexture.TextureView); - _context.DrawIndexed(6, 0, 0); } - private static void DrawRect(ref VertexPositionColorTextureMode* v, in Line2 lineA, in Line2 lineB, in Color c) + private static void DrawRect(Item* ptr, in Line2 lineA, in Line2 lineB, in Color c) { // p1 - v->X = lineA.X1; - v->Y = lineA.Y1; + ptr->V1.X = lineA.X1; + ptr->V1.Y = lineA.Y1; - v->R = c.R; - v->G = c.G; - v->B = c.B; - v->A = c.A; + ptr->V1.R = c.R; + ptr->V1.G = c.G; + ptr->V1.B = c.B; + ptr->V1.A = c.A; - v->M = COLOR_MODE; - v++; + ptr->V1.M = COLOR_MODE; // p2 - v->X = lineA.X2; - v->Y = lineA.Y2; + ptr->V2.X = lineA.X2; + ptr->V2.Y = lineA.Y2; - v->R = c.R; - v->G = c.G; - v->B = c.B; - v->A = c.A; + ptr->V2.R = c.R; + ptr->V2.G = c.G; + ptr->V2.B = c.B; + ptr->V2.A = c.A; - v->M = COLOR_MODE; - v++; + ptr->V2.M = COLOR_MODE; // p2' - v->X = lineB.X2; - v->Y = lineB.Y2; + ptr->V3.X = lineB.X2; + ptr->V3.Y = lineB.Y2; - v->R = c.R; - v->G = c.G; - v->B = c.B; - v->A = c.A; + ptr->V3.R = c.R; + ptr->V3.G = c.G; + ptr->V3.B = c.B; + ptr->V3.A = c.A; - v->M = COLOR_MODE; - v++; + ptr->V3.M = COLOR_MODE; // p1' - v->X = lineB.X1; - v->Y = lineB.Y1; + ptr->V4.X = lineB.X1; + ptr->V4.Y = lineB.Y1; - v->R = c.R; - v->G = c.G; - v->B = c.B; - v->A = c.A; + ptr->V4.R = c.R; + ptr->V4.G = c.G; + ptr->V4.B = c.B; + ptr->V4.A = c.A; - v->M = COLOR_MODE; - v++; + ptr->V4.M = COLOR_MODE; } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.SpriteFont.cs b/src/Exomia.Framework/Graphics/Canvas.SpriteFont.cs index 73f6c91f..5e32b056 100644 --- a/src/Exomia.Framework/Graphics/Canvas.SpriteFont.cs +++ b/src/Exomia.Framework/Graphics/Canvas.SpriteFont.cs @@ -26,7 +26,7 @@ public sealed partial class Canvas [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, string text, in Vector2 position, in Color color) { - font.Draw(DrawTextInternal, text, position, color, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0f); + font.Draw(DrawTextInternal, text, position, color, 0f, Vector2.Zero, 1.0f, TextureEffects.None, 0f); } /// @@ -40,7 +40,7 @@ public void DrawText(SpriteFont font, string text, in Vector2 position, in Color [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, string text, in Vector2 position, in Color color, float rotation) { - font.Draw(DrawTextInternal, text, position, color, rotation, Vector2.Zero, 1.0f, SpriteEffects.None, 0f); + font.Draw(DrawTextInternal, text, position, color, rotation, Vector2.Zero, 1.0f, TextureEffects.None, 0f); } /// @@ -55,14 +55,14 @@ public void DrawText(SpriteFont font, string text, in Vector2 position, in Color /// The opacity. /// The effects. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - string text, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects) + public void DrawText(SpriteFont font, + string text, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects) { font.Draw(DrawTextInternal, text, position, color, rotation, origin, opacity, effects, 0f); } @@ -81,16 +81,16 @@ public void DrawText(SpriteFont font, /// The opacity. /// The effects. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - string text, - int start, - int end, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects) + public void DrawText(SpriteFont font, + string text, + int start, + int end, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects) { font.Draw(DrawTextInternal, text, start, end, position, color, rotation, origin, opacity, effects, 0f); } @@ -110,17 +110,17 @@ public void DrawText(SpriteFont font, /// The opacity. /// The effects. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - string text, - int start, - int end, - in Vector2 position, - in Size2F dimension, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects) + public void DrawText(SpriteFont font, + string text, + int start, + int end, + in Vector2 position, + in Size2F dimension, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects) { font.Draw( DrawTextInternal, text, start, end, position, dimension, color, rotation, origin, opacity, effects, 0f); @@ -137,7 +137,7 @@ public void DrawText(SpriteFont font, [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, in Color color, float rotation) { - font.Draw(DrawTextInternal, text, position, color, rotation, Vector2.Zero, 1.0f, SpriteEffects.None, 0f); + font.Draw(DrawTextInternal, text, position, color, rotation, Vector2.Zero, 1.0f, TextureEffects.None, 0f); } /// @@ -152,14 +152,14 @@ public void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, i /// The opacity. /// The effects. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - StringBuilder text, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects) + public void DrawText(SpriteFont font, + StringBuilder text, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects) { font.Draw(DrawTextInternal, text, position, color, rotation, origin, opacity, effects, 0f); } @@ -178,16 +178,16 @@ public void DrawText(SpriteFont font, /// The opacity. /// The effects. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - StringBuilder text, - int start, - int end, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects) + public void DrawText(SpriteFont font, + StringBuilder text, + int start, + int end, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects) { font.Draw(DrawTextInternal, text, start, end, position, color, rotation, origin, opacity, effects, 0f); } @@ -207,17 +207,17 @@ public void DrawText(SpriteFont font, /// The opacity. /// The effects. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - StringBuilder text, - int start, - int end, - in Vector2 position, - in Size2F dimension, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects) + public void DrawText(SpriteFont font, + StringBuilder text, + int start, + int end, + in Vector2 position, + in Size2F dimension, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects) { font.Draw( DrawTextInternal, text, start, end, position, dimension, color, rotation, origin, opacity, effects, 0f); @@ -237,18 +237,18 @@ public void DrawText(SpriteFont font, /// The effects. /// The depth of the layer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void DrawTextInternal(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float scale, - float opacity, - SpriteEffects effects, - float layerDepth) + internal void DrawTextInternal(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float scale, + float opacity, + TextureEffects effects, + float layerDepth) { - DrawSprite( + DrawTexture( texture, new RectangleF(position.X, position.Y, scale, scale), true, sourceRectangle, color, rotation, origin, opacity, effects); } @@ -263,7 +263,7 @@ internal void DrawTextInternal(Texture texture, [MethodImpl(MethodImplOptions.AggressiveInlining)] private void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, in Color color) { - font.Draw(DrawTextInternal, text, position, color, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0f); + font.Draw(DrawTextInternal, text, position, color, 0f, Vector2.Zero, 1.0f, TextureEffects.None, 0f); } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.Texture.cs b/src/Exomia.Framework/Graphics/Canvas.Texture.cs index 51081ee8..e9259965 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Texture.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Texture.cs @@ -8,12 +8,13 @@ #endregion +using System; using System.Runtime.CompilerServices; using SharpDX; namespace Exomia.Framework.Graphics { - public sealed partial class Canvas + public sealed unsafe partial class Canvas { /// /// Draws. @@ -24,9 +25,9 @@ public sealed partial class Canvas [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Draw(Texture texture, in Vector2 position, in Color color) { - DrawSprite( + DrawTexture( texture, new RectangleF(position.X, position.Y, 1f, 1f), true, - s_nullRectangle, color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None); + s_nullRectangle, color, 0f, s_vector2Zero, 1.0f, TextureEffects.None); } /// @@ -38,9 +39,9 @@ public void Draw(Texture texture, in Vector2 position, in Color color) [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Draw(Texture texture, in RectangleF destinationRectangle, in Color color) { - DrawSprite( + DrawTexture( texture, destinationRectangle, false, - s_nullRectangle, color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None); + s_nullRectangle, color, 0f, s_vector2Zero, 1.0f, TextureEffects.None); } /// @@ -53,9 +54,9 @@ public void Draw(Texture texture, in RectangleF destinationRectangle, in Color c [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Draw(Texture texture, in Vector2 position, in Rectangle? sourceRectangle, in Color color) { - DrawSprite( + DrawTexture( texture, new RectangleF(position.X, position.Y, 1f, 1f), true, - sourceRectangle, color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None); + sourceRectangle, color, 0f, s_vector2Zero, 1.0f, TextureEffects.None); } /// @@ -71,9 +72,9 @@ public void Draw(Texture texture, in Rectangle? sourceRectangle, in Color color) { - DrawSprite( + DrawTexture( texture, destinationRectangle, false, - sourceRectangle, color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None); + sourceRectangle, color, 0f, s_vector2Zero, 1.0f, TextureEffects.None); } /// @@ -88,16 +89,16 @@ public void Draw(Texture texture, /// The opacity. /// The effects. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Draw(Texture texture, - in RectangleF destinationRectangle, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects) + public void Draw(Texture texture, + in RectangleF destinationRectangle, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects) { - DrawSprite( + DrawTexture( texture, destinationRectangle, false, sourceRectangle, color, rotation, origin, opacity, effects); } @@ -115,17 +116,17 @@ public void Draw(Texture texture, /// The opacity. /// The effects. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Draw(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float scale, - float opacity, - SpriteEffects effects) + public void Draw(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float scale, + float opacity, + TextureEffects effects) { - DrawSprite( + DrawTexture( texture, new RectangleF(position.X, position.Y, scale, scale), true, sourceRectangle, color, rotation, origin, opacity, effects); } @@ -143,17 +144,17 @@ public void Draw(Texture texture, /// The opacity. /// The effects. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Draw(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - in Vector2 scale, - float opacity, - SpriteEffects effects) + public void Draw(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + in Vector2 scale, + float opacity, + TextureEffects effects) { - DrawSprite( + DrawTexture( texture, new RectangleF(position.X, position.Y, scale.X, scale.Y), true, sourceRectangle, color, rotation, origin, opacity, effects); } @@ -170,14 +171,117 @@ public void Draw(Texture texture, /// The origin. /// The opacity. /// The effects. - private void DrawSprite(Texture texture, - in RectangleF destination, - bool scaleDestination, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects) { } + private void DrawTexture(Texture texture, + in RectangleF destination, + bool scaleDestination, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects) + + { + long tp = texture.TexturePointer.ToInt64(); + if (!_textures.ContainsKey(tp)) + { + bool lockTaken = false; + try + { + _spinLock.Enter(ref lockTaken); + if (!_textures.ContainsKey(tp)) + { + _textures.Add(tp, texture); + } + } + finally + { + if (lockTaken) + { + _spinLock.Exit(false); + } + } + } + + Color scaledColor = color * opacity; + + Rectangle s = sourceRectangle ?? new Rectangle(0, 0, texture.Width, texture.Height); + RectangleF d = destination; + if (scaleDestination) + { + d.Width *= s.Width; + d.Height *= s.Width; + } + + if (d.Width < 0) + { + d.X += d.Width; + d.Width = -d.Width; + } + + if (d.Height < 0) + { + d.Y += d.Height; + d.Height = -d.Height; + } + + float deltaX = 1.0f / texture.Width; + float deltaY = 1.0f / texture.Height; + + Item* ptr = Reserve(1); + if (rotation == 0f) + { + for (int j = 0; j < 4; j++) + { + VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)ptr + j; + + Vector2 corner = s_rectangleCornerOffsets[j]; + + vertex->X = d.X + ((corner.X - origin.X) * d.Width); + vertex->Y = d.Y + ((corner.Y - origin.Y) * d.Height); + vertex->ZW = tp; + + vertex->R = scaledColor.R; + vertex->G = scaledColor.G; + vertex->B = scaledColor.B; + vertex->A = scaledColor.A; + + corner = s_rectangleCornerOffsets[j ^ 0]; + vertex->U = (s.X + (corner.X * s.Width)) * deltaX; + vertex->V = (s.Y + (corner.Y * s.Height)) * deltaY; + + vertex->M = TEXTURE_MODE; + } + } + else + { + double cos = Math.Cos(rotation); + double sin = Math.Sin(rotation); + + for (int j = 0; j < 4; j++) + { + VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)ptr + j; + + Vector2 corner = s_rectangleCornerOffsets[j]; + float posX = (corner.X - origin.X) * d.Width; + float posY = (corner.Y - origin.Y) * d.Height; + + vertex->X = (float)((d.X + (posX * cos)) - (posY * sin)); + vertex->Y = (float)(d.Y + (posX * sin) + (posY * cos)); + vertex->ZW = tp; + + vertex->R = scaledColor.R; + vertex->G = scaledColor.G; + vertex->B = scaledColor.B; + vertex->A = scaledColor.A; + + corner = s_rectangleCornerOffsets[j ^ (int)effects]; + vertex->U = (s.X + (corner.X * s.Width)) * deltaX; + vertex->V = (s.Y + (corner.Y * s.Height)) * deltaY; + + vertex->M = TEXTURE_MODE; + } + } + } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.Triangle.cs b/src/Exomia.Framework/Graphics/Canvas.Triangle.cs index 48fcdc7d..7308485e 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Triangle.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Triangle.cs @@ -82,10 +82,6 @@ public void DrawTriangle(in Triangle2 triangle, Triangle2 t = rotation == 0.0 ? triangle : Triangle2.RotateAround(triangle, rotation, origin); Color scaledColor = color * opacity; - DataBox box = _context.MapSubresource( - _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); - VertexPositionColorTextureMode* vpctmPtr = (VertexPositionColorTextureMode*)box.DataPointer; - Line2 a = new Line2(t.X1, t.Y1, t.X2, t.Y2); Line2 perpendicularA = a.GetPerpendicular(lineWidth); @@ -110,15 +106,10 @@ public void DrawTriangle(in Triangle2 triangle, throw new ArgumentException("The lines c and a are parallel to each other! Check the triangle points!"); } - DrawRect(ref vpctmPtr, a, new Line2(ipCa.X, ipCa.Y, ipAb.X, ipAb.Y), in scaledColor); - DrawRect(ref vpctmPtr, b, new Line2(ipAb.X, ipAb.Y, ipBc.X, ipBc.Y), in scaledColor); - DrawRect(ref vpctmPtr, c, new Line2(ipBc.X, ipBc.Y, ipCa.X, ipCa.Y), in scaledColor); - - _context.UnmapSubresource(_vertexBuffer, 0); - - PrepareForRendering(); - _context.PixelShader.SetShaderResource(0, _whiteTexture.TextureView); - _context.DrawIndexed(18, 0, 0); + Item* ptr = Reserve(3); + DrawRect(ptr + 0, a, new Line2(ipCa.X, ipCa.Y, ipAb.X, ipAb.Y), in scaledColor); + DrawRect(ptr + 1, b, new Line2(ipAb.X, ipAb.Y, ipBc.X, ipBc.Y), in scaledColor); + DrawRect(ptr + 2, c, new Line2(ipBc.X, ipBc.Y, ipCa.X, ipCa.Y), in scaledColor); } /// @@ -179,16 +170,14 @@ public void DrawFillTriangle(in Triangle2 triangle, float opacity) { Color scaledColor = color * opacity; - - DataBox box = _context.MapSubresource( - _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); - VertexPositionColorTextureMode* vpctmPtr = (VertexPositionColorTextureMode*)box.DataPointer; + + Item* ptr = Reserve(1); if (rotation == 0.0f) { for (int i = 0; i < 3; i++) { - VertexPositionColorTextureMode* vertex = vpctmPtr + i; + VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)ptr + i; fixed (Triangle2* t = &triangle) { @@ -196,7 +185,7 @@ public void DrawFillTriangle(in Triangle2 triangle, vertex->X = *(tf + (i << 1)); vertex->Y = *(tf + (i << 1) + 1); } - + vertex->R = scaledColor.R; vertex->G = scaledColor.G; vertex->B = scaledColor.B; @@ -212,7 +201,7 @@ public void DrawFillTriangle(in Triangle2 triangle, for (int i = 0; i < 3; i++) { - VertexPositionColorTextureMode* vertex = vpctmPtr + i; + VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)ptr + i; fixed (Triangle2* t = &triangle) { @@ -232,11 +221,8 @@ public void DrawFillTriangle(in Triangle2 triangle, } } - _context.UnmapSubresource(_vertexBuffer, 0); - - PrepareForRendering(); - _context.PixelShader.SetShaderResource(0, _whiteTexture.TextureView); - _context.DrawIndexed(3, 0, 0); + // INFO: currently we need 4 vertices so we just copy the first one as the 4th one + *((VertexPositionColorTextureMode*)ptr + 3) = *(VertexPositionColorTextureMode*)ptr; } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.VertexPositionColorTexture.cs b/src/Exomia.Framework/Graphics/Canvas.VertexPositionColorTexture.cs index 17ff674a..e0773add 100644 --- a/src/Exomia.Framework/Graphics/Canvas.VertexPositionColorTexture.cs +++ b/src/Exomia.Framework/Graphics/Canvas.VertexPositionColorTexture.cs @@ -14,6 +14,22 @@ namespace Exomia.Framework.Graphics { public sealed partial class Canvas { + [StructLayout(LayoutKind.Explicit, Size = VERTEX_STRIDE * 4)] + private struct Item + { + [FieldOffset(VERTEX_STRIDE * 0)] + public VertexPositionColorTextureMode V1; + + [FieldOffset(VERTEX_STRIDE * 1)] + public VertexPositionColorTextureMode V2; + + [FieldOffset(VERTEX_STRIDE * 2)] + public VertexPositionColorTextureMode V3; + + [FieldOffset(VERTEX_STRIDE * 3)] + public VertexPositionColorTextureMode V4; + } + [StructLayout(LayoutKind.Explicit, Size = VERTEX_STRIDE)] private struct VertexPositionColorTextureMode { @@ -29,6 +45,9 @@ private struct VertexPositionColorTextureMode [FieldOffset(12)] public float W; + [FieldOffset(8)] + public long ZW; + [FieldOffset(16)] public float R; diff --git a/src/Exomia.Framework/Graphics/Canvas.cs b/src/Exomia.Framework/Graphics/Canvas.cs index e8123434..b60d2bd7 100644 --- a/src/Exomia.Framework/Graphics/Canvas.cs +++ b/src/Exomia.Framework/Graphics/Canvas.cs @@ -9,8 +9,12 @@ #endregion using System; +using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; using Exomia.Framework.Graphics.Buffers; using Exomia.Framework.Graphics.Shader; using Exomia.Framework.Resources; @@ -23,7 +27,7 @@ namespace Exomia.Framework.Graphics /// /// A canvas. This class cannot be inherited. /// - public sealed partial class Canvas : IDisposable + public sealed unsafe partial class Canvas : IDisposable { private const int MAX_BATCH_SIZE = 1 << 13; private const int INITIAL_QUEUE_SIZE = 1 << 7; @@ -31,17 +35,19 @@ public sealed partial class Canvas : IDisposable private const int MAX_INDEX_COUNT = MAX_BATCH_SIZE * 6; private const int BATCH_SEQUENTIAL_THRESHOLD = 1 << 9; private const int VERTEX_STRIDE = sizeof(float) * 12; + private const int MAX_TEXTURE_SLOTS = 4; - private const float COLOR_MODE = 0.0f; - private const float TEXTURE_MODE = 1.0f; - private const float FILL_CIRCLE_MODE = 2.0f; - private const float FILL_CIRCLE_ARC_MODE = 3.0f; + private const float COLOR_MODE = 0.0f; + private const float TEXTURE_MODE = 1.0f; + private const float FILL_CIRCLE_MODE = 2.0f; + private const float FILL_CIRCLE_ARC_MODE = 3.0f; + private const float BORDER_CIRCLE_MODE = 4.0f; + private const float BORDER_CIRCLE_ARC_MODE = 5.0f; private static readonly ushort[] s_indices; private static readonly Vector2 s_vector2Zero = Vector2.Zero; private static readonly Rectangle? s_nullRectangle = null; - private readonly Device5 _device; private readonly DeviceContext4 _context; private readonly InputLayout _vertexInputLayout; @@ -53,7 +59,6 @@ public sealed partial class Canvas : IDisposable private readonly Shader.Shader _shader; private readonly PixelShader _pixelShader; private readonly VertexShader _vertexShader; - private readonly Texture _whiteTexture; private readonly BlendState _defaultBlendState; private readonly DepthStencilState _defaultDepthStencilState; @@ -70,6 +75,15 @@ public sealed partial class Canvas : IDisposable private Matrix _projectionMatrix, _viewMatrix, _transformMatrix; + private Item* _itemQueue; + private int _itemQueueLength; + private int _itemQueueCount; + + private SpinLock _spinLock = new SpinLock(Debugger.IsAttached); + + private readonly Dictionary _textures = new Dictionary(INITIAL_QUEUE_SIZE); + private readonly Dictionary _textureSlotMap = new Dictionary(MAX_TEXTURE_SLOTS); + /// /// Initializes static members of the class. /// @@ -107,18 +121,15 @@ static Canvas() /// Thrown when a value was unexpectedly null. public Canvas(IGraphicsDevice graphicsDevice) { - _device = graphicsDevice.Device; _context = graphicsDevice.DeviceContext; - _defaultBlendState = graphicsDevice.BlendStates.Default; - _defaultSamplerState = graphicsDevice.SamplerStates.LinearWrap; - _defaultDepthStencilState = graphicsDevice.DepthStencilStates.None; - + _defaultBlendState = graphicsDevice.BlendStates.Default; + _defaultSamplerState = graphicsDevice.SamplerStates.LinearWrap; + _defaultDepthStencilState = graphicsDevice.DepthStencilStates.None; + _defaultRasterizerState = graphicsDevice.RasterizerStates.CullBackDepthClipOff; _defaultRasterizerScissorEnabledState = graphicsDevice.RasterizerStates.CullBackDepthClipOffScissorEnabled; - _whiteTexture = graphicsDevice.Textures.White; - _indexBuffer = IndexBuffer.Create(graphicsDevice, s_indices); Assembly assembly = Assembly.GetExecutingAssembly(); @@ -139,8 +150,9 @@ public Canvas(IGraphicsDevice graphicsDevice) _vertexBuffer = VertexBuffer.Create(graphicsDevice, MAX_VERTEX_COUNT); _perFrameBuffer = ConstantBuffer.Create(graphicsDevice); - graphicsDevice.ResizeFinished += GraphicsDeviceOnResizeFinished; + _itemQueue = (Item*)Marshal.AllocHGlobal(sizeof(Item) * (_itemQueueLength = MAX_BATCH_SIZE)); + graphicsDevice.ResizeFinished += GraphicsDeviceOnResizeFinished; Resize(graphicsDevice.Viewport); } @@ -231,7 +243,11 @@ public void End() throw new InvalidOperationException("Begin must be called before End"); } - //PrepareForRendering(); + if (_itemQueueCount > 0) + { + PrepareForRendering(); + FlushBatch(); + } _isBeginCalled = false; } @@ -272,6 +288,113 @@ private void PrepareForRendering() _context.InputAssembler.SetIndexBuffer(_indexBuffer, _indexBuffer.Format, 0); _context.InputAssembler.SetVertexBuffers(0, _vertexBuffer); } + + private void FlushBatch() + { + int offset = 0; + + for (int i = 0; i < _itemQueueCount; i++) + { + ref Item item = ref _itemQueue[i]; + + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (item.V1.M == TEXTURE_MODE) + { + long tp = item.V1.ZW; + if (!_textures.TryGetValue(tp, out Texture texture)) + { + throw new KeyNotFoundException("The looked up texture wasn't found!"); + } + + if (!_textureSlotMap.TryGetValue(tp, out int tSlot)) + { + _context.PixelShader.SetShaderResource(_textureSlotMap.Count, texture.TextureView); + _textureSlotMap.Add(tp, _textureSlotMap.Count); + } + + item.V1.O = tSlot; + item.V2.O = tSlot; + item.V3.O = tSlot; + item.V4.O = tSlot; + + if (_textureSlotMap.Count > MAX_TEXTURE_SLOTS) + { + if (i > offset) + { + DrawBatch(offset, i - offset); + } + + offset = i; + _textureSlotMap.Clear(); + } + } + } + + DrawBatch(offset, _itemQueueCount - offset); + + _itemQueueCount = 0; + _textureSlotMap.Clear(); + } + + private void DrawBatch(int offset, int count) + { + while (count > 0) + { + int batchSize = count; + if (batchSize > MAX_BATCH_SIZE) + { + batchSize = MAX_BATCH_SIZE; + } + + DataBox box = _context.MapSubresource( + _vertexBuffer, 0, MapMode.WriteDiscard, MapFlags.None); + VertexPositionColorTextureMode* vpctPtr = (VertexPositionColorTextureMode*)box.DataPointer; + + for (int i = 0; i < batchSize; i++) + { + ref Item item = ref _itemQueue[i + offset]; + VertexPositionColorTextureMode* v = vpctPtr + (i << 2); + *(v + 0) = item.V1; + *(v + 1) = item.V2; + *(v + 2) = item.V3; + *(v + 3) = item.V4; + } + + _context.UnmapSubresource(_vertexBuffer, 0); + _context.DrawIndexed(6 * batchSize, 0, 0); + + offset += batchSize; + count -= batchSize; + } + } + + private Item* Reserve(int itemCount) + { + if (_itemQueueCount >= _itemQueueLength) + { + bool lockTaken = false; + try + { + _spinLock.Enter(ref lockTaken); + int size = _itemQueueLength * 2; + + Item* ptr = (Item*)Marshal.AllocHGlobal(sizeof(Item) * size); + Marshal.FreeHGlobal(new IntPtr(_itemQueue)); + + _itemQueue = ptr; + _itemQueueLength = size; + } + finally + { + if (lockTaken) + { + _spinLock.Exit(false); + } + } + } + + return _itemQueue + (Interlocked.Add(ref _itemQueueCount, itemCount) - itemCount); + } #region IDisposable Support @@ -315,6 +438,8 @@ private void Dispose(bool disposing) _vertexInputLayout.Dispose(); } + Marshal.FreeHGlobal(new IntPtr(_itemQueue)); + _disposed = true; } } diff --git a/src/Exomia.Framework/Graphics/RasterizerStates.cs b/src/Exomia.Framework/Graphics/RasterizerStates.cs index 1e484eca..ad6899fc 100644 --- a/src/Exomia.Framework/Graphics/RasterizerStates.cs +++ b/src/Exomia.Framework/Graphics/RasterizerStates.cs @@ -59,7 +59,12 @@ public sealed class RasterizerStates : IDisposable /// . /// public readonly RasterizerState CullBackDepthClipOffScissorEnabled; - + + /// + /// Built-in rasterizer state object with settings and multi sample enabled. + /// + public readonly RasterizerState CullBackDepthClipOffMultiSampleOn; + /// /// Initializes a new instance of the class. /// @@ -67,18 +72,24 @@ public sealed class RasterizerStates : IDisposable internal RasterizerStates(IGraphicsDevice graphicsDevice) { WireFrame = Create( - graphicsDevice.Device, nameof(WireFrame), FillMode.Wireframe, CullMode.Back, true, false); + graphicsDevice.Device, nameof(WireFrame), FillMode.Wireframe, CullMode.Back, true, false, false); WireFrameCullNone = Create( - graphicsDevice.Device, nameof(WireFrameCullNone), FillMode.Wireframe, CullMode.None, true, false); - CullFront = Create(graphicsDevice.Device, nameof(CullFront), FillMode.Solid, CullMode.Front, true, false); - CullBack = Create(graphicsDevice.Device, nameof(CullBack), FillMode.Solid, CullMode.Back, true, false); - CullNone = Create(graphicsDevice.Device, nameof(CullNone), FillMode.Solid, CullMode.None, true, false); + graphicsDevice.Device, nameof(WireFrameCullNone), FillMode.Wireframe, CullMode.None, true, false, + false); + CullFront = Create( + graphicsDevice.Device, nameof(CullFront), FillMode.Solid, CullMode.Front, true, false, false); + CullBack = Create( + graphicsDevice.Device, nameof(CullBack), FillMode.Solid, CullMode.Back, true, false, false); + CullNone = Create( + graphicsDevice.Device, nameof(CullNone), FillMode.Solid, CullMode.None, true, false, false); CullBackDepthClipOff = Create( - graphicsDevice.Device, nameof(CullBack), FillMode.Solid, CullMode.Back, false, false); + graphicsDevice.Device, nameof(CullBack), FillMode.Solid, CullMode.Back, false, false, false); CullBackScissorEnabled = Create( - graphicsDevice.Device, nameof(CullBack), FillMode.Solid, CullMode.Back, true, true); + graphicsDevice.Device, nameof(CullBack), FillMode.Solid, CullMode.Back, true, true, false); CullBackDepthClipOffScissorEnabled = Create( - graphicsDevice.Device, nameof(CullBack), FillMode.Solid, CullMode.Back, true, true); + graphicsDevice.Device, nameof(CullBack), FillMode.Solid, CullMode.Back, true, true, false); + CullBackDepthClipOffMultiSampleOn = Create( + graphicsDevice.Device, nameof(CullBack), FillMode.Solid, CullMode.Back, false, false, true); } private static RasterizerState Create(Device5 device, @@ -86,7 +97,8 @@ private static RasterizerState Create(Device5 device, FillMode fillMode, CullMode cullMode, bool depthClipEnabled, - bool scissorEnabled) + bool scissorEnabled, + bool multiSampleEnabled) { return new RasterizerState( device, @@ -100,8 +112,8 @@ private static RasterizerState Create(Device5 device, SlopeScaledDepthBias = 0, IsDepthClipEnabled = depthClipEnabled, IsScissorEnabled = scissorEnabled, - IsMultisampleEnabled = false, - IsAntialiasedLineEnabled = false + IsMultisampleEnabled = multiSampleEnabled, + IsAntialiasedLineEnabled = multiSampleEnabled }) { DebugName = name }; } @@ -123,6 +135,7 @@ private void Dispose(bool disposing) CullBackDepthClipOff.Dispose(); CullBackScissorEnabled.Dispose(); CullBackDepthClipOffScissorEnabled.Dispose(); + CullBackDepthClipOffMultiSampleOn.Dispose(); } _disposed = true; diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.Line.cs b/src/Exomia.Framework/Graphics/SpriteBatch.Line.cs index debce03c..57311d6e 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.Line.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.Line.cs @@ -100,7 +100,7 @@ public void DrawLine(in Line2 line, _whiteTexture, new RectangleF( line.X1, line.Y1, (float)Math.Sqrt((dx * dx) + (dy * dy)) * lengthFactor, lineWidth), false, s_nullRectangle, color, (float)Math.Atan2(dy, dx), - s_vector2Zero, opacity, SpriteEffects.None, layerDepth); + s_vector2Zero, opacity, TextureEffects.None, layerDepth); } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.Rectangle.cs b/src/Exomia.Framework/Graphics/SpriteBatch.Rectangle.cs index d177c1e6..f3c6a70e 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.Rectangle.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.Rectangle.cs @@ -111,7 +111,7 @@ public void DrawFillRectangle(in RectangleF destinationRectangle, in Color color { DrawSprite( _whiteTexture, destinationRectangle, false, s_nullRectangle, - color, 0.0f, s_vector2Zero, 1.0f, SpriteEffects.None, layerDepth); + color, 0.0f, s_vector2Zero, 1.0f, TextureEffects.None, layerDepth); } /// @@ -129,7 +129,7 @@ public void DrawFillRectangle(in RectangleF destinationRectangle, { DrawSprite( _whiteTexture, destinationRectangle, false, s_nullRectangle, - color, 0.0f, s_vector2Zero, opacity, SpriteEffects.None, layerDepth); + color, 0.0f, s_vector2Zero, opacity, TextureEffects.None, layerDepth); } /// @@ -151,7 +151,7 @@ public void DrawFillRectangle(in RectangleF destinationRectangle, { DrawSprite( _whiteTexture, destinationRectangle, false, s_nullRectangle, - color, rotation, origin, opacity, SpriteEffects.None, layerDepth); + color, rotation, origin, opacity, TextureEffects.None, layerDepth); } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.SpriteFont.cs b/src/Exomia.Framework/Graphics/SpriteBatch.SpriteFont.cs index e14e9ffc..a15fa802 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.SpriteFont.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.SpriteFont.cs @@ -29,7 +29,7 @@ public void DrawText(SpriteFont font, string text, in Vector2 position, in Color { font.Draw( DrawTextInternal, text, position, - color, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); + color, 0f, Vector2.Zero, 1.0f, TextureEffects.None, layerDepth); } /// @@ -51,7 +51,7 @@ public void DrawText(SpriteFont font, { font.Draw( DrawTextInternal, text, position, - color, rotation, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); + color, rotation, Vector2.Zero, 1.0f, TextureEffects.None, layerDepth); } /// @@ -67,15 +67,15 @@ public void DrawText(SpriteFont font, /// The effects. /// The depth of the layer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - string text, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) + public void DrawText(SpriteFont font, + string text, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) { font.Draw( DrawTextInternal, text, position, @@ -97,17 +97,17 @@ public void DrawText(SpriteFont font, /// The effects. /// The depth of the layer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - string text, - int start, - int end, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) + public void DrawText(SpriteFont font, + string text, + int start, + int end, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) { font.Draw( DrawTextInternal, text, start, end, position, @@ -130,18 +130,18 @@ public void DrawText(SpriteFont font, /// The effects. /// The depth of the layer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - string text, - int start, - int end, - in Vector2 position, - in Size2F dimension, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) + public void DrawText(SpriteFont font, + string text, + int start, + int end, + in Vector2 position, + in Size2F dimension, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) { font.Draw( DrawTextInternal, text, start, end, position, dimension, @@ -161,7 +161,7 @@ public void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, i { font.Draw( DrawTextInternal, text, position, - color, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); + color, 0f, Vector2.Zero, 1.0f, TextureEffects.None, layerDepth); } /// @@ -183,7 +183,7 @@ public void DrawText(SpriteFont font, { font.Draw( DrawTextInternal, text, position, - color, rotation, Vector2.Zero, 1.0f, SpriteEffects.None, layerDepth); + color, rotation, Vector2.Zero, 1.0f, TextureEffects.None, layerDepth); } /// @@ -199,15 +199,15 @@ public void DrawText(SpriteFont font, /// The effects. /// The depth of the layer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - StringBuilder text, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) + public void DrawText(SpriteFont font, + StringBuilder text, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) { font.Draw( DrawTextInternal, text, position, @@ -229,17 +229,17 @@ public void DrawText(SpriteFont font, /// The effects. /// The depth of the layer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - StringBuilder text, - int start, - int end, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) + public void DrawText(SpriteFont font, + StringBuilder text, + int start, + int end, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) { font.Draw( DrawTextInternal, text, start, end, position, @@ -262,18 +262,18 @@ public void DrawText(SpriteFont font, /// The effects. /// The depth of the layer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - StringBuilder text, - int start, - int end, - in Vector2 position, - in Size2F dimension, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) + public void DrawText(SpriteFont font, + StringBuilder text, + int start, + int end, + in Vector2 position, + in Size2F dimension, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) { font.Draw( DrawTextInternal, text, start, end, position, dimension, @@ -294,16 +294,16 @@ public void DrawText(SpriteFont font, /// The effects. /// The depth of the layer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal void DrawTextInternal(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float scale, - float opacity, - SpriteEffects effects, - float layerDepth) + internal void DrawTextInternal(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float scale, + float opacity, + TextureEffects effects, + float layerDepth) { DrawSprite( texture, new RectangleF(position.X, position.Y, scale, scale), true, sourceRectangle, diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.Structs.cs b/src/Exomia.Framework/Graphics/SpriteBatch.Structs.cs index 8a46ea7d..43f4c94a 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.Structs.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.Structs.cs @@ -18,14 +18,14 @@ public sealed partial class SpriteBatch { internal struct SpriteInfo { - public RectangleF Source; - public RectangleF Destination; - public Vector2 Origin; - public float Rotation; - public float Depth; - public SpriteEffects SpriteEffects; - public Color Color; - public float Opacity; + public RectangleF Source; + public RectangleF Destination; + public Vector2 Origin; + public float Rotation; + public float Depth; + public TextureEffects SpriteEffects; + public Color Color; + public float Opacity; } internal readonly struct TextureInfo diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.Texture.cs b/src/Exomia.Framework/Graphics/SpriteBatch.Texture.cs index af6b759a..dcb506a7 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.Texture.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.Texture.cs @@ -28,7 +28,7 @@ public void Draw(Texture texture, in Vector2 position, in Color color) { DrawSprite( texture, new RectangleF(position.X, position.Y, 1f, 1f), true, s_nullRectangle, - color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); + color, 0f, s_vector2Zero, 1.0f, TextureEffects.None, 0f); } /// @@ -42,7 +42,7 @@ public void Draw(Texture texture, in RectangleF destinationRectangle, in Color c { DrawSprite( texture, destinationRectangle, false, s_nullRectangle, - color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); + color, 0f, s_vector2Zero, 1.0f, TextureEffects.None, 0f); } /// @@ -57,7 +57,7 @@ public void Draw(Texture texture, in Vector2 position, in Rectangle? sourceRecta { DrawSprite( texture, new RectangleF(position.X, position.Y, 1f, 1f), true, sourceRectangle, - color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); + color, 0f, s_vector2Zero, 1.0f, TextureEffects.None, 0f); } /// @@ -75,7 +75,7 @@ public void Draw(Texture texture, { DrawSprite( texture, destinationRectangle, false, sourceRectangle, - color, 0f, s_vector2Zero, 1.0f, SpriteEffects.None, 0f); + color, 0f, s_vector2Zero, 1.0f, TextureEffects.None, 0f); } /// @@ -97,7 +97,7 @@ public void Draw(Texture texture, { DrawSprite( texture, new RectangleF(position.X, position.Y, 1f, 1f), true, s_nullRectangle, - color, rotation, origin, 1.0f, SpriteEffects.None, layerDepth); + color, rotation, origin, 1.0f, TextureEffects.None, layerDepth); } /// @@ -119,7 +119,7 @@ public void Draw(Texture texture, { DrawSprite( texture, destinationRectangle, false, s_nullRectangle, - color, rotation, origin, 1.0f, SpriteEffects.None, layerDepth); + color, rotation, origin, 1.0f, TextureEffects.None, layerDepth); } /// @@ -135,15 +135,15 @@ public void Draw(Texture texture, /// The effects. /// The depth of the layer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Draw(Texture texture, - in RectangleF destinationRectangle, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) + public void Draw(Texture texture, + in RectangleF destinationRectangle, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) { DrawSprite( texture, destinationRectangle, false, sourceRectangle, @@ -164,16 +164,16 @@ public void Draw(Texture texture, /// The effects. /// The depth of the layer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Draw(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float scale, - float opacity, - SpriteEffects effects, - float layerDepth) + public void Draw(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float scale, + float opacity, + TextureEffects effects, + float layerDepth) { DrawSprite( texture, new RectangleF(position.X, position.Y, scale, scale), true, sourceRectangle, @@ -194,32 +194,32 @@ public void Draw(Texture texture, /// The effects. /// The depth of the layer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Draw(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - in Vector2 scale, - float opacity, - SpriteEffects effects, - float layerDepth) + public void Draw(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + in Vector2 scale, + float opacity, + TextureEffects effects, + float layerDepth) { DrawSprite( texture, new RectangleF(position.X, position.Y, scale.X, scale.Y), true, sourceRectangle, color, rotation, origin, opacity, effects, layerDepth); } - private unsafe void DrawSprite(Texture texture, - in RectangleF destination, - bool scaleDestination, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float depth) + private unsafe void DrawSprite(Texture texture, + in RectangleF destination, + bool scaleDestination, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float depth) { if (!_isBeginCalled) { diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.cs b/src/Exomia.Framework/Graphics/SpriteBatch.cs index 0c7bc920..35fa7e99 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.cs @@ -230,6 +230,7 @@ public void End() { throw new InvalidOperationException("Begin must be called before End"); } + if (_spriteQueueCount > 0) { PrepareForRendering(); diff --git a/src/Exomia.Framework/Graphics/SpriteFont.cs b/src/Exomia.Framework/Graphics/SpriteFont.cs index e95ff29c..033463b0 100644 --- a/src/Exomia.Framework/Graphics/SpriteFont.cs +++ b/src/Exomia.Framework/Graphics/SpriteFont.cs @@ -193,16 +193,16 @@ public SpriteFont() /// The opacity. /// The effects. /// Depth of the layer. - internal delegate void DrawFont(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float scale, - float opacity, - SpriteEffects effects, - float layerDepth); + internal delegate void DrawFont(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float scale, + float opacity, + TextureEffects effects, + float layerDepth); /// /// A glyph. @@ -443,15 +443,15 @@ public int HitTest(string text, int start, int end, float xPos, float yPos) /// The opacity. /// The effects. /// Depth of the layer. - internal void Draw(DrawFont drawCallback, - string text, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) + internal void Draw(DrawFont drawCallback, + string text, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) { float x = 0; float y = 0; @@ -524,17 +524,17 @@ internal void Draw(DrawFont drawCallback, /// The opacity. /// The effects. /// Depth of the layer. - internal void Draw(DrawFont drawCallback, - string text, - int start, - int end, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) + internal void Draw(DrawFont drawCallback, + string text, + int start, + int end, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) { if (end <= start || end > text.Length) { end = text.Length; } @@ -609,18 +609,18 @@ internal void Draw(DrawFont drawCallback, /// The opacity. /// The effects. /// Depth of the layer. - internal void Draw(DrawFont drawCallback, - string text, - int start, - int end, - in Vector2 position, - in Size2F dimension, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) + internal void Draw(DrawFont drawCallback, + string text, + int start, + int end, + in Vector2 position, + in Size2F dimension, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) { if (end <= start || end > text.Length) { end = text.Length; } @@ -870,15 +870,15 @@ public int HitTest(StringBuilder text, int start, int end, float xPos, float yPo /// The opacity. /// The effects. /// Depth of the layer. - internal void Draw(DrawFont drawCallback, - StringBuilder text, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) + internal void Draw(DrawFont drawCallback, + StringBuilder text, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) { float x = 0; float y = 0; @@ -950,17 +950,17 @@ internal void Draw(DrawFont drawCallback, /// The opacity. /// The effects. /// Depth of the layer. - internal void Draw(DrawFont drawCallback, - StringBuilder text, - int start, - int end, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) + internal void Draw(DrawFont drawCallback, + StringBuilder text, + int start, + int end, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) { if (end <= start || end > text.Length) { end = text.Length; } @@ -1035,18 +1035,18 @@ internal void Draw(DrawFont drawCallback, /// The opacity. /// The effects. /// Depth of the layer. - internal void Draw(DrawFont drawCallback, - StringBuilder text, - int start, - int end, - in Vector2 position, - in Size2F dimension, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - SpriteEffects effects, - float layerDepth) + internal void Draw(DrawFont drawCallback, + StringBuilder text, + int start, + int end, + in Vector2 position, + in Size2F dimension, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) { if (end <= start || end > text.Length) { end = text.Length; } diff --git a/src/Exomia.Framework/Graphics/SpriteEffects.cs b/src/Exomia.Framework/Graphics/TextureEffects.cs similarity index 91% rename from src/Exomia.Framework/Graphics/SpriteEffects.cs rename to src/Exomia.Framework/Graphics/TextureEffects.cs index f0c735df..5f6759e5 100644 --- a/src/Exomia.Framework/Graphics/SpriteEffects.cs +++ b/src/Exomia.Framework/Graphics/TextureEffects.cs @@ -13,10 +13,10 @@ namespace Exomia.Framework.Graphics { /// - /// Bitfield of flags for specifying SpriteEffects. + /// Bitfield of flags for specifying TextureEffects. /// [Flags] - public enum SpriteEffects + public enum TextureEffects { /// /// A binary constant representing the none flag. diff --git a/src/Exomia.Framework/Resources/shaders/canvas.ehlsl b/src/Exomia.Framework/Resources/shaders/canvas.ehlsl index 706f344f..d29f4029 100644 --- a/src/Exomia.Framework/Resources/shaders/canvas.ehlsl +++ b/src/Exomia.Framework/Resources/shaders/canvas.ehlsl @@ -5,7 +5,11 @@ * ps PSMain ps_5_0 OptimizationLevel3 */ -Texture2D g_Texture : register(t0); +Texture2D g_Texture1 : register(t0); +Texture2D g_Texture2 : register(t1); +Texture2D g_Texture3 : register(t2); +Texture2D g_Texture4 : register(t3); +Texture2D g_Textures[4] : register(t4); SamplerState g_Sampler : register(s0); cbuffer PerFrame : register(b0) @@ -41,24 +45,35 @@ PS_INPUT VSMain(VS_INPUT input) return output; } -#define COLOR_MODE 0.0f -#define TEXTURE_MODE 1.0f -#define FILL_CIRCLE_MODE 2.0f -#define FILL_CIRCLE_ARC_MODE 3.0f +#define COLOR_MODE 0.0f +#define TEXTURE_MODE 1.0f +#define FILL_CIRCLE_MODE 2.0f +#define FILL_CIRCLE_ARC_MODE 3.0f +#define BORDER_CIRCLE_MODE 4.0f +#define BORDER_CIRCLE_ARC_MODE 5.0f #define PI 3.141593f float4 PSMain(PS_INPUT input) : SV_TARGET { - //discard; - //clip(-1); switch (input.mo.x) { default: case COLOR_MODE: return input.c; case TEXTURE_MODE: - return g_Texture.Sample(g_Sampler, input.uv) * input.c; + { + switch (input.mo.y) + { + case 0.0f: + return g_Texture1.Sample(g_Sampler, input.uv) * input.c; + case 1.0f: + return g_Texture2.Sample(g_Sampler, input.uv) * input.c; + case 2.0f: + return g_Texture3.Sample(g_Sampler, input.uv) * input.c; + } + return g_Texture4.Sample(g_Sampler, input.uv) * input.c; + } case FILL_CIRCLE_MODE: { float2 p = input.p; @@ -78,23 +93,71 @@ float4 PSMain(PS_INPUT input) : SV_TARGET float2 p = input.p; float2 center = input.zw; float radius = input.mo.y; - float start = input.uv.x; - float end = input.uv.y; float2 d = center - p; float ls = (d.x * d.x) + (d.y * d.y); - if (ls > radius * radius) + if (ls < radius * radius) + { + float start = input.uv.x; + float end = input.uv.y; + + float anglePositive = atan2(d.y, d.x) + PI; + float angleNegative = atan2(d.y, d.x) - PI; + + if (anglePositive >= start && anglePositive <= end || + angleNegative >= start && angleNegative <= end) + { + return input.c; + } + } + discard; + return float4(0, 0, 0, 0); + } + case BORDER_CIRCLE_MODE: + { + float2 p = input.p; + float2 center = input.zw; + + float2 d = center - p; + float ls = (d.x * d.x) + (d.y * d.y); + + float r = float(((uint)input.mo.y >> 16) / 10.0f); + float l = float(((uint)input.mo.y & 0xffff) / 10.0f); + + if (ls > r * r || ls < l * l) discard; + + return input.c; + } + case BORDER_CIRCLE_ARC_MODE: + { + float2 p = input.p; + float2 center = input.zw; + + float2 d = center - p; + float ls = (d.x * d.x) + (d.y * d.y); + + float r = float(((uint) input.mo.y >> 16) / 10.0f); + float l = float(((uint) input.mo.y & 0xffff) / 10.0f); + + if (ls < r * r && ls > l * l) + { + float start = input.uv.x; + float end = input.uv.y; + + float anglePositive = atan2(d.y, d.x) + PI; + float angleNegative = atan2(d.y, d.x) - PI; - float angle = PI + atan2(d.y, d.x); + if (anglePositive >= start && anglePositive <= end || + angleNegative >= start && angleNegative <= end) + { + return input.c; + } + } - if (angle >= start && angle <= end) - return input.c; discard; - return float4(0,0,0,0); + return float4(0, 0, 0, 0); } } -} - - +} \ No newline at end of file diff --git a/src/Exomia.Framework/Win32/Mem.cs b/src/Exomia.Framework/Win32/Mem.cs index 504fc4bd..f99dc960 100644 --- a/src/Exomia.Framework/Win32/Mem.cs +++ b/src/Exomia.Framework/Win32/Mem.cs @@ -47,5 +47,23 @@ public static extern void Cpy(void* dest, public static extern void Move(void* dest, void* src, int count); + + /// + /// memset call + /// Sets the first num bytes of the block of memory pointed by ptr to the specified value + /// (interpreted as an unsigned char). + /// + /// [in,out] destination addr. + /// value to be set. + /// count of bytes. + /// + /// Null if it fails, else a void*. + /// + [SuppressUnmanagedCodeSecurity] + [DllImport( + "msvcrt.dll", EntryPoint = "memset", CallingConvention = CallingConvention.Cdecl, SetLastError = false)] + public static extern void* Set(void* dest, + int value, + int count); } } \ No newline at end of file From d7d6a1a7038f4a8b76ff7c72ea4d9804fbdc54ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=A4tz?= Date: Sat, 21 Nov 2020 02:02:35 +0100 Subject: [PATCH 33/44] wip --- src/Exomia.Framework/Resources/shaders/canvas.ehlsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Exomia.Framework/Resources/shaders/canvas.ehlsl b/src/Exomia.Framework/Resources/shaders/canvas.ehlsl index d29f4029..801e3f41 100644 --- a/src/Exomia.Framework/Resources/shaders/canvas.ehlsl +++ b/src/Exomia.Framework/Resources/shaders/canvas.ehlsl @@ -9,7 +9,7 @@ Texture2D g_Texture1 : register(t0); Texture2D g_Texture2 : register(t1); Texture2D g_Texture3 : register(t2); Texture2D g_Texture4 : register(t3); -Texture2D g_Textures[4] : register(t4); + SamplerState g_Sampler : register(s0); cbuffer PerFrame : register(b0) From 6d082153bcb695fc4ca5705ffdd8f820ca191bd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=A4tz?= Date: Sat, 21 Nov 2020 02:05:15 +0100 Subject: [PATCH 34/44] wip --- .../{Canvas.VertexPositionColorTexture.cs => Canvas.Structs.cs} | 0 src/Exomia.Framework/Graphics/Canvas.Texture.cs | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/Exomia.Framework/Graphics/{Canvas.VertexPositionColorTexture.cs => Canvas.Structs.cs} (100%) diff --git a/src/Exomia.Framework/Graphics/Canvas.VertexPositionColorTexture.cs b/src/Exomia.Framework/Graphics/Canvas.Structs.cs similarity index 100% rename from src/Exomia.Framework/Graphics/Canvas.VertexPositionColorTexture.cs rename to src/Exomia.Framework/Graphics/Canvas.Structs.cs diff --git a/src/Exomia.Framework/Graphics/Canvas.Texture.cs b/src/Exomia.Framework/Graphics/Canvas.Texture.cs index e9259965..da26acb9 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Texture.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Texture.cs @@ -246,7 +246,7 @@ private void DrawTexture(Texture texture, vertex->B = scaledColor.B; vertex->A = scaledColor.A; - corner = s_rectangleCornerOffsets[j ^ 0]; + corner = s_rectangleCornerOffsets[j ^ (int)effects]; vertex->U = (s.X + (corner.X * s.Width)) * deltaX; vertex->V = (s.Y + (corner.Y * s.Height)) * deltaY; From e7b5d1fa67e27ceacbcf942db7e443d47a24b15f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=A4tz?= Date: Sat, 21 Nov 2020 02:39:01 +0100 Subject: [PATCH 35/44] wip --- .../Content/logo1.jpg | Bin 0 -> 14257 bytes .../Content/logo2.png | Bin 0 -> 3914 bytes .../Exomia.Framework.Example.Canvas.csproj | 11 +++++-- .../Exomia.Framework.Example.Canvas/MyGame.cs | 11 +++++-- .../Graphics/Canvas.Texture.cs | 28 +++++------------- src/Exomia.Framework/Graphics/Canvas.cs | 8 ++--- 6 files changed, 29 insertions(+), 29 deletions(-) create mode 100644 examples/Exomia.Framework.Example.Canvas/Content/logo1.jpg create mode 100644 examples/Exomia.Framework.Example.Canvas/Content/logo2.png diff --git a/examples/Exomia.Framework.Example.Canvas/Content/logo1.jpg b/examples/Exomia.Framework.Example.Canvas/Content/logo1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..45dde99b5f9ad368a48e79eb6c089bdb19119551 GIT binary patch literal 14257 zcmeHtdpuNY-}e%lBqoR05u=dW#Z*q^G?hw{J(WrkQ%PuI5;7PwqEN!Fc9iZ+Ckdf) zDr8IsyKRe{CL`vcT{&e@AG;7diV0N=33WU>sr_E{JVbN zOYvGEfaY)8;=Tn^Qc{Apf#y4u~ZOtUI!V z;9}xLb)bfx2n~!pWI_!+9v0z1bzbsya0k$y>BcWH`T9sC*?Gx6&mAVNl#_ubwpO-Q ztCoPbPaZkyuxrzn-`@pS&P#ruWOQ`2RkXDgSFTu@izzl=D^<^ z_?rWNbKq|d{Qt*+zp|acFp%OzgIq>22Cdu?Oo^mK1XE6!SX-@v)^2q7R56EUj`>|i z7kV?H$0|b!YF9^*jdX=*))9ACSJIAM#4YaIH-khAf@bYL9uOL#vI>Gi!y-@aa@%OK zZ@-TTMg+})=0kdr736RzAmW6l*OuL1$NZNkNe=`@f}l>znX&%mBmcfr{Rqf}AV_Hr zc*G^(#K}m|2Du-!Jv#ElO#3I$)(r?gbOf~TgZ9dkV1l6CHPe6iTl>RIJLp?mHq$=2 zdzUMqZ9Zt51pQO{@ISQ!f=`BmX8`4pS?KX7Fo&fsuisGy z=UGROLeQst2-4UOK|1XaG}reV&%nKz`_LUO1nrIkqH2YpYdH|K6g-bTpy&fU0y+GD z>zEnjzcs+j%ZhqPYYvnJWhpCZL9?`!l(m!;90&)LNA=s-GepcBO0$$zRA*!6sLfRe z4^+&DW+^Ev&r(rVRaH>|cjLi*NJUFkd-3WGvvqbJ!Ym2bU32>4tvRL}AF&tgdIg(V zA3m9=HdjyoyM+ekOD&cy|K7&d&VKDW2iHxTx43O}-{!S@&t7l9@PH$MM}vYxjzvU9 zorM#*4QevDHkicfkt|pL{h}&&)<>E}kLnD`o$8 zgeCqzQT8Wcf6>K*<|!)y;VElD1PDc!K{sb5%!R;@CP9Sd;AhD!V7K#hbJ`DLMv9XX zEM*&*E1+{uhX#rIBYF;)WSZ^Gp&u(6(c)sV!%saDhxqgd+kD(VF5UdH>p;!-KVsjK zMENp(mSkK3C1%q0ioHj<3P@#^JUfgQa}zm=e5hM1udcHXR^En$3L{n@tY#(K5cL(% zQH0nK{$;tm;AR!4L4;pOE&9RtbvZxLKmI|)FVH>)yOK~-8CWVxR%RVm_ub^#0EFvEbV6TOFmRyAO8)6G)5t)an$?M|O6Zp2! z$>~y=wkfLq1<*3;CT7ZXg3!5lO6XjFY^K>Nq% zTHIjdQSS(xZu#%6>@F_RHT)6#kRiCifWy7d(pS?$(jsFw! zg)tBLsNwC3xQSgk_IUxFp-zj7s0GOdg5m&9hY_mPUh8>(q|QiuL?`5&pzWN?if-Ft zg8M=2(7kVx{9T}b$Q3I}X~d>5Rb7m!EuywY=0Yk%INm@?sl#>Ayaq`INdC^GZS79$ zZieizZTxuW{=l0xcf*^`YcKoJJv=(x%r5K4wkW4nKP$=HkQ5G~d|YNkk^bOEHLU0Q z6XgG32~tUA`I!fet;8o1LorRH3fzUrg|}-GdwA;i?^Zq&+rGtWygPf#-}OEQ6Y3|SD)g5MNTb#oz9V!yZ8OnXyH1Fm+pF%o zmg*H%L7^&)za!l;!ds$>YBWEr*%!t3 zTTKr@X#Iyjt?++TXm1c){gjJ~{2vNvMrzE=n+oVmRb$;I9`*w37=B@}wOf>GMY;aY z7nC>=xi4mMO?&x@Cs9}|O%ImbB8wD|K5v*czk;MeJ$4W~<|~M!g z1)dmT>GRCwYK_ulnZAIf!Mh%6y|vRa?dQ=p)0XJ_!?EdasvL5wiie}^b6!4sFhCk{ zXq8I};-jNiVTyJrtyhI~p&gia7J$pB+8(JRgYC@TCwKYsDRh31U*yl72#2s{Dr&{VG1?B;=OZRrsDwOvzn? zl!=3y{BcMe%oUEOOyYDAZd2Xzu7e%rSj}LA-5TL>_lNDP<`paozkTMsnf3v{H|`pF zcdh%0^VUENEp)LMJLaf>FurJKl?w)TZp&l^5s)SNqwfbl5QLUu%0;`RK|C+5$!FfH z{tcm_s$D022ap`ez}Bz{%efzoTpReRwa)i_5LTn4x|Cz--QaIzB6T93QRg!hmTbMMhH1*GaPzfoGJK?{6D)I>fv6x<)d zskqpGn2vhJO?R13?HC@g(U+*ct&ER&ZZO!l--r6Xo*P{`O*uEw7Z-BtX@`@?T`Gl> z^BqRWl4%#AbBm;#(C7Se&rF$C3aai*LyZuYklR^Hkebtb>P))AtZMbee0H?Ab_jiT zyR8CRG<>md=@XvFSHoKPp5wf|Z`kKv9)-|AIkzeVrxTfITaO*p{L5ei^jXyde&*WN;};^whSTP!U-P;)6ngGo&L&>0B^w|Dw*K=hNg>J`l2Fd4++q9)H=TBNw3XbJmsRaR|&WwGR=Gifa3lSbV%y|4+ z32O=Gak{|8>LM|N_%wnZEl>zXXKB!l5ynn2F`Y&h-PoeBVm~eC3eH(aZOVeZ|a-nQvH_cX9 zkU*%QoaQUn>Cju5YPD)GUO+l+gG*-3busv0S7!*55@q(sLd#oCw^!m#%bYST2ksOM z+n;{UtM@S)5#$x;}PsSNYBjo?WcAMG3i#tgButJ{XK%XPK!&NE3V{c&@`gsDEAPi zXH{j6;SEzxwOg{x{Z<0q5GeBZEI}cwoH%MJ-Siq-1fze}fdWreh=;zwi`fs8iNIvyBI2D=&j88)?Xxqd;oD*cG3_$R^M?gmm zs12NKcqj*(Tx)%EUuyx`p{JN}qGdsG1~Y(S%lWkWWf$-K%RO5$V$4^`F~3SKN*osH1|8iT4+qjyw@ z8EIotq*R~MU5QvuLLBLi!4tm$)fUb*$%xfS*EmtbppVhDZt8 z=UH({y7S3ncs!Y|G#vY^%OL(IYk&V%)qh;%@fyuJV~ci{C1CFogu_huREnHrkFKa; z^X2N15Tl`+AQ;0=*HL8N(Mhany${OLc)(dr+5tJR$dFQGseI}@LvS;e-#D&8@8C6a z6i`~OP8x^qgt!a&Nerz>tXlJ-+kI45-;P=>LPP01YTT(SwquiMO2M%@^{xj|hEME< zR}c3*d~tj|;T!{5hL`CPP)(qGiDBq#<^o0_C5>N+mK6*$HE8Ze{IfDwLOr&(uyZ|f z3-0r}EcK`#aO~(HByD@|EZ%GMh-6y#4renkoL8S+>RYOTIM(ZR(bf zqs2WS6K6E!j(Hm`(_^A@(*>o7Ieyf85SPxy=aF#+vOozdgZ7IZE{x{-QW#0T#4Fty4{ex4B|k=kcG&=I^Jof5vTTSeR1Juyf~Ms|r z)}EE4He|#5wd6smTzPj@*F?W1&H9%9W6Gla!>88c`s1PhF;B4=%zG(FFYmL;OGo!e zw}mj_&3I&GWakjh(8jG(<|tiE?*>_4>-bqhFc$Ns&FY$fsBvt-rfaYgB%|lYIcmX? ztmHZ;)+gI|%AU&W!W7O5KWkA|)BRq z_*n(BEn^3ExJD8w&#lv<|3Xlq8_q03W;x;V5gno1^UQg@RPX1;i#mU#zkAtblkJn0 ze`+_e2ubnpI$Fzh@+jroROhlvhaED?3fjUMapBepaeHPsY!7@faFstf1D(>!-->t%m@==W@Fk&SUaI0Bfe%#4X?8sTui@qR~Hx8TyA$ahDcQ#gjSzr_r zmRAMqH~lO!vt-E@8)V#x$VZ;gK#5<2C>En9z@yGG*7W( zQ{A#xPSzl4snhG0QAEsz$GET$61NdfPRb*ekc~~dZ0#aKH81B6=~Wq|H@^F<&D+$G z*m5C(afvY|mF}XyBEjL!vIW=KEKL{Xq1bYCZcnW@p3Us_sOR0Rsp^nn;H+OHejbek zeOg4wtY2-e_Xln7tiYWo=v1gA4l5w{cAHlF=OtE`ZzEIgAE=rX3fxLQacrsI%+7d;GMEu1&q&My#sg%G?Q5>ogCZNyrq4@*-(;*codQiUOp=H+Z=E&#Aold0MXERl#$2IXSwQ* zhK6gGR@YSLtcauD&Dyk4Y0?%Dh3;g+k$9Ol0X33K{i?(MsmGoWqzH2gfv9$n`H28|*qDjMbo4z(n=02Y; z^y{T&?%2=CQ9#KwL-@V>)t|8!3_)?AjV0&?wFU(wTb(&NzzA*2$kmtXkJ(FiBRQ>2Tz74dvY>IXzMYRo>FEjev{3xsPMHTe zQb~T|kDMO^3*nK$=raVtk2v@wMyC6|Vft6kd-OI1R8d;bP(wTP28_$D9A8q6WQz#8 z2*x+tyYEr)Mjq1AL@NK@*KN@{kI+L}#?F^b6XHRjo_%=D5CJBZ@|xKOx6}vm>U2Iy z%aHT%MdMp?6igIYT|5@HhecKDrrC>hJr&TW9>)ZigI!AU)8EVsbg@qne#0_=AxP~= z#*7cwj{%ifnu#nWjj9e3kmaRg(E>&s36~j5k*9EN9z0(SeFu-XahN_aJ&Vzl_8N2@>%fBM2l#^o6fn zOlgPY_a>iNyCWDuP0eLWA=T{wyrn2_B!}O;?_=l!wyB3$K(%gqh!8mr zr=H=@)cWSTnGqR6rdD23h{5EgmW9fsCpDx$V}e(<^Ylj(yfR1=f8DuYi@SF?;HMrFWUt3#gZy*#8u#Ai-4J_o+|@ck!HSdY=y|`sXR&0?=WfB zZG-F0mUzOJvMPI@mk%FqUzt1Z)G}k^bY>Rwg#%qIb1rQX4T;W5>fbGddQ+`76+FQyP_?UzKZ;5zb^-r zQ8@%9Bxy%C%^k$R%e=HP#&f!v7@KOF_Thm{J-_z}=C^E_!4)vm6TmfD%kP`X&)3;f znWLn#nI&JSUFY+huvn=`yYf{tfMe1VK04!+Pw_SqdVG?m=eXn;Ex>1m=o=>n=$vg?5I zQN}OEAOpFLlN_&eQb4clfU`M9fI}H$sxa|uy}KOLK-kiaG$PDkE1HMCyGUY;9! z85O7=b)K92mVlJ_u=c$9!@3S(HL&MQkJFJ>}AVi+vro9$WDft==A8p?Ax=Z2Gq}4X+EO9LELZAWY%r zmwAh0%($rb@buYx**dKe5sY|2zX#i83G0bNMn#P3L(Eh^h_|m9Y+o;QuDA3%9#vgb zl?uv@l1h2@%1E4&%s+JFTf0YM)8`tY=J^f$^zR>Ad&EVE95q}*G0o9)KDFR7Z9IwI zH7TAC#iW$6JP1wy3PccoQb5RBLv(J^;Qrq_fUc#3#FV%pO6)3;${*4)lk3){vAxMF z`LkT~kS6wZ&is*_)*9QYEA-gTb|^`*mT+?;BM(E$>`tem5g%lQM`0BiNOW|R&Zf2{##+njYFs? z9nHQO!qxXzN5%y;MX8e{Bl0x%boo=u>;v)Pp&12Y9pSsHmXnrVyQ-2z#D+sotz+MC2yPX9wzxI#$~PS1 z-NNGX863h49!OT2j$V(mp!YK#!}1DNz&H;lA-b$3XkeOI$v#sJmj_=7OOfrwvxLeH zGxW8wKFWuyB=37`L4gI(^?dW4FTKruhnr1sjm@(4FZAW+vx%~e6$n9HL;u2jo3k&Z;0-ApbCq1zxH;^dZwAF27i$j-rj^V~P& ztXSRZ=9FaC-4O?)0f0JcBPTuM+*9^;M7d=d$_d_`6X{+=NM;K}dX&K~<}U!lGb+X# zN_jOxdzr3?IKL{n^?gd+6586Q@{8u}k(4x?`sC-Z+?5F9!SIjtuAEXyFiWq}p)#r1 z{m#g8Axl3Pz_WOXOJU^c`~wLLQY6R)Kf8kfb02)8i`p!S6=wno2>wBUf52g1h~J}g zW5n+~i0Z+yxU+-Xm*`ZA`z5& zb>5c2@wr#>sI|%iEWvqTrkfcU2HQqvB*I=$KnrE-nZ}?b$1)D6;WC1WJRQH9XJVs| z%s7!_H@BiK1%1|QsKGPkbwXwv zsNe&WkerjBWd&a!M^;YBw2~XY!Jqe$BuRz*QY|6>fFBh<$V&WJV%qH#QToAncE{UF z&+rOPr2~^gNXa=^)m7oSZ2)_YppoC;2j4CRtacaOV zwa$WiUX>fwUDh!wTPJM8CeX!yuGqw255n&y{%=qwsKTm(%>#+6UbDVJnUlEr^d8n@ z@05v=KcURn{ER5May{=r)>kOA*$YX5KX2Fj3T3jz7Q*uB87R}}gz}UrKwf7)Aiu#9 z6!FU{GMh+A-YUPu?KPH=;R;{3$nSj48cEKaF++$ zWV)XRf6dC(Yo8#f`|PJ?v`Atei;XTmsS>-LxBRI7p;Qd)A)Dhf`?P5JL3lig=BUEd zK`mYc38c;|wuz}2;4Rq;fOVZmH33_WQ5`wBg{U=>NXR6>J4l(U`$t&i7Gr89{Xha! zL|_mffGt2&oY1Z8lVR>B1HWRVY#vzIPUEQ`Ts4iwQJLXp8`d#G`i2n9#nYxhmI}rB>X@QS@`3A(@xC64Y z#Sf0z{Q<jPb{9B@B-^mCxd(KMVQ%GC9JqyLH| z0&>8omTM?;cCm&0*~lq17YiBjQX5+myZ4F+#)493;))qL$c#Xw>4KwEU94q6Vim@} z^GB~r$+-|b`)Mhrhq)m>1nmd7k3K)fcnNYtv`pWRySL4w47ejF7bR)qe*(U6&F_ET zG4Kr?o&wv0&^Zl!UK6yX|LSNVPg zhcO&xGN@MTL?%SlW8Z+3#d~Jc$0;j?+l6CeM8oC!HZ z#L^AOp@~q&y+9*?@q{yiKB9&cUaYw z6z66K3EMQOH07!De^Bss@7T9(4_`n?PP`4qUJB|c#MecVE7wu=8S(Gx#BD-)?-Cgg z&~CzG{glWrA89!0dg?C8J7;234oDo;?s){~n$(E(d+YdvZOPU9E4!nf`KyysN%NL= zpvyxpF0ECX{+c<1PYj~XBzQMdEre%(rq(S4j+5N(T)E$63H=uZq-9I?#ilyA6z6a8 zK2QTM;)V~slKlXmE#}y3R=1^$dF}5Abpgw6wftn6MSO%tS^~YTU1_~m%gP;_%|5?a zw5q|d#ipaWS$F4_ytkL!7oFMqN-5~n;yoLVn#>AT{^A8be-ltx-_bS*{FllExV9f+ zz^@5a{6_U6mg?p~X7a;*)Mg>2{#@SPs-CEyY3o}-{Uu-!ui(yg`T6a-K?>Nu+pf^v1G*GwBlk==OimNS9`gB zii}*~({C1y7x^BAxtw*pfexj?C&iW~RqL^hgmk_pOYjzpm|@PC_RQ$A>N*4qY_DxP zz#~XFLgBeSr!N=dI5qc=FR%keoR(q))8xOVV#Bd^H>1b&_UhJZqn}fAeLPJt_5KS% zHRBpVP(@ncb^2nX*80u>@%J(-=2B)Rj-=Y(tTz?0@xj5Z- z@l!iySno6t4F!m1rb@6&w(d5Pg3blks^OkGk_hpYa-S>B^~_$2&0RL}_KmrVZh*|` zAd=>p!X~N6G(w#MezlvK$0LE_sC7AV_olUJXd}h zogXr=pxgGk2bp3h+a;dIhkv5^Bjj>{!3Im)`^r U7<3-V4KTrc*!)kD!6QFa!Bd=h*B06@^n66wIc<{b>4 zL+oe(44wu6fRg@bmrxhm^ZMR|Yigc2f)`#b@>&p^XDiM|26=i1;6uS)cwhfOL&##w zYY5mMX9#iDvPIYind1HYEu)Ee$7nmWcXWWa9u9KWh|eHWpWWaZKGYK&dF^Uoh<>CY z44gvow2@NoWxY(k=rUW7$tfi)ax1BM^Pz>Uw&5aD)b2LqnCVPz{L+4E2mu4GfVzXz|}3NPLJl(LX5EpAZN> z=;`T22n#iYK;Q?H!2dT3d%5ucua}+tf5-Sh_BM&^{YY3po@GC#TmGh|s1OGW6R?$; zskXYFwzjHNLts zzM523b!Js71uxGr+!+`>6|;(&shRUw7x$9IM+(aZh9&)vH&$be4EuM0*L7=fX`^x7 zxYcOHR7jtN2zKp)u3uS^kvTb~tS?F7?e3WgLhZ$^7bCN4f9Yo}ybU~+JVJOflphp} z79THm>j@Ac@IF_j`e8SbpUF(_TLhS)(>LGLoD=&EF2bNa55kdf`S_rDkczUQEDYXN zWF>lkamNK7tWXzns^@Z@zB5 z^#Ku#I3s>iaRc^-sg#n!Io%xzq@zv9xq1(T>_t8e$jFndmGmgKq#49z1?WuMh!{mUBr>i=C!r1)uO0~jj^vA;p_8yJ4UZbMO%>({d)Z? z`x9U5ef$3zx^tCu=X$PXs1LA6}VhM2Kzv6K2~_e$-q<0D?Z9Af6~YKF?8$> z?Wgyi;Ig6)0|=^GesiFglc&_q*;;V2xsNx>@%~q(TR-uE@YW!8`-&NRar4B4Iu`$8= zlNi+bSQWajjHty3tA|U9~HY_}LI^nz*2E zsQSWaZwoy9%`)#!IcrihAdjCox?R^1E^*41rnlgvpRs92Z{1$Cdg7gx z9_zNHa&`W6c7Z0zdk_{+-gNYku%d4#e2L;-q48C6W^lBD_V;|JOy=G9@WI?mIcZ^Y znM3uqZf4t#7h!;ZdN2NUm%F~VuKj&eeTj6xUl=fyiT#8}h`89Q=8Oj1mA&+kiW69N z?+a<}FVBr=kM0hJfzQ6h=&7%9z7DLv#~(85_QB_?wk~%h$@P3ZrRVXqpAc(AS#h$2 z;FTEqA?MK;C9ooX0!KZ>BS07gww7;Ld!)^6-{b}7cfR%krp>K z*^tNBrKN2P0USruN7Y8`Qy0OAMz_SQ_Aa|TQ8BDx%!vT8rSs-kpDp8@FtM|$e&R(IzaB}Mh;Z=7q-*@4z*8opXCBYrbV`A!ytvO5b1-p?0Qhu#vrFn-z6k(Cn2#(l}y&I9*vbvh8%4_>^_8$zdPf5mB2C zaD%who(@yLXBXB9Mx@xx_~ABt+GB!=H`P46aW?}lo98DkdL?2%&m=dN%#Xpn6RwG~ zipy%rMZ!qJ$H@|`o?+dJt!qnltu2oiaQAi$eK<2NrCG;&$CUBzExD-+IbFHvO;#Z! zKWXiX^81|x8P>(wITd61kKwaT^#@s(?8=*%S2WhwzI3P9eC^7$R`Pl?CArqa5=5TM zR9RRMA2S4{1&KGyi)5{QEj+ySOjw+`l9<^(Yu-s*nb|)1A%D-TbNlb9HnCGgzQ(=J zeT>UDGLS~ti>`h*d97dxns+B>EicuXkL)BaHVc1&UZO5A{{&7IcK5E~k?14Z4zJ@I zz~5I@8MfhV!FC^us9(F$!loA;HLBl^B=p(l{RXLl);|k(DN91)FGzEwWyB23$6H@~ z$F=WKR@~9erG4oS(3vCSwEd6kj1pKUO5_qGJ_8h$)LkgqMLDj-FRE#oDgl4d@@D-n zu$59OhShvH8do!?us`ocP(Fppn9CBUuDK*&%`l0-G)d%^?Xl zs}@y1(^=WLJ5zJpsW{E)1IgZZ4~2`nj@j=g?+l*hQtuN;Nk{&3V%tu5Nriu{VQ0!z z_pZ{-fkT#pZ z4c7Grot$Oqu3V$}ihDDvXe9yy=itq)myIXf*c>kn!z1q-`^7#XEYdq9Bt>8FzrwHkGd?OOq z(du9#d0xru-Z`PYd*gM#%lFYg6qSB<$SeeLHf}E79L3I0T4--qeJ?ffh{f2Q>0kJnf4tN;X6V>uY^q=j_rIfTkW!cNxk8@qF;wjkBYxX!aK1g*8+( zxgMcXTQcr%bkb6*^P1Tf^igrd7L4{e{>X25NdWk7;ye3pRYb?&tH#FGxcj zpN~iO67#qA)1qNykvZ~=lqWpnYO|#7pjoK+CUh7z)sxojR!VpF7czbH=SNTDxWjl8 zDKTwOEA+lJhrx+2o5sCo`gfqi*@ev$BPOw$$??Yi%Q#aTXO*M!iw_2?Q@e;|bS7 zk^a}2&-)v!Ws~_{eKFtDCfOL!9(9hJA3ZA{2(oLE@-U1!HfN)^jK!7hrxIruEjpRK z#c~Ki63-Q{=z_EeFVN5ya7JBIpRv4kD2yX?U!BL2~V8k;_$I@ z`y^;wyka}HE-e9yowK5b0~eoRw(!mQOi-8?exfbI;c9lH50lSft9FaYgCoKBeNH@E8%7J!4xPcX|?sYk*-gfNEQwfjYB3<{2 zm#5MV3a#-<-y5o$$;YVzP-iV=4D@C%MzuAwx0HzCd|JVF4xZmBY`>v$zBP}H-7-6T zU^LiYbheJAV{FZK7`t+Q?Am;Hw8;Sm%FSl$a&6=fTn7u~e?VQ*|ChR*en6eDu{fwo zDI*^!!tJRLc0^GfQ1nq#O0O~NiePRv5Ka4mqCPmsx+0KU&5fqTpsTe}^bht_SShiC z9m|QlPz*5i1=~L)hE`*txt#j8Z2!SFKKa%d4otoc1)5deOL2%g_i4s~YETYk+ZDEN zVhg*Hp!wD(0A)QC2X3STt#6Yg7$>pB2gRV|SkdCIUp3I%>+P!0K=nJ3LWP`+Fx<>= zNIPPhWVMq8a~(b^tsGb&I1k=8qj4$Z9%c$0QdIh@DB@7B%tA<8{Se?Zw$(MSBuildProjectName).$(Platform) $(MSBuildProjectName).$(Platform) - + - + - + + PreserveNewest + + + PreserveNewest + \ No newline at end of file diff --git a/examples/Exomia.Framework.Example.Canvas/MyGame.cs b/examples/Exomia.Framework.Example.Canvas/MyGame.cs index e99e7ec6..bb8c6ac7 100644 --- a/examples/Exomia.Framework.Example.Canvas/MyGame.cs +++ b/examples/Exomia.Framework.Example.Canvas/MyGame.cs @@ -27,7 +27,10 @@ sealed class MyGame : Game.Game private Graphics.Canvas _canvas = null!; - private float k; + private Texture _texture = null!; + private Texture _texture2 = null!; + + private float k; /// /// Initializes a new instance of the class. @@ -79,6 +82,9 @@ protected override void OnLoadContent() /* * TODO: use base.Content to load your game content here */ + + _texture = Content.Load("logo1.jpg"); + _texture2 = Content.Load("logo2.png"); } /// @@ -245,7 +251,8 @@ protected override void Draw(GameTime gameTime) new Arc2(center400, 50f, MathUtil.DegreesToRadians(-200), MathUtil.DegreesToRadians(-80)), Color.Blue, 0.0f, Vector2.Zero, 1.0f); - _canvas.Draw(GraphicsDevice.Textures.White, new RectangleF(1400,50, 200,200), Color.YellowGreen); + _canvas.Draw(_texture, new RectangleF(1100, 50, 200, 200), Color.White); + _canvas.Draw(_texture2, new RectangleF(1350, 50, 200, 200), Color.White); _canvas.End(); diff --git a/src/Exomia.Framework/Graphics/Canvas.Texture.cs b/src/Exomia.Framework/Graphics/Canvas.Texture.cs index da26acb9..3bbef28f 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Texture.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Texture.cs @@ -17,7 +17,7 @@ namespace Exomia.Framework.Graphics public sealed unsafe partial class Canvas { /// - /// Draws. + /// Draws a texture. /// /// The texture. /// The position. @@ -31,7 +31,7 @@ public void Draw(Texture texture, in Vector2 position, in Color color) } /// - /// Draws. + /// Draws a texture. /// /// The texture. /// The destination rectangle. @@ -45,7 +45,7 @@ public void Draw(Texture texture, in RectangleF destinationRectangle, in Color c } /// - /// Draws. + /// Draws a texture. /// /// The texture. /// The position. @@ -60,7 +60,7 @@ public void Draw(Texture texture, in Vector2 position, in Rectangle? sourceRecta } /// - /// Draws. + /// Draws a texture. /// /// The texture. /// The destination rectangle. @@ -78,7 +78,7 @@ public void Draw(Texture texture, } /// - /// Draws. + /// Draws a texture. /// /// The texture. /// The destination rectangle. @@ -104,7 +104,7 @@ public void Draw(Texture texture, } /// - /// Draws. + /// Draws a texture. /// /// The texture. /// The position. @@ -132,7 +132,7 @@ public void Draw(Texture texture, } /// - /// Draws. + /// Draws a texture. /// /// The texture. /// The position. @@ -159,18 +159,6 @@ public void Draw(Texture texture, sourceRectangle, color, rotation, origin, opacity, effects); } - /// - /// Draw sprite. - /// - /// The texture. - /// Destination for the. - /// True to scale destination. - /// The source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. private void DrawTexture(Texture texture, in RectangleF destination, bool scaleDestination, @@ -245,7 +233,7 @@ private void DrawTexture(Texture texture, vertex->G = scaledColor.G; vertex->B = scaledColor.B; vertex->A = scaledColor.A; - + corner = s_rectangleCornerOffsets[j ^ (int)effects]; vertex->U = (s.X + (corner.X * s.Width)) * deltaX; vertex->V = (s.Y + (corner.Y * s.Height)) * deltaY; diff --git a/src/Exomia.Framework/Graphics/Canvas.cs b/src/Exomia.Framework/Graphics/Canvas.cs index b60d2bd7..7d7192ce 100644 --- a/src/Exomia.Framework/Graphics/Canvas.cs +++ b/src/Exomia.Framework/Graphics/Canvas.cs @@ -123,7 +123,7 @@ public Canvas(IGraphicsDevice graphicsDevice) { _context = graphicsDevice.DeviceContext; - _defaultBlendState = graphicsDevice.BlendStates.Default; + _defaultBlendState = graphicsDevice.BlendStates.AlphaBlend; _defaultSamplerState = graphicsDevice.SamplerStates.LinearWrap; _defaultDepthStencilState = graphicsDevice.DepthStencilStates.None; @@ -271,8 +271,8 @@ private void PrepareForRendering() { _context.Rasterizer.State = _rasterizerState ?? _defaultRasterizerScissorEnabledState; _context.Rasterizer.SetScissorRectangle( - _scissorRectangle.Left, _scissorRectangle.Top, _scissorRectangle.Right, - _scissorRectangle.Bottom); + _scissorRectangle.Left, _scissorRectangle.Top, + _scissorRectangle.Right, _scissorRectangle.Bottom); } _context.PixelShader.SetSampler(0, _samplerState ?? _defaultSamplerState); @@ -309,7 +309,7 @@ private void FlushBatch() if (!_textureSlotMap.TryGetValue(tp, out int tSlot)) { _context.PixelShader.SetShaderResource(_textureSlotMap.Count, texture.TextureView); - _textureSlotMap.Add(tp, _textureSlotMap.Count); + _textureSlotMap.Add(tp, tSlot = _textureSlotMap.Count); } item.V1.O = tSlot; From 029e856892368ee1a63fa777773737ddb28f5595 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=A4tz?= Date: Sat, 21 Nov 2020 02:53:39 +0100 Subject: [PATCH 36/44] wip --- .../Graphics/Canvas.SpriteFont.cs | 2 +- .../Graphics/Canvas.Texture.cs | 9 +- src/Exomia.Framework/Graphics/Canvas.cs | 104 ++++++++++++------ .../Resources/shaders/canvas.ehlsl | 42 ++++++- 4 files changed, 114 insertions(+), 43 deletions(-) diff --git a/src/Exomia.Framework/Graphics/Canvas.SpriteFont.cs b/src/Exomia.Framework/Graphics/Canvas.SpriteFont.cs index 5e32b056..3793a460 100644 --- a/src/Exomia.Framework/Graphics/Canvas.SpriteFont.cs +++ b/src/Exomia.Framework/Graphics/Canvas.SpriteFont.cs @@ -250,7 +250,7 @@ internal void DrawTextInternal(Texture texture, { DrawTexture( texture, new RectangleF(position.X, position.Y, scale, scale), true, sourceRectangle, color, - rotation, origin, opacity, effects); + rotation, origin, opacity, effects, FONT_TEXTURE_MODE); } /// diff --git a/src/Exomia.Framework/Graphics/Canvas.Texture.cs b/src/Exomia.Framework/Graphics/Canvas.Texture.cs index 3bbef28f..55564ebe 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Texture.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Texture.cs @@ -159,7 +159,7 @@ public void Draw(Texture texture, sourceRectangle, color, rotation, origin, opacity, effects); } - private void DrawTexture(Texture texture, + private void DrawTexture(Texture texture, in RectangleF destination, bool scaleDestination, in Rectangle? sourceRectangle, @@ -167,7 +167,8 @@ private void DrawTexture(Texture texture, float rotation, in Vector2 origin, float opacity, - TextureEffects effects) + TextureEffects effects, + float mode = TEXTURE_MODE) { long tp = texture.TexturePointer.ToInt64(); @@ -238,7 +239,7 @@ private void DrawTexture(Texture texture, vertex->U = (s.X + (corner.X * s.Width)) * deltaX; vertex->V = (s.Y + (corner.Y * s.Height)) * deltaY; - vertex->M = TEXTURE_MODE; + vertex->M = mode; } } else @@ -267,7 +268,7 @@ private void DrawTexture(Texture texture, vertex->U = (s.X + (corner.X * s.Width)) * deltaX; vertex->V = (s.Y + (corner.Y * s.Height)) * deltaY; - vertex->M = TEXTURE_MODE; + vertex->M = mode; } } } diff --git a/src/Exomia.Framework/Graphics/Canvas.cs b/src/Exomia.Framework/Graphics/Canvas.cs index 7d7192ce..64ea2281 100644 --- a/src/Exomia.Framework/Graphics/Canvas.cs +++ b/src/Exomia.Framework/Graphics/Canvas.cs @@ -35,14 +35,16 @@ public sealed unsafe partial class Canvas : IDisposable private const int MAX_INDEX_COUNT = MAX_BATCH_SIZE * 6; private const int BATCH_SEQUENTIAL_THRESHOLD = 1 << 9; private const int VERTEX_STRIDE = sizeof(float) * 12; - private const int MAX_TEXTURE_SLOTS = 4; + private const int MAX_TEXTURE_SLOTS = 8; + private const int MAX_FONT_TEXTURE_SLOTS = 4; private const float COLOR_MODE = 0.0f; private const float TEXTURE_MODE = 1.0f; - private const float FILL_CIRCLE_MODE = 2.0f; - private const float FILL_CIRCLE_ARC_MODE = 3.0f; - private const float BORDER_CIRCLE_MODE = 4.0f; - private const float BORDER_CIRCLE_ARC_MODE = 5.0f; + private const float FONT_TEXTURE_MODE = 2.0f; + private const float FILL_CIRCLE_MODE = 3.0f; + private const float FILL_CIRCLE_ARC_MODE = 4.0f; + private const float BORDER_CIRCLE_MODE = 5.0f; + private const float BORDER_CIRCLE_ARC_MODE = 6.0f; private static readonly ushort[] s_indices; private static readonly Vector2 s_vector2Zero = Vector2.Zero; @@ -82,7 +84,8 @@ public sealed unsafe partial class Canvas : IDisposable private SpinLock _spinLock = new SpinLock(Debugger.IsAttached); private readonly Dictionary _textures = new Dictionary(INITIAL_QUEUE_SIZE); - private readonly Dictionary _textureSlotMap = new Dictionary(MAX_TEXTURE_SLOTS); + private readonly Dictionary _textureSlotMap = new Dictionary(MAX_TEXTURE_SLOTS); + private readonly Dictionary _fontTextureSlotMap = new Dictionary(MAX_FONT_TEXTURE_SLOTS); /// /// Initializes static members of the class. @@ -297,43 +300,78 @@ private void FlushBatch() { ref Item item = ref _itemQueue[i]; - // ReSharper disable once CompareOfFloatsByEqualityOperator - if (item.V1.M == TEXTURE_MODE) + switch (item.V1.M) { - long tp = item.V1.ZW; - if (!_textures.TryGetValue(tp, out Texture texture)) - { - throw new KeyNotFoundException("The looked up texture wasn't found!"); - } - - if (!_textureSlotMap.TryGetValue(tp, out int tSlot)) - { - _context.PixelShader.SetShaderResource(_textureSlotMap.Count, texture.TextureView); - _textureSlotMap.Add(tp, tSlot = _textureSlotMap.Count); - } - - item.V1.O = tSlot; - item.V2.O = tSlot; - item.V3.O = tSlot; - item.V4.O = tSlot; + case TEXTURE_MODE: + { + long tp = item.V1.ZW; + if (!_textures.TryGetValue(tp, out Texture texture)) + { + throw new KeyNotFoundException("The looked up texture wasn't found!"); + } + + if (!_textureSlotMap.TryGetValue(tp, out int tSlot)) + { + _context.PixelShader.SetShaderResource(_textureSlotMap.Count, texture.TextureView); + _textureSlotMap.Add(tp, tSlot = _textureSlotMap.Count); + } + + item.V1.O = tSlot; + item.V2.O = tSlot; + item.V3.O = tSlot; + item.V4.O = tSlot; - if (_textureSlotMap.Count > MAX_TEXTURE_SLOTS) - { - if (i > offset) + if (_textureSlotMap.Count > MAX_TEXTURE_SLOTS) + { + if (i > offset) + { + DrawBatch(offset, i - offset); + } + + offset = i; + _textureSlotMap.Clear(); + } + break; + } + case FONT_TEXTURE_MODE: { - DrawBatch(offset, i - offset); + long tp = item.V1.ZW; + if (!_textures.TryGetValue(tp, out Texture texture)) + { + throw new KeyNotFoundException("The looked up texture wasn't found!"); + } + + if (!_fontTextureSlotMap.TryGetValue(tp, out int tSlot)) + { + _context.PixelShader.SetShaderResource(MAX_TEXTURE_SLOTS + _fontTextureSlotMap.Count, texture.TextureView); + _fontTextureSlotMap.Add(tp, tSlot = _fontTextureSlotMap.Count); + } + + item.V1.O = tSlot; + item.V2.O = tSlot; + item.V3.O = tSlot; + item.V4.O = tSlot; + + if (_fontTextureSlotMap.Count > MAX_FONT_TEXTURE_SLOTS) + { + if (i > offset) + { + DrawBatch(offset, i - offset); + } + + offset = i; + _fontTextureSlotMap.Clear(); + } + break; } - - offset = i; - _textureSlotMap.Clear(); - } - } + } } DrawBatch(offset, _itemQueueCount - offset); _itemQueueCount = 0; _textureSlotMap.Clear(); + _fontTextureSlotMap.Clear(); } private void DrawBatch(int offset, int count) diff --git a/src/Exomia.Framework/Resources/shaders/canvas.ehlsl b/src/Exomia.Framework/Resources/shaders/canvas.ehlsl index 801e3f41..17bcaeea 100644 --- a/src/Exomia.Framework/Resources/shaders/canvas.ehlsl +++ b/src/Exomia.Framework/Resources/shaders/canvas.ehlsl @@ -9,6 +9,16 @@ Texture2D g_Texture1 : register(t0); Texture2D g_Texture2 : register(t1); Texture2D g_Texture3 : register(t2); Texture2D g_Texture4 : register(t3); +Texture2D g_Texture5 : register(t4); +Texture2D g_Texture6 : register(t5); +Texture2D g_Texture7 : register(t6); +Texture2D g_Texture8 : register(t7); + + +Texture2D g_FontTexture1 : register(t8); +Texture2D g_FontTexture2 : register(t9); +Texture2D g_FontTexture3 : register(t10); +Texture2D g_FontTexture4 : register(t11); SamplerState g_Sampler : register(s0); @@ -47,10 +57,11 @@ PS_INPUT VSMain(VS_INPUT input) #define COLOR_MODE 0.0f #define TEXTURE_MODE 1.0f -#define FILL_CIRCLE_MODE 2.0f -#define FILL_CIRCLE_ARC_MODE 3.0f -#define BORDER_CIRCLE_MODE 4.0f -#define BORDER_CIRCLE_ARC_MODE 5.0f +#define FONT_TEXTURE_MODE 2.0f +#define FILL_CIRCLE_MODE 3.0f +#define FILL_CIRCLE_ARC_MODE 4.0f +#define BORDER_CIRCLE_MODE 5.0f +#define BORDER_CIRCLE_ARC_MODE 6.0f #define PI 3.141593f @@ -71,8 +82,29 @@ float4 PSMain(PS_INPUT input) : SV_TARGET return g_Texture2.Sample(g_Sampler, input.uv) * input.c; case 2.0f: return g_Texture3.Sample(g_Sampler, input.uv) * input.c; + case 3.0f: + return g_Texture4.Sample(g_Sampler, input.uv) * input.c; + case 4.0f: + return g_Texture5.Sample(g_Sampler, input.uv) * input.c; + case 5.0f: + return g_Texture6.Sample(g_Sampler, input.uv) * input.c; + case 6.0f: + return g_Texture7.Sample(g_Sampler, input.uv) * input.c; + } + return g_Texture8.Sample(g_Sampler, input.uv) * input.c; + } + case FONT_TEXTURE_MODE: + { + switch (input.mo.y) + { + case 0.0f: + return g_FontTexture1.Sample(g_Sampler, input.uv) * input.c; + case 1.0f: + return g_FontTexture2.Sample(g_Sampler, input.uv) * input.c; + case 2.0f: + return g_FontTexture3.Sample(g_Sampler, input.uv) * input.c; } - return g_Texture4.Sample(g_Sampler, input.uv) * input.c; + return g_FontTexture4.Sample(g_Sampler, input.uv) * input.c; } case FILL_CIRCLE_MODE: { From 5c8b4bd8c66fd3c86ee3c42a0561421912895ebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=A4tz?= Date: Sat, 21 Nov 2020 12:07:28 +0100 Subject: [PATCH 37/44] wip --- src/Exomia.Framework/Graphics/Canvas.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Exomia.Framework/Graphics/Canvas.cs b/src/Exomia.Framework/Graphics/Canvas.cs index 64ea2281..77589b7b 100644 --- a/src/Exomia.Framework/Graphics/Canvas.cs +++ b/src/Exomia.Framework/Graphics/Canvas.cs @@ -329,7 +329,8 @@ private void FlushBatch() } offset = i; - _textureSlotMap.Clear(); + _textureSlotMap.Clear(); + _fontTextureSlotMap.Clear(); } break; } @@ -360,7 +361,8 @@ private void FlushBatch() } offset = i; - _fontTextureSlotMap.Clear(); + _fontTextureSlotMap.Clear(); + _textureSlotMap.Clear(); } break; } From d7be0b619588f4ebd8994e809fc8b84c156e3b54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=A4tz?= Date: Sun, 22 Nov 2020 18:31:19 +0100 Subject: [PATCH 38/44] v1.5.0-rc.3 - canvas implementation - ref & cleanup --- .../Exomia.Framework.Example.Canvas/MyGame.cs | 42 +++++++------- src/Exomia.Framework/Graphics/Canvas.Arc.cs | 6 +- .../Graphics/Canvas.Polygon.cs | 56 +++++++++++++++++-- .../Graphics/Canvas.Texture.cs | 28 +++++----- .../Graphics/Canvas.Triangle.cs | 10 ++-- src/Exomia.Framework/Graphics/Canvas.cs | 29 +++++----- src/Exomia.Framework/Win32/Mem.cs | 20 +++++++ 7 files changed, 130 insertions(+), 61 deletions(-) diff --git a/examples/Exomia.Framework.Example.Canvas/MyGame.cs b/examples/Exomia.Framework.Example.Canvas/MyGame.cs index bb8c6ac7..49d20082 100644 --- a/examples/Exomia.Framework.Example.Canvas/MyGame.cs +++ b/examples/Exomia.Framework.Example.Canvas/MyGame.cs @@ -29,8 +29,8 @@ sealed class MyGame : Game.Game private Texture _texture = null!; private Texture _texture2 = null!; - - private float k; + + private float k; /// /// Initializes a new instance of the class. @@ -116,7 +116,7 @@ protected override void Draw(GameTime gameTime) _canvas.Begin(rasterizerState: GraphicsDevice.RasterizerStates.CullBackDepthClipOffMultiSampleOn); k += gameTime.DeltaTimeS / 2; - + _canvas.DrawFillTriangle(new Triangle2(100, 50, 150, 100, 50, 100), Color.Red, 0, Vector2.Zero, 1.0f); _canvas.DrawTriangle(new Triangle2(100, 50, 150, 100, 50, 100), Color.Green, 5.0f, 0, Vector2.Zero, 1.0f); @@ -138,31 +138,32 @@ protected override void Draw(GameTime gameTime) _canvas.DrawLine(new Line2(400, 450, 450, 400), Color.Yellow, 5.0f, 1.0f); _canvas.DrawFillPolygon( - new[] - { - new Vector2(400, 300), new Vector2(550, 320), new Vector2(650, 520), new Vector2(520, 450) - }, Color.Red, 1.0f); + new[] { new Vector2(400, 300), new Vector2(550, 320), new Vector2(650, 520), new Vector2(520, 450) }, + Color.Red, 0.0f, Vector2.Zero, 1.0f); + _canvas.DrawPolygon( + new[] { new Vector2(400, 300), new Vector2(550, 320), new Vector2(650, 520), new Vector2(520, 450) }, + Color.Green, 5.0f, 0.0f, Vector2.Zero, 1.0f); + _canvas.DrawFillPolygon( + new[] { new Vector2(400, 300), new Vector2(550, 320), new Vector2(650, 520), new Vector2(520, 450) }, + Color.Yellow, k, new Vector2(400, 300), 1.0f); _canvas.DrawPolygon( - new[] - { - new Vector2(400, 300), new Vector2(550, 320), new Vector2(650, 520), new Vector2(520, 450) - }, Color.Yellow, 15.0f, 1.0f); + new[] { new Vector2(400, 300), new Vector2(550, 320), new Vector2(650, 520), new Vector2(520, 450) }, + Color.Green, 5.0f, k, new Vector2(400, 300), 1.0f); _canvas.DrawFillPolygon( new[] { new Vector2(600, 600), new Vector2(650, 610), new Vector2(650, 720), new Vector2(450, 750), new Vector2(400, 630) - }, Color.Red, 1.0f); + }, Color.Red, 0.0f, Vector2.Zero, 1.0f); _canvas.DrawPolygon( new[] { new Vector2(600, 600), new Vector2(650, 610), new Vector2(650, 720), new Vector2(450, 750), - new Vector2(400, 630) - }, Color.Yellow, 5.0f, 1.0f); + }, Color.Yellow, 5.0f, 0.0f, Vector2.Zero, 1.0f); Vector2 center = new Vector2(800, 400); @@ -197,7 +198,8 @@ protected override void Draw(GameTime gameTime) Vector2 center3 = new Vector2(1200, 500); _canvas.DrawRectangle( new RectangleF(center3.X - 50f, center3.Y - 50f, 100, 100), Color.Green, 2.0f, 0, Vector2.Zero, 1.0f); - _canvas.DrawFillArc(new Arc2(center3, 50f, MathUtil.DegreesToRadians(80), 0), Color.Blue, 0.0f, Vector2.Zero, 1.0f); + _canvas.DrawFillArc( + new Arc2(center3, 50f, MathUtil.DegreesToRadians(80), 0), Color.Blue, 0.0f, Vector2.Zero, 1.0f); Vector2 center31 = new Vector2(1300, 500); _canvas.DrawRectangle( @@ -224,7 +226,8 @@ protected override void Draw(GameTime gameTime) _canvas.DrawRectangle( new RectangleF(center5.X - 50f, center5.Y - 50f, 100, 100), Color.Green, 2.0f, 0, Vector2.Zero, 1.0f); _canvas.DrawFillArc( - new Arc2(center5, 50f, MathUtil.DegreesToRadians(0), MathUtil.DegreesToRadians(200)), Color.Blue, 0.0f, Vector2.Zero, 1.0f); + new Arc2(center5, 50f, MathUtil.DegreesToRadians(0), MathUtil.DegreesToRadians(200)), Color.Blue, 0.0f, + Vector2.Zero, 1.0f); Vector2 center51 = new Vector2(1300, 700); _canvas.DrawRectangle( @@ -235,14 +238,15 @@ protected override void Draw(GameTime gameTime) Vector2 center200 = new Vector2(1400, 400); _canvas.DrawRectangle( - new RectangleF(center200.X - 50f, center200.Y - 50f, 100, 100), Color.Green, 2.0f, 0, Vector2.Zero, 1.0f); + new RectangleF(center200.X - 50f, center200.Y - 50f, 100, 100), Color.Green, 2.0f, 0, Vector2.Zero, + 1.0f); _canvas.DrawFillArc( new Arc2(center200, 50f, MathUtil.DegreesToRadians(80), MathUtil.DegreesToRadians(10)), Color.Blue, 0.0f, Vector2.Zero, 1.0f); _canvas.DrawFillArc( new Arc2(center200, 50f, MathUtil.DegreesToRadians(80) + k, MathUtil.DegreesToRadians(10) + k), Color.DeepPink, 0.0f, center200, 1.0f); - + Vector2 center400 = new Vector2(1400, 500); _canvas.DrawRectangle( new RectangleF(center400.X - 50f, center400.Y - 50f, 100, 100), Color.Green, 2.0f, 0, Vector2.Zero, @@ -251,7 +255,7 @@ protected override void Draw(GameTime gameTime) new Arc2(center400, 50f, MathUtil.DegreesToRadians(-200), MathUtil.DegreesToRadians(-80)), Color.Blue, 0.0f, Vector2.Zero, 1.0f); - _canvas.Draw(_texture, new RectangleF(1100, 50, 200, 200), Color.White); + _canvas.Draw(_texture, new RectangleF(1100, 50, 200, 200), Color.White); _canvas.Draw(_texture2, new RectangleF(1350, 50, 200, 200), Color.White); _canvas.End(); diff --git a/src/Exomia.Framework/Graphics/Canvas.Arc.cs b/src/Exomia.Framework/Graphics/Canvas.Arc.cs index 8f94a695..99e4420d 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Arc.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Arc.cs @@ -260,6 +260,7 @@ public void DrawFillArc(in Arc2 arc, // ReSharper disable CompareOfFloatsByEqualityOperator float m = u == 0.0f && v == MathUtil.TwoPi ? FILL_CIRCLE_MODE : FILL_CIRCLE_ARC_MODE; + // ReSharper enable CompareOfFloatsByEqualityOperator Item* ptr = Reserve(1); @@ -296,11 +297,12 @@ private static void DrawArcRect(Item* ptr, float u, float v, float o) - { + { // ReSharper disable CompareOfFloatsByEqualityOperator float m = u == 0.0f && v == MathUtil.TwoPi ? BORDER_CIRCLE_MODE : BORDER_CIRCLE_ARC_MODE; + // ReSharper enable CompareOfFloatsByEqualityOperator - + for (int i = 0; i < 2; i++) { VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)ptr + i; diff --git a/src/Exomia.Framework/Graphics/Canvas.Polygon.cs b/src/Exomia.Framework/Graphics/Canvas.Polygon.cs index b9ab9c5d..d5cec622 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Polygon.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Polygon.cs @@ -20,11 +20,19 @@ public sealed unsafe partial class Canvas /// /// Draws a polygon. /// - /// he vertices. + /// The vertices. /// The color. /// The width of the line. + /// The rotation. + /// The origin. /// The opacity. - public void DrawPolygon(Vector2[] vertices, in Color color, float lineWidth, float opacity) + /// Thrown when one or more arguments are outside the required range. + public void DrawPolygon(Vector2[] vertices, + in Color color, + float lineWidth, + float rotation, + in Vector2 origin, + float opacity) { if (vertices.Length < 2) { throw new ArgumentOutOfRangeException(nameof(vertices.Length)); } @@ -32,6 +40,20 @@ public void DrawPolygon(Vector2[] vertices, in Color color, float lineWidth, flo Item* ptr = Reserve(vertices.Length); + if (rotation != 0.0f) + { + double cos = Math.Cos(rotation); + double sin = Math.Sin(rotation); + for (int i = 0; i < vertices.Length; i++) + { + float x = vertices[i].X - origin.X; + float y = vertices[i].Y - origin.Y; + vertices[i] = new Vector2( + (float)(((cos * x) - (sin * y)) + origin.X), + (float)((sin * x) + (cos * y) + origin.Y)); + } + } + Line2 previous = new Line2(vertices[vertices.Length - 1], vertices[0]); Line2 perpendicularPrevious = previous.GetPerpendicular(lineWidth); @@ -73,15 +95,36 @@ public void DrawPolygon(Vector2[] vertices, in Color color, float lineWidth, flo /// /// Draws a filled polygon. /// - /// The vertices. - /// The color. - /// The opacity. - public void DrawFillPolygon(Vector2[] vertices, in Color color, float opacity) + /// The vertices. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// Thrown when one or more arguments are outside the required range. + public void DrawFillPolygon(Vector2[] vertices, + in Color color, + float rotation, + in Vector2 origin, + float opacity) { if (vertices.Length < 3) { throw new ArgumentOutOfRangeException(nameof(vertices.Length)); } Color scaledColor = color * opacity; + if (rotation != 0.0f) + { + double cos = Math.Cos(rotation); + double sin = Math.Sin(rotation); + for (int i = 0; i < vertices.Length; i++) + { + float x = vertices[i].X - origin.X; + float y = vertices[i].Y - origin.Y; + vertices[i] = new Vector2( + (float)(((cos * x) - (sin * y)) + origin.X), + (float)((sin * x) + (cos * y) + origin.Y)); + } + } + // TODO: refactor; remove list; place directly into _vertexBuffer List vs = new List(); for (int i = 1; i < vertices.Length - 1; i += 2) @@ -114,6 +157,7 @@ public void DrawFillPolygon(Vector2[] vertices, in Color color, float opacity) if ((vs.Count & 1) == 1) { + // INFO: currently we need 4 vertices (rectangle) and can't draw triangles directly so just use the first vertex as the last vertex too. *((VertexPositionColorTextureMode*)ptr + vs.Count) = *((VertexPositionColorTextureMode*)ptr + (vs.Count - 3)); } diff --git a/src/Exomia.Framework/Graphics/Canvas.Texture.cs b/src/Exomia.Framework/Graphics/Canvas.Texture.cs index 55564ebe..1b18eb38 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Texture.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Texture.cs @@ -60,7 +60,7 @@ public void Draw(Texture texture, in Vector2 position, in Rectangle? sourceRecta } /// - /// Draws a texture. + /// Draws a texture. /// /// The texture. /// The destination rectangle. @@ -104,7 +104,7 @@ public void Draw(Texture texture, } /// - /// Draws a texture. + /// Draws a texture. /// /// The texture. /// The position. @@ -159,16 +159,16 @@ public void Draw(Texture texture, sourceRectangle, color, rotation, origin, opacity, effects); } - private void DrawTexture(Texture texture, - in RectangleF destination, - bool scaleDestination, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - TextureEffects effects, - float mode = TEXTURE_MODE) + private void DrawTexture(Texture texture, + in RectangleF destination, + bool scaleDestination, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float mode = TEXTURE_MODE) { long tp = texture.TexturePointer.ToInt64(); @@ -229,12 +229,12 @@ private void DrawTexture(Texture texture, vertex->X = d.X + ((corner.X - origin.X) * d.Width); vertex->Y = d.Y + ((corner.Y - origin.Y) * d.Height); vertex->ZW = tp; - + vertex->R = scaledColor.R; vertex->G = scaledColor.G; vertex->B = scaledColor.B; vertex->A = scaledColor.A; - + corner = s_rectangleCornerOffsets[j ^ (int)effects]; vertex->U = (s.X + (corner.X * s.Width)) * deltaX; vertex->V = (s.Y + (corner.Y * s.Height)) * deltaY; diff --git a/src/Exomia.Framework/Graphics/Canvas.Triangle.cs b/src/Exomia.Framework/Graphics/Canvas.Triangle.cs index 7308485e..de39415b 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Triangle.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Triangle.cs @@ -196,8 +196,8 @@ public void DrawFillTriangle(in Triangle2 triangle, } else { - float cos = (float)Math.Cos(rotation); - float sin = (float)Math.Sin(rotation); + double cos = Math.Cos(rotation); + double sin = Math.Sin(rotation); for (int i = 0; i < 3; i++) { @@ -208,8 +208,8 @@ public void DrawFillTriangle(in Triangle2 triangle, float* tf = (float*)t; float x = *(tf + (i << 1)) - origin.X; float y = *(tf + (i << 1) + 1) - origin.Y; - vertex->X = ((cos * x) - (sin * y)) + origin.X; - vertex->Y = (sin * x) + (cos * y) + origin.Y; + vertex->X = (float)(((cos * x) - (sin * y)) + origin.X); + vertex->Y = (float)((sin * x) + (cos * y) + origin.Y); } vertex->R = scaledColor.R; @@ -221,7 +221,7 @@ public void DrawFillTriangle(in Triangle2 triangle, } } - // INFO: currently we need 4 vertices so we just copy the first one as the 4th one + // INFO: currently we need 4 vertices (rectangle) and can't draw triangles directly so just use the first vertex as the last vertex too. *((VertexPositionColorTextureMode*)ptr + 3) = *(VertexPositionColorTextureMode*)ptr; } } diff --git a/src/Exomia.Framework/Graphics/Canvas.cs b/src/Exomia.Framework/Graphics/Canvas.cs index 77589b7b..d76ae830 100644 --- a/src/Exomia.Framework/Graphics/Canvas.cs +++ b/src/Exomia.Framework/Graphics/Canvas.cs @@ -18,6 +18,7 @@ using Exomia.Framework.Graphics.Buffers; using Exomia.Framework.Graphics.Shader; using Exomia.Framework.Resources; +using Exomia.Framework.Win32; using SharpDX; using SharpDX.Direct3D; using SharpDX.Direct3D11; @@ -49,7 +50,7 @@ public sealed unsafe partial class Canvas : IDisposable private static readonly ushort[] s_indices; private static readonly Vector2 s_vector2Zero = Vector2.Zero; private static readonly Rectangle? s_nullRectangle = null; - + private readonly DeviceContext4 _context; private readonly InputLayout _vertexInputLayout; @@ -84,7 +85,7 @@ public sealed unsafe partial class Canvas : IDisposable private SpinLock _spinLock = new SpinLock(Debugger.IsAttached); private readonly Dictionary _textures = new Dictionary(INITIAL_QUEUE_SIZE); - private readonly Dictionary _textureSlotMap = new Dictionary(MAX_TEXTURE_SLOTS); + private readonly Dictionary _textureSlotMap = new Dictionary(MAX_TEXTURE_SLOTS); private readonly Dictionary _fontTextureSlotMap = new Dictionary(MAX_FONT_TEXTURE_SLOTS); /// @@ -274,7 +275,7 @@ private void PrepareForRendering() { _context.Rasterizer.State = _rasterizerState ?? _defaultRasterizerScissorEnabledState; _context.Rasterizer.SetScissorRectangle( - _scissorRectangle.Left, _scissorRectangle.Top, + _scissorRectangle.Left, _scissorRectangle.Top, _scissorRectangle.Right, _scissorRectangle.Bottom); } @@ -291,7 +292,7 @@ private void PrepareForRendering() _context.InputAssembler.SetIndexBuffer(_indexBuffer, _indexBuffer.Format, 0); _context.InputAssembler.SetVertexBuffers(0, _vertexBuffer); } - + private void FlushBatch() { int offset = 0; @@ -320,7 +321,7 @@ private void FlushBatch() item.V2.O = tSlot; item.V3.O = tSlot; item.V4.O = tSlot; - + if (_textureSlotMap.Count > MAX_TEXTURE_SLOTS) { if (i > offset) @@ -329,7 +330,7 @@ private void FlushBatch() } offset = i; - _textureSlotMap.Clear(); + _textureSlotMap.Clear(); _fontTextureSlotMap.Clear(); } break; @@ -344,7 +345,8 @@ private void FlushBatch() if (!_fontTextureSlotMap.TryGetValue(tp, out int tSlot)) { - _context.PixelShader.SetShaderResource(MAX_TEXTURE_SLOTS + _fontTextureSlotMap.Count, texture.TextureView); + _context.PixelShader.SetShaderResource( + MAX_TEXTURE_SLOTS + _fontTextureSlotMap.Count, texture.TextureView); _fontTextureSlotMap.Add(tp, tSlot = _fontTextureSlotMap.Count); } @@ -361,7 +363,7 @@ private void FlushBatch() } offset = i; - _fontTextureSlotMap.Clear(); + _fontTextureSlotMap.Clear(); _textureSlotMap.Clear(); } break; @@ -416,13 +418,10 @@ private void DrawBatch(int offset, int count) try { _spinLock.Enter(ref lockTaken); - int size = _itemQueueLength * 2; - - Item* ptr = (Item*)Marshal.AllocHGlobal(sizeof(Item) * size); - Marshal.FreeHGlobal(new IntPtr(_itemQueue)); - - _itemQueue = ptr; - _itemQueueLength = size; + if (_itemQueueCount >= _itemQueueLength) + { + Mem.Resize(ref _itemQueue, ref _itemQueueLength, _itemQueueLength * 2); + } } finally { diff --git a/src/Exomia.Framework/Win32/Mem.cs b/src/Exomia.Framework/Win32/Mem.cs index f99dc960..e10c5a0f 100644 --- a/src/Exomia.Framework/Win32/Mem.cs +++ b/src/Exomia.Framework/Win32/Mem.cs @@ -8,6 +8,8 @@ #endregion +using System; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; @@ -65,5 +67,23 @@ public static extern void Move(void* dest, public static extern void* Set(void* dest, int value, int count); + + /// + /// Resizes the given array with the given to the given . + /// + /// Generic type parameter. + /// [in,out] The source array ptr. + /// [in,out] The length of the source array. + /// The length of the new array. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Resize(ref T* src, ref int srcLength, int newLength) where T : unmanaged + { + T* ptr = (T*)Marshal.AllocHGlobal(sizeof(T) * newLength); + Mem.Cpy(ptr, src, srcLength * sizeof(T)); + Marshal.FreeHGlobal(new IntPtr(src)); + + src = ptr; + srcLength = newLength; + } } } \ No newline at end of file From e640b1b18e9e141fd6e59dd8e74dfc40c36b649f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=A4tz?= Date: Sun, 22 Nov 2020 18:55:54 +0100 Subject: [PATCH 39/44] v1.5.0-rc.4 - bug fix - canvas drawtext example --- .../Exomia.Framework.Example.Canvas/MyGame.cs | 12 +- .../Graphics/Canvas.Texture.cs | 2 +- src/Exomia.Framework/Graphics/SpriteFont.cs | 109 ++---------------- 3 files changed, 18 insertions(+), 105 deletions(-) diff --git a/examples/Exomia.Framework.Example.Canvas/MyGame.cs b/examples/Exomia.Framework.Example.Canvas/MyGame.cs index 49d20082..00297208 100644 --- a/examples/Exomia.Framework.Example.Canvas/MyGame.cs +++ b/examples/Exomia.Framework.Example.Canvas/MyGame.cs @@ -27,8 +27,10 @@ sealed class MyGame : Game.Game private Graphics.Canvas _canvas = null!; - private Texture _texture = null!; - private Texture _texture2 = null!; + private Texture _texture = null!; + private Texture _texture2 = null!; + private SpriteFont _spriteFont1_12Px = null!; + private SpriteFont _spriteFont1_24Px = null!; private float k; @@ -85,6 +87,9 @@ protected override void OnLoadContent() _texture = Content.Load("logo1.jpg"); _texture2 = Content.Load("logo2.png"); + + _spriteFont1_12Px = Content.Load(Resources.Fonts.ARIAL_12_PX, true); + _spriteFont1_24Px = Content.Load(Resources.Fonts.ARIAL_24_PX, true); } /// @@ -257,6 +262,9 @@ protected override void Draw(GameTime gameTime) _canvas.Draw(_texture, new RectangleF(1100, 50, 200, 200), Color.White); _canvas.Draw(_texture2, new RectangleF(1350, 50, 200, 200), Color.White); + + _canvas.DrawText(_spriteFont1_12Px, "This is the canvas example.", new Vector2(450, 50), Color.Black); + _canvas.DrawText(_spriteFont1_24Px, "This is the canvas example.", new Vector2(450, 65), Color.Black); _canvas.End(); diff --git a/src/Exomia.Framework/Graphics/Canvas.Texture.cs b/src/Exomia.Framework/Graphics/Canvas.Texture.cs index 1b18eb38..f9db2dbe 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Texture.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Texture.cs @@ -199,7 +199,7 @@ private void DrawTexture(Texture texture, if (scaleDestination) { d.Width *= s.Width; - d.Height *= s.Width; + d.Height *= s.Height; } if (d.Width < 0) diff --git a/src/Exomia.Framework/Graphics/SpriteFont.cs b/src/Exomia.Framework/Graphics/SpriteFont.cs index 033463b0..39dd8f31 100644 --- a/src/Exomia.Framework/Graphics/SpriteFont.cs +++ b/src/Exomia.Framework/Graphics/SpriteFont.cs @@ -179,20 +179,7 @@ public SpriteFont() { Dispose(false); } - - /// - /// Draw font. - /// - /// The texture. - /// The position. - /// Source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The scale. - /// The opacity. - /// The effects. - /// Depth of the layer. + internal delegate void DrawFont(Texture texture, in Vector2 position, in Rectangle? sourceRectangle, @@ -430,19 +417,7 @@ public int HitTest(string text, int start, int end, float xPos, float yPos) return end; } - - /// - /// Draws. - /// - /// The draw callback. - /// The text. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. + internal void Draw(DrawFont drawCallback, string text, in Vector2 position, @@ -509,21 +484,7 @@ internal void Draw(DrawFont drawCallback, key <<= 16; } } - - /// - /// Draws. - /// - /// The draw callback. - /// The text. - /// The start. - /// The end. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. + internal void Draw(DrawFont drawCallback, string text, int start, @@ -593,22 +554,7 @@ internal void Draw(DrawFont drawCallback, key <<= 16; } } - - /// - /// Draws. - /// - /// The draw callback. - /// The text. - /// The start. - /// The end. - /// The position. - /// The dimension. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. + internal void Draw(DrawFont drawCallback, string text, int start, @@ -857,19 +803,7 @@ public int HitTest(StringBuilder text, int start, int end, float xPos, float yPo return end; } - - /// - /// Draws. - /// - /// The draw callback. - /// The text. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. + internal void Draw(DrawFont drawCallback, StringBuilder text, in Vector2 position, @@ -935,21 +869,7 @@ internal void Draw(DrawFont drawCallback, key <<= 16; } } - - /// - /// Draws. - /// - /// The draw callback. - /// The text. - /// The start. - /// The end. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. + internal void Draw(DrawFont drawCallback, StringBuilder text, int start, @@ -1019,22 +939,7 @@ internal void Draw(DrawFont drawCallback, key <<= 16; } } - - /// - /// Draws. - /// - /// The draw callback. - /// The text. - /// The start. - /// The end. - /// The position. - /// The dimension. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// Depth of the layer. + internal void Draw(DrawFont drawCallback, StringBuilder text, int start, From 8be35e8d0c1123fb81f1904ecbb857052722c0ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=A4tz?= Date: Sun, 22 Nov 2020 19:11:17 +0100 Subject: [PATCH 40/44] updated workflow --- .github/workflows/build_test_and_publish.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_test_and_publish.yml b/.github/workflows/build_test_and_publish.yml index 956ce7d4..30dfa352 100644 --- a/.github/workflows/build_test_and_publish.yml +++ b/.github/workflows/build_test_and_publish.yml @@ -52,7 +52,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: extract tag version - run: echo ::set-env name=TAG_VERSION::${GITHUB_REF#refs/tags/v*} + run: echo "TAG_VERSION=${GITHUB_REF#refs/tags/v*}" >> $GITHUB_ENV shell: bash - uses: actions/setup-dotnet@v1 with: @@ -78,7 +78,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: extract tag version - run: echo ::set-env name=TAG_VERSION::${GITHUB_REF#refs/tags/v*} + run: echo "TAG_VERSION=${GITHUB_REF#refs/tags/v*}" >> $GITHUB_ENV shell: bash - uses: actions/setup-dotnet@v1 with: From 5b0421c0c2465953b986d9fa7a97b105c5b9ba52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=A4tz?= Date: Sun, 22 Nov 2020 19:30:20 +0100 Subject: [PATCH 41/44] updated wiki --- examples/Exomia.Framework.Example.Canvas/MyGame.cs | 2 +- framework.wiki | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/Exomia.Framework.Example.Canvas/MyGame.cs b/examples/Exomia.Framework.Example.Canvas/MyGame.cs index 00297208..99197bc7 100644 --- a/examples/Exomia.Framework.Example.Canvas/MyGame.cs +++ b/examples/Exomia.Framework.Example.Canvas/MyGame.cs @@ -264,7 +264,7 @@ protected override void Draw(GameTime gameTime) _canvas.Draw(_texture2, new RectangleF(1350, 50, 200, 200), Color.White); _canvas.DrawText(_spriteFont1_12Px, "This is the canvas example.", new Vector2(450, 50), Color.Black); - _canvas.DrawText(_spriteFont1_24Px, "This is the canvas example.", new Vector2(450, 65), Color.Black); + _canvas.DrawText(_spriteFont1_24Px, "This is the canvas example.", new Vector2(450, 65), Color.Black); _canvas.End(); diff --git a/framework.wiki b/framework.wiki index fe71e576..89bb7be5 160000 --- a/framework.wiki +++ b/framework.wiki @@ -1 +1 @@ -Subproject commit fe71e576d303aeb21822dec7a3a2939b5c039d7c +Subproject commit 89bb7be513e702d434f66ae6236a47694d3df750 From 43893b4dca4329f0cde2ebb8da5196c1cb4387d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=A4tz?= Date: Mon, 23 Nov 2020 01:08:19 +0100 Subject: [PATCH 42/44] improved polygon drawing - added remarks --- .../Exomia.Framework.Example.Canvas/MyGame.cs | 21 ++++-- .../Graphics/Canvas.Polygon.cs | 70 +++++++++++++------ 2 files changed, 62 insertions(+), 29 deletions(-) diff --git a/examples/Exomia.Framework.Example.Canvas/MyGame.cs b/examples/Exomia.Framework.Example.Canvas/MyGame.cs index 99197bc7..6a75585c 100644 --- a/examples/Exomia.Framework.Example.Canvas/MyGame.cs +++ b/examples/Exomia.Framework.Example.Canvas/MyGame.cs @@ -143,18 +143,25 @@ protected override void Draw(GameTime gameTime) _canvas.DrawLine(new Line2(400, 450, 450, 400), Color.Yellow, 5.0f, 1.0f); _canvas.DrawFillPolygon( - new[] { new Vector2(400, 300), new Vector2(550, 320), new Vector2(650, 520), new Vector2(520, 450) }, + new[] { new Vector2(550, 250), new Vector2(550, 120), new Vector2(650, 320), new Vector2(520, 250) }, Color.Red, 0.0f, Vector2.Zero, 1.0f); _canvas.DrawPolygon( - new[] { new Vector2(400, 300), new Vector2(550, 320), new Vector2(650, 520), new Vector2(520, 450) }, + new[] { new Vector2(550, 250), new Vector2(550, 120), new Vector2(650, 320), new Vector2(520, 250) }, Color.Green, 5.0f, 0.0f, Vector2.Zero, 1.0f); _canvas.DrawFillPolygon( - new[] { new Vector2(400, 300), new Vector2(550, 320), new Vector2(650, 520), new Vector2(520, 450) }, - Color.Yellow, k, new Vector2(400, 300), 1.0f); + new[] { new Vector2(450, 400), new Vector2(700, 420), new Vector2(700, 450), new Vector2(600, 480), new Vector2(600, 600) }, + Color.Red, 0.0f, Vector2.Zero, 1.0f); + _canvas.DrawPolygon( + new[] { new Vector2(450, 400), new Vector2(700, 420), new Vector2(700, 450), new Vector2(600, 480), new Vector2(600, 600) }, + Color.Green, 5.0f, 0.0f, Vector2.Zero, 1.0f); + + _canvas.DrawFillPolygon( + new[] { new Vector2(400, 600), new Vector2(550, 620), new Vector2(650, 820), new Vector2(520, 750) }, + Color.Yellow, k, new Vector2(400, 600), 1.0f); _canvas.DrawPolygon( - new[] { new Vector2(400, 300), new Vector2(550, 320), new Vector2(650, 520), new Vector2(520, 450) }, - Color.Green, 5.0f, k, new Vector2(400, 300), 1.0f); + new[] { new Vector2(400, 600), new Vector2(550, 620), new Vector2(650, 820), new Vector2(520, 750) }, + Color.Green, 5.0f, k, new Vector2(400, 600), 1.0f); _canvas.DrawFillPolygon( new[] @@ -173,7 +180,7 @@ protected override void Draw(GameTime gameTime) Vector2 center = new Vector2(800, 400); _canvas.DrawRectangle( - new RectangleF(center.X - 100, center.Y - 100, 200, 200), Color.Green, 2, 0, Vector2.Zero, 0.0f); + new RectangleF(center.X - 100, center.Y - 100, 200, 200), Color.Green, 2, 0, Vector2.Zero, 1.0f); _canvas.DrawFillArc(new Arc2(center, 100f), Color.Black, 0, center, 1.0f); float l = 20; diff --git a/src/Exomia.Framework/Graphics/Canvas.Polygon.cs b/src/Exomia.Framework/Graphics/Canvas.Polygon.cs index d5cec622..eea8fceb 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Polygon.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Polygon.cs @@ -101,6 +101,12 @@ public void DrawPolygon(Vector2[] vertices, /// The origin. /// The opacity. /// Thrown when one or more arguments are outside the required range. + /// + /// Attention: + /// - The must be declared in a clockwise orientation. + /// - The triangulation used to fill the polygon may not work for concave polygons at the moment! + /// - Complex polygons may not work at all! + /// public void DrawFillPolygon(Vector2[] vertices, in Color color, float rotation, @@ -125,27 +131,23 @@ public void DrawFillPolygon(Vector2[] vertices, } } - // TODO: refactor; remove list; place directly into _vertexBuffer - List vs = new List(); + VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)Reserve(vertices.Length - 2); + for (int i = 1; i < vertices.Length - 1; i += 2) { - vs.Add(vertices[0]); - vs.Add(vertices[i]); - vs.Add(vertices[i + 1]); - if (i + 2 < vertices.Length) - { - vs.Add(vertices[i + 2]); - } - } + vertex->X = vertices[0].X; + vertex->Y = vertices[0].Y; - Item* ptr = Reserve((vs.Count + 1) / 4); + vertex->R = scaledColor.R; + vertex->G = scaledColor.G; + vertex->B = scaledColor.B; + vertex->A = scaledColor.A; - for (int j = 0; j < vs.Count; j++) - { - VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)ptr + j; + vertex->M = COLOR_MODE; + vertex++; - vertex->X = vs[j].X; - vertex->Y = vs[j].Y; + vertex->X = vertices[i].X; + vertex->Y = vertices[i].Y; vertex->R = scaledColor.R; vertex->G = scaledColor.G; @@ -153,13 +155,37 @@ public void DrawFillPolygon(Vector2[] vertices, vertex->A = scaledColor.A; vertex->M = COLOR_MODE; - } + vertex++; - if ((vs.Count & 1) == 1) - { - // INFO: currently we need 4 vertices (rectangle) and can't draw triangles directly so just use the first vertex as the last vertex too. - *((VertexPositionColorTextureMode*)ptr + vs.Count) = - *((VertexPositionColorTextureMode*)ptr + (vs.Count - 3)); + vertex->X = vertices[i + 1].X; + vertex->Y = vertices[i + 1].Y; + + vertex->R = scaledColor.R; + vertex->G = scaledColor.G; + vertex->B = scaledColor.B; + vertex->A = scaledColor.A; + + vertex->M = COLOR_MODE; + vertex++; + + if (i + 2 < vertices.Length) + { + vertex->X = vertices[i + 2].X; + vertex->Y = vertices[i + 2].Y; + + vertex->R = scaledColor.R; + vertex->G = scaledColor.G; + vertex->B = scaledColor.B; + vertex->A = scaledColor.A; + + vertex->M = COLOR_MODE; + vertex++; + } + else + { + // INFO: currently we need 4 vertices (rectangle) and can't draw triangles directly so just use the first vertex as the last vertex too. + *vertex = *(vertex - 3); + } } } } From 9fcd80cb2ae21a54fd809acf59068e3376944fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=A4tz?= Date: Mon, 23 Nov 2020 02:22:11 +0100 Subject: [PATCH 43/44] performance --- src/Exomia.Framework/Graphics/Canvas.Arc.cs | 12 ++- src/Exomia.Framework/Graphics/Canvas.Line.cs | 44 +++++----- .../Graphics/Canvas.Polygon.cs | 44 +++++----- .../Graphics/Canvas.Rectangle.cs | 28 +++---- .../Graphics/Canvas.Structs.cs | 4 + .../Graphics/Canvas.Triangle.cs | 34 ++++---- .../Graphics/SpriteBatch.Line.cs | 2 +- src/Exomia.Framework/Mathematics/Line2.cs | 82 ++++++++++++++----- src/Exomia.Framework/Mathematics/Triangle2.cs | 63 ++++++++++---- 9 files changed, 188 insertions(+), 125 deletions(-) diff --git a/src/Exomia.Framework/Graphics/Canvas.Arc.cs b/src/Exomia.Framework/Graphics/Canvas.Arc.cs index 99e4420d..1a34a297 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Arc.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Arc.cs @@ -274,7 +274,7 @@ public void DrawFillArc(in Arc2 arc, vertex->Y = y + (corner.Y * arc.Radius); vertex->Z = x; vertex->W = y; - + vertex->R = scaledColor.R; vertex->G = scaledColor.G; vertex->B = scaledColor.B; @@ -308,9 +308,8 @@ private static void DrawArcRect(Item* ptr, VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)ptr + i; fixed (Line2* t = &lineA) { - float* lf = (float*)t; - vertex->X = *(lf + (i << 1)); - vertex->Y = *(lf + (i << 1) + 1); + Vector2* lf = (Vector2*)t; + vertex->XY = *(lf + i); } vertex->Z = z; @@ -333,9 +332,8 @@ private static void DrawArcRect(Item* ptr, VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)ptr + 2 + (1 - i); fixed (Line2* t = &lineB) { - float* lf = (float*)t; - vertex->X = *(lf + (i << 1)); - vertex->Y = *(lf + (i << 1) + 1); + Vector2* lf = (Vector2*)t; + vertex->XY = *(lf + i); } vertex->Z = z; diff --git a/src/Exomia.Framework/Graphics/Canvas.Line.cs b/src/Exomia.Framework/Graphics/Canvas.Line.cs index 6a057290..3ab66e2c 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Line.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Line.cs @@ -34,7 +34,7 @@ public void DrawLine(in Vector2 point1, float opacity, float lengthFactor = 1.0f) { - DrawLine(new Line2(point1, point2), color, lineWidth, opacity, lengthFactor); + DrawLine(new Line2(in point1, in point2), color, lineWidth, opacity, lengthFactor); } /// @@ -51,6 +51,8 @@ public void DrawLine(in Line2 line, float opacity, float lengthFactor = 1.0f) { + Color scaledColor = color * opacity; + float dx = line.X2 - line.X1; float dy = line.Y2 - line.Y1; @@ -61,25 +63,23 @@ public void DrawLine(in Line2 line, VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)Reserve(1); // p1 - vertex->X = line.X1; - vertex->Y = line.Y1; + vertex->XY = line.XY1; - vertex->R = color.R * opacity; - vertex->G = color.G * opacity; - vertex->B = color.B * opacity; - vertex->A = color.A * opacity; + vertex->R = scaledColor.R; + vertex->G = scaledColor.G; + vertex->B = scaledColor.B; + vertex->A = scaledColor.A; vertex->M = COLOR_MODE; vertex++; // p2 - vertex->X = line.X2; - vertex->Y = line.Y2; - - vertex->R = color.R * opacity; - vertex->G = color.G * opacity; - vertex->B = color.B * opacity; - vertex->A = color.A * opacity; + vertex->XY = line.XY2; + + vertex->R = scaledColor.R; + vertex->G = scaledColor.G; + vertex->B = scaledColor.B; + vertex->A = scaledColor.A; vertex->M = COLOR_MODE; vertex++; @@ -88,10 +88,10 @@ public void DrawLine(in Line2 line, vertex->X = line.X2 - nx; vertex->Y = line.Y2 + ny; - vertex->R = color.R * opacity; - vertex->G = color.G * opacity; - vertex->B = color.B * opacity; - vertex->A = color.A * opacity; + vertex->R = scaledColor.R; + vertex->G = scaledColor.G; + vertex->B = scaledColor.B; + vertex->A = scaledColor.A; vertex->M = COLOR_MODE; vertex++; @@ -100,10 +100,10 @@ public void DrawLine(in Line2 line, vertex->X = line.X1 - nx; vertex->Y = line.Y1 + ny; - vertex->R = color.R * opacity; - vertex->G = color.G * opacity; - vertex->B = color.B * opacity; - vertex->A = color.A * opacity; + vertex->R = scaledColor.R; + vertex->G = scaledColor.G; + vertex->B = scaledColor.B; + vertex->A = scaledColor.A; vertex->M = COLOR_MODE; } diff --git a/src/Exomia.Framework/Graphics/Canvas.Polygon.cs b/src/Exomia.Framework/Graphics/Canvas.Polygon.cs index eea8fceb..60c7ed0b 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Polygon.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Polygon.cs @@ -46,19 +46,19 @@ public void DrawPolygon(Vector2[] vertices, double sin = Math.Sin(rotation); for (int i = 0; i < vertices.Length; i++) { - float x = vertices[i].X - origin.X; - float y = vertices[i].Y - origin.Y; - vertices[i] = new Vector2( - (float)(((cos * x) - (sin * y)) + origin.X), - (float)((sin * x) + (cos * y) + origin.Y)); + ref Vector2 v = ref vertices[i]; + float x = v.X - origin.X; + float y = v.Y - origin.Y; + v.X = (float)(((cos * x) - (sin * y)) + origin.X); + v.Y = (float)((sin * x) + (cos * y) + origin.Y); } } - - Line2 previous = new Line2(vertices[vertices.Length - 1], vertices[0]); - Line2 perpendicularPrevious = previous.GetPerpendicular(lineWidth); - - Line2 current = new Line2(vertices[0], vertices[1]); - Line2 perpendicularCurrent = current.GetPerpendicular(lineWidth); + + Line2 previous = Line2.CreateWithPerpendicular( + ref vertices[vertices.Length - 1], ref vertices[0], lineWidth, out Line2 perpendicularPrevious); + + Line2 current = Line2.CreateWithPerpendicular( + ref vertices[0], ref vertices[1], lineWidth, out Line2 perpendicularCurrent); if (!perpendicularPrevious.IntersectWith(perpendicularCurrent, out Vector2 ipE)) { @@ -68,15 +68,15 @@ public void DrawPolygon(Vector2[] vertices, Vector2 ip1 = ipE; for (int i = 1; i < vertices.Length - 1; i++) { - Line2 next = new Line2(vertices[i], vertices[i + 1]); - Line2 perpendicularNext = next.GetPerpendicular(lineWidth); + Line2 next = Line2.CreateWithPerpendicular( + ref vertices[i], ref vertices[i + 1], lineWidth, out Line2 perpendicularNext); if (!perpendicularCurrent.IntersectWith(perpendicularNext, out Vector2 ip2)) { ip2 = new Vector2(perpendicularNext.X1, perpendicularNext.Y1); } - DrawRect(ptr + i, current, new Line2(ip1.X, ip1.Y, ip2.X, ip2.Y), in scaledColor); + DrawRect(ptr + i, current, new Line2(in ip1, in ip2), in scaledColor); current = next; perpendicularCurrent = perpendicularNext; @@ -88,8 +88,8 @@ public void DrawPolygon(Vector2[] vertices, ip3 = new Vector2(perpendicularPrevious.X1, perpendicularPrevious.Y1); } - DrawRect(ptr, current, new Line2(ip1.X, ip1.Y, ip3.X, ip3.Y), in scaledColor); - DrawRect(ptr + (vertices.Length - 1), previous, new Line2(ip3.X, ip3.Y, ipE.X, ipE.Y), in scaledColor); + DrawRect(ptr, current, new Line2(in ip1, in ip3), in scaledColor); + DrawRect(ptr + (vertices.Length - 1), previous, new Line2(in ip3, in ipE), in scaledColor); } /// @@ -135,8 +135,7 @@ public void DrawFillPolygon(Vector2[] vertices, for (int i = 1; i < vertices.Length - 1; i += 2) { - vertex->X = vertices[0].X; - vertex->Y = vertices[0].Y; + vertex->XY = vertices[0]; vertex->R = scaledColor.R; vertex->G = scaledColor.G; @@ -146,8 +145,7 @@ public void DrawFillPolygon(Vector2[] vertices, vertex->M = COLOR_MODE; vertex++; - vertex->X = vertices[i].X; - vertex->Y = vertices[i].Y; + vertex->XY = vertices[i]; vertex->R = scaledColor.R; vertex->G = scaledColor.G; @@ -157,8 +155,7 @@ public void DrawFillPolygon(Vector2[] vertices, vertex->M = COLOR_MODE; vertex++; - vertex->X = vertices[i + 1].X; - vertex->Y = vertices[i + 1].Y; + vertex->XY = vertices[i + 1]; vertex->R = scaledColor.R; vertex->G = scaledColor.G; @@ -170,8 +167,7 @@ public void DrawFillPolygon(Vector2[] vertices, if (i + 2 < vertices.Length) { - vertex->X = vertices[i + 2].X; - vertex->Y = vertices[i + 2].Y; + vertex->XY = vertices[i + 2]; vertex->R = scaledColor.R; vertex->G = scaledColor.G; diff --git a/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs b/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs index 04968095..97770dce 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs @@ -49,25 +49,25 @@ public void DrawRectangle(in RectangleF destination, DrawRect( ptr + 0, new Line2(destination.TopLeft, destination.TopRight), - new Line2(tl, tr), + new Line2(in tl, in tr), in scaledColor); DrawRect( ptr + 1, new Line2(destination.TopRight, destination.BottomRight), - new Line2(tr, br), + new Line2(in tr, in br), in scaledColor); DrawRect( ptr + 2, new Line2(destination.BottomRight, destination.BottomLeft), - new Line2(br, bl), + new Line2(in br, in bl), in scaledColor); DrawRect( ptr + 3, new Line2(destination.BottomLeft, destination.TopLeft), - new Line2(bl, tl), + new Line2(in bl, in tl), in scaledColor); } else @@ -119,10 +119,10 @@ public void DrawRectangle(in RectangleF destination, Vector2 bl2 = new Vector2( (float)((blx2 * cos) - (bly2 * sin)) + origin.X, (float)((blx2 * sin) + (bly2 * cos)) + origin.Y); - DrawRect(ptr + 0, new Line2(tl1, tr1), new Line2(tl2, tr2), in scaledColor); - DrawRect(ptr + 1, new Line2(tr1, br1), new Line2(tr2, br2), in scaledColor); - DrawRect(ptr + 2, new Line2(br1, bl1), new Line2(br2, bl2), in scaledColor); - DrawRect(ptr + 3, new Line2(bl1, tl1), new Line2(bl2, tl2), in scaledColor); + DrawRect(ptr + 0, new Line2(in tl1, in tr1), new Line2(in tl2, in tr2), in scaledColor); + DrawRect(ptr + 1, new Line2(in tr1, in br1), new Line2(in tr2, in br2), in scaledColor); + DrawRect(ptr + 2, new Line2(in br1, in bl1), new Line2(in br2, in bl2), in scaledColor); + DrawRect(ptr + 3, new Line2(in bl1, in tl1), new Line2(in bl2, in tl2), in scaledColor); } } @@ -192,8 +192,7 @@ public void DrawFillRectangle(in RectangleF destination, private static void DrawRect(Item* ptr, in Line2 lineA, in Line2 lineB, in Color c) { // p1 - ptr->V1.X = lineA.X1; - ptr->V1.Y = lineA.Y1; + ptr->V1.XY = lineA.XY1; ptr->V1.R = c.R; ptr->V1.G = c.G; @@ -203,8 +202,7 @@ private static void DrawRect(Item* ptr, in Line2 lineA, in Line2 lineB, in Color ptr->V1.M = COLOR_MODE; // p2 - ptr->V2.X = lineA.X2; - ptr->V2.Y = lineA.Y2; + ptr->V2.XY = lineA.XY2; ptr->V2.R = c.R; ptr->V2.G = c.G; @@ -214,8 +212,7 @@ private static void DrawRect(Item* ptr, in Line2 lineA, in Line2 lineB, in Color ptr->V2.M = COLOR_MODE; // p2' - ptr->V3.X = lineB.X2; - ptr->V3.Y = lineB.Y2; + ptr->V3.XY = lineB.XY2; ptr->V3.R = c.R; ptr->V3.G = c.G; @@ -225,8 +222,7 @@ private static void DrawRect(Item* ptr, in Line2 lineA, in Line2 lineB, in Color ptr->V3.M = COLOR_MODE; // p1' - ptr->V4.X = lineB.X1; - ptr->V4.Y = lineB.Y1; + ptr->V4.XY = lineB.XY1; ptr->V4.R = c.R; ptr->V4.G = c.G; diff --git a/src/Exomia.Framework/Graphics/Canvas.Structs.cs b/src/Exomia.Framework/Graphics/Canvas.Structs.cs index e0773add..04fb31f7 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Structs.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Structs.cs @@ -9,6 +9,7 @@ #endregion using System.Runtime.InteropServices; +using SharpDX; namespace Exomia.Framework.Graphics { @@ -38,6 +39,9 @@ private struct VertexPositionColorTextureMode [FieldOffset(4)] public float Y; + + [FieldOffset(0)] + public Vector2 XY; [FieldOffset(8)] public float Z; diff --git a/src/Exomia.Framework/Graphics/Canvas.Triangle.cs b/src/Exomia.Framework/Graphics/Canvas.Triangle.cs index de39415b..8264048c 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Triangle.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Triangle.cs @@ -49,7 +49,7 @@ public void DrawTriangle(in Vector2 point1, in Vector2 origin, float opacity) { - DrawTriangle(new Triangle2(point1, point2, point3), color, lineWidth, rotation, in origin, opacity); + DrawTriangle(new Triangle2(in point1, in point2, in point3), color, lineWidth, rotation, in origin, opacity); } /// @@ -79,16 +79,16 @@ public void DrawTriangle(in Triangle2 triangle, in Vector2 origin, float opacity) { - Triangle2 t = rotation == 0.0 ? triangle : Triangle2.RotateAround(triangle, rotation, origin); + Triangle2 t = rotation == 0.0 ? triangle : Triangle2.RotateAround(in triangle, rotation, in origin); Color scaledColor = color * opacity; - Line2 a = new Line2(t.X1, t.Y1, t.X2, t.Y2); + Line2 a = new Line2(in t.XY1, in t.XY2); Line2 perpendicularA = a.GetPerpendicular(lineWidth); - - Line2 b = new Line2(t.X2, t.Y2, t.X3, t.Y3); + + Line2 b = new Line2(in t.XY2, in t.XY3); Line2 perpendicularB = b.GetPerpendicular(lineWidth); - Line2 c = new Line2(t.X3, t.Y3, t.X1, t.Y1); + Line2 c = new Line2(in t.XY3, in t.XY1); Line2 perpendicularC = c.GetPerpendicular(lineWidth); if (!perpendicularA.IntersectWith(perpendicularB, out Vector2 ipAb)) @@ -107,9 +107,9 @@ public void DrawTriangle(in Triangle2 triangle, } Item* ptr = Reserve(3); - DrawRect(ptr + 0, a, new Line2(ipCa.X, ipCa.Y, ipAb.X, ipAb.Y), in scaledColor); - DrawRect(ptr + 1, b, new Line2(ipAb.X, ipAb.Y, ipBc.X, ipBc.Y), in scaledColor); - DrawRect(ptr + 2, c, new Line2(ipBc.X, ipBc.Y, ipCa.X, ipCa.Y), in scaledColor); + DrawRect(ptr + 0, a, new Line2(in ipCa, in ipAb), in scaledColor); + DrawRect(ptr + 1, b, new Line2(in ipAb, in ipBc), in scaledColor); + DrawRect(ptr + 2, c, new Line2(in ipBc, in ipCa), in scaledColor); } /// @@ -141,7 +141,7 @@ public void DrawFillTriangle(in Vector2 point1, in Vector2 origin, float opacity) { - DrawFillTriangle(new Triangle2(point1, point2, point3), color, rotation, origin, opacity); + DrawFillTriangle(new Triangle2(in point1, in point2, in point3), color, rotation, origin, opacity); } /// @@ -181,9 +181,8 @@ public void DrawFillTriangle(in Triangle2 triangle, fixed (Triangle2* t = &triangle) { - float* tf = (float*)t; - vertex->X = *(tf + (i << 1)); - vertex->Y = *(tf + (i << 1) + 1); + Vector2* tf = (Vector2*)t; + vertex->XY = *(tf + i ); } vertex->R = scaledColor.R; @@ -205,11 +204,10 @@ public void DrawFillTriangle(in Triangle2 triangle, fixed (Triangle2* t = &triangle) { - float* tf = (float*)t; - float x = *(tf + (i << 1)) - origin.X; - float y = *(tf + (i << 1) + 1) - origin.Y; - vertex->X = (float)(((cos * x) - (sin * y)) + origin.X); - vertex->Y = (float)((sin * x) + (cos * y) + origin.Y); + Vector2* tf = (Vector2*)t; + Vector2 v = *(tf + i) - origin; + vertex->X = (float)(((cos * v.X) - (sin * v.Y)) + origin.X); + vertex->Y = (float)((sin * v.X) + (cos * v.Y) + origin.Y); } vertex->R = scaledColor.R; diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.Line.cs b/src/Exomia.Framework/Graphics/SpriteBatch.Line.cs index 57311d6e..a7e1128a 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.Line.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.Line.cs @@ -74,7 +74,7 @@ public void DrawLine(in Vector2 point1, float lengthFactor, float layerDepth) { - DrawLine(new Line2(point1, point2), color, lineWidth, opacity, lengthFactor, layerDepth); + DrawLine(new Line2(in point1, in point2), color, lineWidth, opacity, lengthFactor, layerDepth); } /// diff --git a/src/Exomia.Framework/Mathematics/Line2.cs b/src/Exomia.Framework/Mathematics/Line2.cs index 05c1cb5b..a8651241 100644 --- a/src/Exomia.Framework/Mathematics/Line2.cs +++ b/src/Exomia.Framework/Mathematics/Line2.cs @@ -13,7 +13,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SharpDX; -using SharpDX.Direct3D9; namespace Exomia.Framework.Mathematics { @@ -21,28 +20,44 @@ namespace Exomia.Framework.Mathematics /// A 2d line. /// /// - [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 16)] + [StructLayout(LayoutKind.Explicit, Pack = 4, Size = 16)] public readonly struct Line2 : IFormattable { /// /// The first x value. /// - public readonly float X1; //Note: do not reorder this field, unless you know what you are doing. + [FieldOffset(0)] + public readonly float X1; /// /// The first y value. /// - public readonly float Y1; //Note: do not reorder this field, unless you know what you are doing. + [FieldOffset(4)] + public readonly float Y1; /// - /// The second x value. + /// The first xy. /// - public readonly float X2; //Note: do not reorder this field, unless you know what you are doing. + [FieldOffset(0)] + public readonly Vector2 XY1; /// /// The second y value. /// - public readonly float Y2; //Note: do not reorder this field, unless you know what you are doing. + [FieldOffset(8)] + public readonly float X2; + + /// + /// The second x value. + /// + [FieldOffset(12)] + public readonly float Y2; + + /// + /// The second xy. + /// + [FieldOffset(8)] + public readonly Vector2 XY2; /// /// Initializes a new instance of the struct. @@ -51,29 +66,32 @@ namespace Exomia.Framework.Mathematics /// The first y value. /// The second x value. /// The second y value. - public Line2(float x1, float y1, float x2, float y2) + public Line2(float x1, float y1, float x2, float y2) : this() { - X1 = x1; - Y1 = y1; - X2 = x2; - Y2 = y2; + X1 = x1; + Y1 = y1; + X2 = x2; + Y2 = y2; } /// /// Initializes a new instance of the struct. /// - /// The VectorI2 to process. - /// The VectorI2 to process. - public Line2(VectorI2 a, VectorI2 b) + /// [in,out] The to process. + /// [in,out] The to process. + public Line2(in VectorI2 a, in VectorI2 b) : this(a.X, a.Y, b.X, b.Y) { } /// /// Initializes a new instance of the struct. /// - /// The Vector2 to process. - /// The Vector2 to process. - public Line2(Vector2 a, Vector2 b) - : this(a.X, a.Y, b.X, b.Y) { } + /// [in,out] The to process. + /// [in,out] The to process. + public Line2(in Vector2 a, in Vector2 b) : this() + { + XY1 = a; + XY2 = b; + } /// /// Determines whether the specified is equal to this instance. @@ -172,7 +190,7 @@ public string ToString(string? format, IFormatProvider formatProvider) } /// - /// Intersect with other . + /// Intersect with other . /// /// The to compare with this instance. /// [out] The intersection point. @@ -246,5 +264,29 @@ public static Line2 RotateAround(in Line2 line, float rotation, in Vector2 origi (float)((x1 * cos) - (y1 * sin)) + origin.X, (float)((x1 * sin) + (y1 * cos)) + origin.Y, (float)((x2 * cos) - (y2 * sin)) + origin.X, (float)((x2 * sin) + (y2 * cos)) + origin.Y); } + + /// + /// Creates a line out of and , as well the perpendicular from this line. + /// + /// [in,out] The first ref . + /// [in,out] The second ref . + /// The offset. + /// [out] The perpendicular. + /// + /// The line created from and . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Line2 CreateWithPerpendicular(ref Vector2 p1, ref Vector2 p2, float offset, out Line2 perpendicular) + { + float dx = p2.X - p1.X; + float dy = p2.Y - p1.Y; + + double dl = Math.Sqrt((dx * dx) + (dy * dy)); + float nx = (float)((dy / dl) * offset); + float ny = (float)((dx / dl) * offset); + + perpendicular = new Line2(p1.X - nx, p1.Y + ny, p2.X - nx, p2.Y + ny); + return new Line2(p1.X, p1.Y, p2.X, p2.Y); + } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Mathematics/Triangle2.cs b/src/Exomia.Framework/Mathematics/Triangle2.cs index b3f3657e..bd6b3289 100644 --- a/src/Exomia.Framework/Mathematics/Triangle2.cs +++ b/src/Exomia.Framework/Mathematics/Triangle2.cs @@ -20,39 +20,63 @@ namespace Exomia.Framework.Mathematics /// A 2d triangle. /// /// - [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 24)] + [StructLayout(LayoutKind.Explicit, Pack = 4, Size = 24)] public readonly struct Triangle2 : IFormattable { /// /// The first x value. /// - public readonly float X1; //Note: do not reorder this field, unless you know what you are doing. + [FieldOffset(0)] + public readonly float X1; /// /// The first y value. /// - public readonly float Y1; //Note: do not reorder this field, unless you know what you are doing. + [FieldOffset(4)] + public readonly float Y1; + + /// + /// The first xy. + /// + [FieldOffset(0)] + public readonly Vector2 XY1; /// /// The second y value. /// - public readonly float X2; //Note: do not reorder this field, unless you know what you are doing. + [FieldOffset(8)] + public readonly float X2; /// /// The second x value. /// - public readonly float Y2; //Note: do not reorder this field, unless you know what you are doing. + [FieldOffset(12)] + public readonly float Y2; + + /// + /// The second xy. + /// + [FieldOffset(8)] + public readonly Vector2 XY2; /// /// The third x value. /// - public readonly float X3; //Note: do not reorder this field, unless you know what you are doing. + [FieldOffset(16)] + public readonly float X3; /// /// The third y value. /// - public readonly float Y3; //Note: do not reorder this field, unless you know what you are doing. + [FieldOffset(20)] + public readonly float Y3; + /// + /// The third xy. + /// + [FieldOffset(16)] + public readonly Vector2 XY3; + /// /// Initializes a new instance of the struct. /// @@ -62,7 +86,7 @@ namespace Exomia.Framework.Mathematics /// The second y value. /// The third x value. /// The third y value. - public Triangle2(float x1, float y1, float x2, float y2, float x3, float y3) + public Triangle2(float x1, float y1, float x2, float y2, float x3, float y3) : this() { X1 = x1; Y1 = y1; @@ -75,20 +99,25 @@ public Triangle2(float x1, float y1, float x2, float y2, float x3, float y3) /// /// Initializes a new instance of the struct. /// - /// The VectorI2 to process. - /// The VectorI2 to process. - /// The VectorI2 to process. - public Triangle2(VectorI2 a, VectorI2 b, VectorI2 c) + /// The to process. + /// The to process. + /// The to process. + public Triangle2(in VectorI2 a, in VectorI2 b, in VectorI2 c) : this(a.X, a.Y, b.X, b.Y, c.X, c.Y) { } /// /// Initializes a new instance of the struct. /// - /// The Vector2 to process. - /// The Vector2 to process. - /// The Vector2 to process. - public Triangle2(Vector2 a, Vector2 b, Vector2 c) - : this(a.X, a.Y, b.X, b.Y, c.X, c.Y) { } + /// The to process. + /// The to process. + /// The to process. + public Triangle2(in Vector2 a, in Vector2 b, in Vector2 c) + : this() + { + XY1 = a; + XY2 = b; + XY3 = c; + } /// /// Determines whether the specified is equal to this instance. From 6e6c787395412c7a231da3e0589562a2ace5b96a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20B=C3=A4tz?= Date: Mon, 23 Nov 2020 14:49:43 +0100 Subject: [PATCH 44/44] netstandard2.1 & netstandard2.0 update - removed stringbuilder support for netstandard2.0 - added readonlyspan support for netstandard2.1 --- .../Exomia.Framework.Example.Canvas.csproj | 2 +- .../Exomia.Framework.Example.Canvas/MyGame.cs | 98 +- src/Exomia.Framework/Exomia.Framework.csproj | 24 +- src/Exomia.Framework/Graphics/Canvas.Arc.cs | 94 +- src/Exomia.Framework/Graphics/Canvas.Line.cs | 82 +- .../Graphics/Canvas.Polygon.cs | 153 +-- .../Graphics/Canvas.Rectangle.cs | 84 +- .../Graphics/Canvas.SpriteFont.cs | 184 ++-- .../Graphics/Canvas.Structs.cs | 13 +- .../Graphics/Canvas.Texture.cs | 44 +- .../Graphics/Canvas.Triangle.cs | 38 +- .../Graphics/SpriteBatch.SpriteFont.cs | 296 +++--- .../Graphics/SpriteFont.Glyph.cs | 50 + .../Graphics/SpriteFont.Kerning.cs | 39 + .../Graphics/SpriteFont.Methods.cs | 531 +++++++++++ src/Exomia.Framework/Graphics/SpriteFont.cs | 881 +----------------- src/Exomia.Framework/Mathematics/Line2.cs | 35 +- src/Exomia.Framework/Mathematics/Triangle2.cs | 15 +- src/Exomia.Framework/Win32/Mem.cs | 9 +- 19 files changed, 1149 insertions(+), 1523 deletions(-) create mode 100644 src/Exomia.Framework/Graphics/SpriteFont.Glyph.cs create mode 100644 src/Exomia.Framework/Graphics/SpriteFont.Kerning.cs create mode 100644 src/Exomia.Framework/Graphics/SpriteFont.Methods.cs diff --git a/examples/Exomia.Framework.Example.Canvas/Exomia.Framework.Example.Canvas.csproj b/examples/Exomia.Framework.Example.Canvas/Exomia.Framework.Example.Canvas.csproj index 8e58dfff..633e5ff7 100644 --- a/examples/Exomia.Framework.Example.Canvas/Exomia.Framework.Example.Canvas.csproj +++ b/examples/Exomia.Framework.Example.Canvas/Exomia.Framework.Example.Canvas.csproj @@ -1,7 +1,7 @@  Exe - net48 + netcoreapp3.1 AnyCPU;x64;x86 8.0 enable diff --git a/examples/Exomia.Framework.Example.Canvas/MyGame.cs b/examples/Exomia.Framework.Example.Canvas/MyGame.cs index 6a75585c..4e718373 100644 --- a/examples/Exomia.Framework.Example.Canvas/MyGame.cs +++ b/examples/Exomia.Framework.Example.Canvas/MyGame.cs @@ -12,6 +12,7 @@ using Exomia.Framework.Game; using Exomia.Framework.Graphics; using Exomia.Framework.Mathematics; +using Exomia.Framework.Resources; using SharpDX; namespace Exomia.Framework.Example.Canvas @@ -34,6 +35,28 @@ sealed class MyGame : Game.Game private float k; + private readonly Vector2[] polyA = + { + new Vector2(550, 250), new Vector2(550, 120), new Vector2(650, 320), new Vector2(520, 250) + }; + + private readonly Vector2[] polyB = + { + new Vector2(450, 400), new Vector2(700, 420), new Vector2(700, 450), new Vector2(600, 480), + new Vector2(600, 600) + }; + + private readonly Vector2[] polyC = + { + new Vector2(400, 600), new Vector2(550, 620), new Vector2(650, 820), new Vector2(520, 750) + }; + + private readonly Vector2[] polyD = + { + new Vector2(600, 600), new Vector2(650, 610), new Vector2(650, 720), new Vector2(450, 750), + new Vector2(400, 630) + }; + /// /// Initializes a new instance of the class. /// @@ -88,8 +111,8 @@ protected override void OnLoadContent() _texture = Content.Load("logo1.jpg"); _texture2 = Content.Load("logo2.png"); - _spriteFont1_12Px = Content.Load(Resources.Fonts.ARIAL_12_PX, true); - _spriteFont1_24Px = Content.Load(Resources.Fonts.ARIAL_24_PX, true); + _spriteFont1_12Px = Content.Load(Fonts.ARIAL_12_PX, true); + _spriteFont1_24Px = Content.Load(Fonts.ARIAL_24_PX, true); } /// @@ -122,13 +145,13 @@ protected override void Draw(GameTime gameTime) k += gameTime.DeltaTimeS / 2; - _canvas.DrawFillTriangle(new Triangle2(100, 50, 150, 100, 50, 100), Color.Red, 0, Vector2.Zero, 1.0f); - _canvas.DrawTriangle(new Triangle2(100, 50, 150, 100, 50, 100), Color.Green, 5.0f, 0, Vector2.Zero, 1.0f); + _canvas.DrawFillTriangle(new Triangle2(100, 250, 150, 300, 50, 300), Color.Red, 0, Vector2.Zero, 1.0f); + _canvas.DrawTriangle(new Triangle2(100, 250, 150, 300, 50, 300), Color.Green, 5.0f, 0, Vector2.Zero, 1.0f); _canvas.DrawFillTriangle( - new Triangle2(100, 50, 150, 100, 50, 100), Color.Yellow, k, new Vector2(100, 50), 1.0f); + new Triangle2(100, 250, 150, 300, 50, 300), Color.Yellow, k, new Vector2(100, 250), 1.0f); _canvas.DrawTriangle( - new Triangle2(100, 50, 150, 100, 50, 100), Color.Green, 5.0f, k, new Vector2(100, 50), 1.0f); + new Triangle2(100, 250, 150, 300, 50, 300), Color.Green, 5.0f, k, new Vector2(100, 250), 1.0f); _canvas.DrawFillRectangle(new RectangleF(200, 200, 100, 50), Color.Red, 0, Vector2.Zero, 1.0f); _canvas.DrawRectangle(new RectangleF(200, 200, 100, 50), Color.Green, 5.0f, 0, Vector2.Zero, 1.0f); @@ -136,51 +159,28 @@ protected override void Draw(GameTime gameTime) _canvas.DrawFillRectangle(new RectangleF(200, 200, 100, 50), Color.Yellow, k, new Vector2(200, 200), 1.0f); _canvas.DrawRectangle(new RectangleF(200, 200, 100, 50), Color.Green, 5.0f, k, new Vector2(200, 200), 1.0f); - _canvas.DrawLine(new Line2(300, 400, 345, 400), Color.Red, 5.0f, 1.0f); - _canvas.DrawLine(new Line2(400, 400, 450, 450), Color.Red, 5.0f, 1.0f); - - _canvas.DrawLine(new Line2(300, 450, 345, 450), Color.Yellow, 5.0f, 1.0f); - _canvas.DrawLine(new Line2(400, 450, 450, 400), Color.Yellow, 5.0f, 1.0f); - - _canvas.DrawFillPolygon( - new[] { new Vector2(550, 250), new Vector2(550, 120), new Vector2(650, 320), new Vector2(520, 250) }, - Color.Red, 0.0f, Vector2.Zero, 1.0f); - _canvas.DrawPolygon( - new[] { new Vector2(550, 250), new Vector2(550, 120), new Vector2(650, 320), new Vector2(520, 250) }, - Color.Green, 5.0f, 0.0f, Vector2.Zero, 1.0f); - - _canvas.DrawFillPolygon( - new[] { new Vector2(450, 400), new Vector2(700, 420), new Vector2(700, 450), new Vector2(600, 480), new Vector2(600, 600) }, - Color.Red, 0.0f, Vector2.Zero, 1.0f); - _canvas.DrawPolygon( - new[] { new Vector2(450, 400), new Vector2(700, 420), new Vector2(700, 450), new Vector2(600, 480), new Vector2(600, 600) }, - Color.Green, 5.0f, 0.0f, Vector2.Zero, 1.0f); - - _canvas.DrawFillPolygon( - new[] { new Vector2(400, 600), new Vector2(550, 620), new Vector2(650, 820), new Vector2(520, 750) }, - Color.Yellow, k, new Vector2(400, 600), 1.0f); - _canvas.DrawPolygon( - new[] { new Vector2(400, 600), new Vector2(550, 620), new Vector2(650, 820), new Vector2(520, 750) }, - Color.Green, 5.0f, k, new Vector2(400, 600), 1.0f); - - _canvas.DrawFillPolygon( - new[] - { - new Vector2(600, 600), new Vector2(650, 610), new Vector2(650, 720), new Vector2(450, 750), - new Vector2(400, 630) - }, Color.Red, 0.0f, Vector2.Zero, 1.0f); + _canvas.DrawLine(new Line2(300, 400, 345, 400), Color.Red, 5.0f, 1.0f, 0, Vector2.Zero); + _canvas.DrawLine(new Line2(400, 400, 450, 450), Color.Red, 5.0f, 1.0f, k, new Vector2(425, 425)); - _canvas.DrawPolygon( - new[] - { - new Vector2(600, 600), new Vector2(650, 610), new Vector2(650, 720), new Vector2(450, 750), - new Vector2(400, 630) - }, Color.Yellow, 5.0f, 0.0f, Vector2.Zero, 1.0f); + _canvas.DrawLine(new Line2(300, 450, 345, 450), Color.Yellow, 5.0f, 1.0f, 0, Vector2.Zero); + _canvas.DrawLine(new Line2(400, 450, 450, 400), Color.Yellow, 5.0f, 1.0f, k, new Vector2(425, 425)); + + _canvas.DrawFillPolygon(polyA, Color.Red, 0.0f, Vector2.Zero, 1.0f); + _canvas.DrawPolygon(polyA, Color.Green, 5.0f, 0.0f, Vector2.Zero, 1.0f); + + _canvas.DrawFillPolygon(polyB, Color.Red, 0.0f, Vector2.Zero, 1.0f); + _canvas.DrawPolygon(polyB, Color.Green, 5.0f, 0.0f, Vector2.Zero, 1.0f); + + _canvas.DrawFillPolygon(polyC, Color.Yellow, k, new Vector2(400, 600), 1.0f); + _canvas.DrawPolygon(polyC, Color.Green, 5.0f, k, new Vector2(400, 600), 1.0f); + + _canvas.DrawFillPolygon(polyD, Color.Red, 0.0f, Vector2.Zero, 1.0f); + _canvas.DrawPolygon(polyD, Color.Yellow, 5.0f, 0.0f, Vector2.Zero, 1.0f); Vector2 center = new Vector2(800, 400); _canvas.DrawRectangle( - new RectangleF(center.X - 100, center.Y - 100, 200, 200), Color.Green, 2, 0, Vector2.Zero, 1.0f); + new RectangleF(center.X - 100, center.Y - 100, 200, 200), Color.Green, 2, 0, Vector2.Zero, 1.0f); _canvas.DrawFillArc(new Arc2(center, 100f), Color.Black, 0, center, 1.0f); float l = 20; @@ -269,9 +269,9 @@ protected override void Draw(GameTime gameTime) _canvas.Draw(_texture, new RectangleF(1100, 50, 200, 200), Color.White); _canvas.Draw(_texture2, new RectangleF(1350, 50, 200, 200), Color.White); - - _canvas.DrawText(_spriteFont1_12Px, "This is the canvas example.", new Vector2(450, 50), Color.Black); - _canvas.DrawText(_spriteFont1_24Px, "This is the canvas example.", new Vector2(450, 65), Color.Black); + + _canvas.DrawText(_spriteFont1_12Px, "This is the canvas example.", new Vector2(450, 50), Color.Black, 0); + _canvas.DrawText(_spriteFont1_24Px, "This is the canvas example.", new Vector2(450, 65), Color.Black, k, new Vector2(450, 65), 1.0f, TextureEffects.None); _canvas.End(); diff --git a/src/Exomia.Framework/Exomia.Framework.csproj b/src/Exomia.Framework/Exomia.Framework.csproj index 5d66170a..94b6dfea 100644 --- a/src/Exomia.Framework/Exomia.Framework.csproj +++ b/src/Exomia.Framework/Exomia.Framework.csproj @@ -161,19 +161,19 @@ - - - - - - - - - - - + + + + + + + + + + + - + diff --git a/src/Exomia.Framework/Graphics/Canvas.Arc.cs b/src/Exomia.Framework/Graphics/Canvas.Arc.cs index 1a34a297..e0881c96 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Arc.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Arc.cs @@ -65,7 +65,11 @@ public void DrawArc(in Arc2 arc, // ReSharper disable once CompareOfFloatsByEqualityOperator if (arc.Start == arc.End) { return; } - Color scaledColor = color * opacity; + Vector4 scaledColor; + scaledColor.X = color.R * opacity; + scaledColor.Y = color.G * opacity; + scaledColor.Z = color.B * opacity; + scaledColor.W = color.A * opacity; float r = arc.Radius; float rh = (arc.Radius - lineWidth) * 0.685f; @@ -197,7 +201,11 @@ public void DrawFillArc(in Arc2 arc, // ReSharper disable once CompareOfFloatsByEqualityOperator if (arc.Start == arc.End) { return; } - Color scaledColor = color * opacity; + Vector4 scaledColor; + scaledColor.X = color.R * opacity; + scaledColor.Y = color.G * opacity; + scaledColor.Z = color.B * opacity; + scaledColor.W = color.A * opacity; float u = arc.Start; float v = arc.End; @@ -270,33 +278,27 @@ public void DrawFillArc(in Arc2 arc, Vector2 corner = s_arcCornerOffsets[i]; - vertex->X = x + (corner.X * arc.Radius); - vertex->Y = y + (corner.Y * arc.Radius); - vertex->Z = x; - vertex->W = y; - - vertex->R = scaledColor.R; - vertex->G = scaledColor.G; - vertex->B = scaledColor.B; - vertex->A = scaledColor.A; - - vertex->U = u; - vertex->V = v; - - vertex->M = m; - vertex->O = arc.Radius; + vertex->X = x + (corner.X * arc.Radius); + vertex->Y = y + (corner.Y * arc.Radius); + vertex->Z = x; + vertex->W = y; + vertex->RGBA = scaledColor; + vertex->U = u; + vertex->V = v; + vertex->M = m; + vertex->O = arc.Radius; } } - private static void DrawArcRect(Item* ptr, - in Line2 lineA, - in Line2 lineB, - in Color c, - float z, - float w, - float u, - float v, - float o) + private static void DrawArcRect(Item* ptr, + in Line2 lineA, + in Line2 lineB, + in Vector4 c, + float z, + float w, + float u, + float v, + float o) { // ReSharper disable CompareOfFloatsByEqualityOperator float m = u == 0.0f && v == MathUtil.TwoPi ? BORDER_CIRCLE_MODE : BORDER_CIRCLE_ARC_MODE; @@ -312,19 +314,13 @@ private static void DrawArcRect(Item* ptr, vertex->XY = *(lf + i); } - vertex->Z = z; - vertex->W = w; - - vertex->R = c.R; - vertex->G = c.G; - vertex->B = c.B; - vertex->A = c.A; - - vertex->U = u; - vertex->V = v; - - vertex->M = m; - vertex->O = o; + vertex->Z = z; + vertex->W = w; + vertex->RGBA = c; + vertex->U = u; + vertex->V = v; + vertex->M = m; + vertex->O = o; } for (int i = 1; i >= 0; i--) @@ -336,19 +332,13 @@ private static void DrawArcRect(Item* ptr, vertex->XY = *(lf + i); } - vertex->Z = z; - vertex->W = w; - - vertex->R = c.R; - vertex->G = c.G; - vertex->B = c.B; - vertex->A = c.A; - - vertex->U = u; - vertex->V = v; - - vertex->M = m; - vertex->O = o; + vertex->Z = z; + vertex->W = w; + vertex->RGBA = c; + vertex->U = u; + vertex->V = v; + vertex->M = m; + vertex->O = o; } } } diff --git a/src/Exomia.Framework/Graphics/Canvas.Line.cs b/src/Exomia.Framework/Graphics/Canvas.Line.cs index 3ab66e2c..5cd0e4bf 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Line.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Line.cs @@ -25,6 +25,8 @@ public sealed unsafe partial class Canvas /// The color. /// The width of the line. /// The opacity. + /// The rotation. + /// The origin. /// (Optional) The length factor. [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawLine(in Vector2 point1, @@ -32,9 +34,11 @@ public void DrawLine(in Vector2 point1, in Color color, float lineWidth, float opacity, + float rotation, + in Vector2 origin, float lengthFactor = 1.0f) { - DrawLine(new Line2(in point1, in point2), color, lineWidth, opacity, lengthFactor); + DrawLine(new Line2(in point1, in point2), color, lineWidth, opacity, rotation, origin, lengthFactor); } /// @@ -44,17 +48,27 @@ public void DrawLine(in Vector2 point1, /// The color. /// The width of the line. /// The opacity. + /// The rotation. + /// The origin. /// (Optional) The length factor. - public void DrawLine(in Line2 line, - in Color color, - float lineWidth, - float opacity, - float lengthFactor = 1.0f) + public void DrawLine(in Line2 line, + in Color color, + float lineWidth, + float opacity, + float rotation, + in Vector2 origin, + float lengthFactor = 1.0f) { - Color scaledColor = color * opacity; - - float dx = line.X2 - line.X1; - float dy = line.Y2 - line.Y1; + Line2 l = rotation == 0.0f ? line : Line2.RotateAround(in line, rotation, origin); + + Vector4 scaledColor; + scaledColor.X = color.R * opacity; + scaledColor.Y = color.G * opacity; + scaledColor.Z = color.B * opacity; + scaledColor.W = color.A * opacity; + + float dx = l.X2 - l.X1; + float dy = l.Y2 - l.Y1; double dl = Math.Sqrt((dx * dx) + (dy * dy)); float nx = (float)((dy / dl) * lineWidth); @@ -63,49 +77,29 @@ public void DrawLine(in Line2 line, VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)Reserve(1); // p1 - vertex->XY = line.XY1; - - vertex->R = scaledColor.R; - vertex->G = scaledColor.G; - vertex->B = scaledColor.B; - vertex->A = scaledColor.A; - - vertex->M = COLOR_MODE; + vertex->XY = l.XY1; + vertex->RGBA = scaledColor; + vertex->M = COLOR_MODE; vertex++; // p2 - vertex->XY = line.XY2; - - vertex->R = scaledColor.R; - vertex->G = scaledColor.G; - vertex->B = scaledColor.B; - vertex->A = scaledColor.A; - - vertex->M = COLOR_MODE; + vertex->XY = l.XY2; + vertex->RGBA = scaledColor; + vertex->M = COLOR_MODE; vertex++; // p2' - vertex->X = line.X2 - nx; - vertex->Y = line.Y2 + ny; - - vertex->R = scaledColor.R; - vertex->G = scaledColor.G; - vertex->B = scaledColor.B; - vertex->A = scaledColor.A; - - vertex->M = COLOR_MODE; + vertex->X = l.X2 - nx; + vertex->Y = l.Y2 + ny; + vertex->RGBA = scaledColor; + vertex->M = COLOR_MODE; vertex++; // p1' - vertex->X = line.X1 - nx; - vertex->Y = line.Y1 + ny; - - vertex->R = scaledColor.R; - vertex->G = scaledColor.G; - vertex->B = scaledColor.B; - vertex->A = scaledColor.A; - - vertex->M = COLOR_MODE; + vertex->X = l.X1 - nx; + vertex->Y = l.Y1 + ny; + vertex->RGBA = scaledColor; + vertex->M = COLOR_MODE; } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.Polygon.cs b/src/Exomia.Framework/Graphics/Canvas.Polygon.cs index 60c7ed0b..21857be5 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Polygon.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Polygon.cs @@ -9,7 +9,6 @@ #endregion using System; -using System.Collections.Generic; using Exomia.Framework.Mathematics; using SharpDX; @@ -36,27 +35,33 @@ public void DrawPolygon(Vector2[] vertices, { if (vertices.Length < 2) { throw new ArgumentOutOfRangeException(nameof(vertices.Length)); } - Color scaledColor = color * opacity; + Vector4 scaledColor; + scaledColor.X = color.R * opacity; + scaledColor.Y = color.G * opacity; + scaledColor.Z = color.B * opacity; + scaledColor.W = color.A * opacity; Item* ptr = Reserve(vertices.Length); if (rotation != 0.0f) { - double cos = Math.Cos(rotation); - double sin = Math.Sin(rotation); + Vector2[] vs = new Vector2[vertices.Length]; + double cos = Math.Cos(rotation); + double sin = Math.Sin(rotation); for (int i = 0; i < vertices.Length; i++) { ref Vector2 v = ref vertices[i]; - float x = v.X - origin.X; - float y = v.Y - origin.Y; - v.X = (float)(((cos * x) - (sin * y)) + origin.X); - v.Y = (float)((sin * x) + (cos * y) + origin.Y); + float x = v.X - origin.X; + float y = v.Y - origin.Y; + vs[i] = new Vector2( + (float)(((cos * x) - (sin * y)) + origin.X), (float)((sin * x) + (cos * y) + origin.Y)); } + vertices = vs; } - + Line2 previous = Line2.CreateWithPerpendicular( ref vertices[vertices.Length - 1], ref vertices[0], lineWidth, out Line2 perpendicularPrevious); - + Line2 current = Line2.CreateWithPerpendicular( ref vertices[0], ref vertices[1], lineWidth, out Line2 perpendicularCurrent); @@ -103,7 +108,7 @@ public void DrawPolygon(Vector2[] vertices, /// Thrown when one or more arguments are outside the required range. /// /// Attention: - /// - The must be declared in a clockwise orientation. + /// - The must be declared in a clockwise orientation. /// - The triangulation used to fill the polygon may not work for concave polygons at the moment! /// - Complex polygons may not work at all! /// @@ -115,72 +120,90 @@ public void DrawFillPolygon(Vector2[] vertices, { if (vertices.Length < 3) { throw new ArgumentOutOfRangeException(nameof(vertices.Length)); } - Color scaledColor = color * opacity; - - if (rotation != 0.0f) - { - double cos = Math.Cos(rotation); - double sin = Math.Sin(rotation); - for (int i = 0; i < vertices.Length; i++) - { - float x = vertices[i].X - origin.X; - float y = vertices[i].Y - origin.Y; - vertices[i] = new Vector2( - (float)(((cos * x) - (sin * y)) + origin.X), - (float)((sin * x) + (cos * y) + origin.Y)); - } - } + Vector4 scaledColor; + scaledColor.X = color.R * opacity; + scaledColor.Y = color.G * opacity; + scaledColor.Z = color.B * opacity; + scaledColor.W = color.A * opacity; VertexPositionColorTextureMode* vertex = (VertexPositionColorTextureMode*)Reserve(vertices.Length - 2); - for (int i = 1; i < vertices.Length - 1; i += 2) + if (rotation == 0.0f) { - vertex->XY = vertices[0]; - - vertex->R = scaledColor.R; - vertex->G = scaledColor.G; - vertex->B = scaledColor.B; - vertex->A = scaledColor.A; - - vertex->M = COLOR_MODE; - vertex++; - - vertex->XY = vertices[i]; - - vertex->R = scaledColor.R; - vertex->G = scaledColor.G; - vertex->B = scaledColor.B; - vertex->A = scaledColor.A; - - vertex->M = COLOR_MODE; - vertex++; + for (int i = 1; i < vertices.Length - 1; i += 2) + { + vertex->XY = vertices[0]; + vertex->RGBA = scaledColor; + vertex->M = COLOR_MODE; + vertex++; - vertex->XY = vertices[i + 1]; + vertex->XY = vertices[i]; + vertex->RGBA = scaledColor; + vertex->M = COLOR_MODE; + vertex++; - vertex->R = scaledColor.R; - vertex->G = scaledColor.G; - vertex->B = scaledColor.B; - vertex->A = scaledColor.A; + vertex->XY = vertices[i + 1]; + vertex->RGBA = scaledColor; + vertex->M = COLOR_MODE; + vertex++; - vertex->M = COLOR_MODE; - vertex++; + if (i + 2 < vertices.Length) + { + vertex->XY = vertices[i + 2]; + vertex->RGBA = scaledColor; + vertex->M = COLOR_MODE; + vertex++; + } + else + { + // INFO: currently we need 4 vertices (rectangle) and can't draw triangles directly so just use the first vertex as the last vertex too. + *vertex = *(vertex - 3); + } + } + } + else + { + Vector2* vs = stackalloc Vector2[vertices.Length]; + double cos = Math.Cos(rotation); + double sin = Math.Sin(rotation); + for (int i = 0; i < vertices.Length; i++) + { + ref Vector2 v = ref vertices[i]; + float x = v.X - origin.X; + float y = v.Y - origin.Y; + *(vs + i) = new Vector2( + (float)(((cos * x) - (sin * y)) + origin.X), (float)((sin * x) + (cos * y) + origin.Y)); + } - if (i + 2 < vertices.Length) + for (int i = 1; i < vertices.Length - 1; i += 2) { - vertex->XY = vertices[i + 2]; + vertex->XY = *vs; + vertex->RGBA = scaledColor; + vertex->M = COLOR_MODE; + vertex++; - vertex->R = scaledColor.R; - vertex->G = scaledColor.G; - vertex->B = scaledColor.B; - vertex->A = scaledColor.A; + vertex->XY = *(vs + i); + vertex->RGBA = scaledColor; + vertex->M = COLOR_MODE; + vertex++; - vertex->M = COLOR_MODE; + vertex->XY = *(vs + i + 1); + vertex->RGBA = scaledColor; + vertex->M = COLOR_MODE; vertex++; - } - else - { - // INFO: currently we need 4 vertices (rectangle) and can't draw triangles directly so just use the first vertex as the last vertex too. - *vertex = *(vertex - 3); + + if (i + 2 < vertices.Length) + { + vertex->XY = *(vs + i + 2); + vertex->RGBA = scaledColor; + vertex->M = COLOR_MODE; + vertex++; + } + else + { + // INFO: currently we need 4 vertices (rectangle) and can't draw triangles directly so just use the first vertex as the last vertex too. + *vertex = *(vertex - 3); + } } } } diff --git a/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs b/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs index 97770dce..afca8d24 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Rectangle.cs @@ -35,7 +35,11 @@ public void DrawRectangle(in RectangleF destination, in Vector2 origin, float opacity) { - Color scaledColor = color * opacity; + Vector4 scaledColor; + scaledColor.X = color.R * opacity; + scaledColor.Y = color.G * opacity; + scaledColor.Z = color.B * opacity; + scaledColor.W = color.A * opacity; Vector2 tl = new Vector2(destination.Left + lineWidth, destination.Top + lineWidth); Vector2 tr = new Vector2(destination.Right - lineWidth, destination.Top + lineWidth); @@ -140,7 +144,11 @@ public void DrawFillRectangle(in RectangleF destination, in Vector2 origin, float opacity) { - Color scaledColor = color * opacity; + Vector4 scaledColor; + scaledColor.X = color.R * opacity; + scaledColor.Y = color.G * opacity; + scaledColor.Z = color.B * opacity; + scaledColor.W = color.A * opacity; Item* ptr = Reserve(1); @@ -152,15 +160,10 @@ public void DrawFillRectangle(in RectangleF destination, Vector2 corner = s_rectangleCornerOffsets[j]; - vertex->X = destination.X + (corner.X * destination.Width); - vertex->Y = destination.Y + (corner.Y * destination.Height); - - vertex->R = scaledColor.R; - vertex->G = scaledColor.G; - vertex->B = scaledColor.B; - vertex->A = scaledColor.A; - - vertex->M = COLOR_MODE; + vertex->X = destination.X + (corner.X * destination.Width); + vertex->Y = destination.Y + (corner.Y * destination.Height); + vertex->RGBA = scaledColor; + vertex->M = COLOR_MODE; } } else @@ -176,60 +179,35 @@ public void DrawFillRectangle(in RectangleF destination, float posX = (destination.X - origin.X) + (corner.X * destination.Width); float posY = (destination.Y - origin.Y) + (corner.Y * destination.Height); - vertex->X = (float)((origin.X + (posX * cos)) - (posY * sin)); - vertex->Y = (float)(origin.Y + (posX * sin) + (posY * cos)); - - vertex->R = scaledColor.R; - vertex->G = scaledColor.G; - vertex->B = scaledColor.B; - vertex->A = scaledColor.A; - - vertex->M = COLOR_MODE; + vertex->X = (float)((origin.X + (posX * cos)) - (posY * sin)); + vertex->Y = (float)(origin.Y + (posX * sin) + (posY * cos)); + vertex->RGBA = scaledColor; + vertex->M = COLOR_MODE; } } } - private static void DrawRect(Item* ptr, in Line2 lineA, in Line2 lineB, in Color c) + private static void DrawRect(Item* ptr, in Line2 lineA, in Line2 lineB, in Vector4 c) { // p1 - ptr->V1.XY = lineA.XY1; - - ptr->V1.R = c.R; - ptr->V1.G = c.G; - ptr->V1.B = c.B; - ptr->V1.A = c.A; - - ptr->V1.M = COLOR_MODE; + ptr->V1.XY = lineA.XY1; + ptr->V1.RGBA = c; + ptr->V1.M = COLOR_MODE; // p2 - ptr->V2.XY = lineA.XY2; - - ptr->V2.R = c.R; - ptr->V2.G = c.G; - ptr->V2.B = c.B; - ptr->V2.A = c.A; - - ptr->V2.M = COLOR_MODE; + ptr->V2.XY = lineA.XY2; + ptr->V2.RGBA = c; + ptr->V2.M = COLOR_MODE; // p2' - ptr->V3.XY = lineB.XY2; - - ptr->V3.R = c.R; - ptr->V3.G = c.G; - ptr->V3.B = c.B; - ptr->V3.A = c.A; - - ptr->V3.M = COLOR_MODE; + ptr->V3.XY = lineB.XY2; + ptr->V3.RGBA = c; + ptr->V3.M = COLOR_MODE; // p1' - ptr->V4.XY = lineB.XY1; - - ptr->V4.R = c.R; - ptr->V4.G = c.G; - ptr->V4.B = c.B; - ptr->V4.A = c.A; - - ptr->V4.M = COLOR_MODE; + ptr->V4.XY = lineB.XY1; + ptr->V4.RGBA = c; + ptr->V4.M = COLOR_MODE; } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.SpriteFont.cs b/src/Exomia.Framework/Graphics/Canvas.SpriteFont.cs index 3793a460..abd398cf 100644 --- a/src/Exomia.Framework/Graphics/Canvas.SpriteFont.cs +++ b/src/Exomia.Framework/Graphics/Canvas.SpriteFont.cs @@ -9,9 +9,13 @@ #endregion using System.Runtime.CompilerServices; -using System.Text; using SharpDX; +#if NETSTANDARD2_1 +using System; + +#endif + namespace Exomia.Framework.Graphics { public sealed partial class Canvas @@ -23,8 +27,13 @@ public sealed partial class Canvas /// The text. /// The position. /// The color. +#if NETSTANDARD2_1 + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, ReadOnlySpan text, in Vector2 position, in Color color) +#else [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, string text, in Vector2 position, in Color color) +#endif { font.Draw(DrawTextInternal, text, position, color, 0f, Vector2.Zero, 1.0f, TextureEffects.None, 0f); } @@ -37,8 +46,17 @@ public void DrawText(SpriteFont font, string text, in Vector2 position, in Color /// The position. /// The color. /// The rotation. +#if NETSTANDARD2_1 + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + ReadOnlySpan text, + in Vector2 position, + in Color color, + float rotation) +#else [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, string text, in Vector2 position, in Color color, float rotation) +#endif { font.Draw(DrawTextInternal, text, position, color, rotation, Vector2.Zero, 1.0f, TextureEffects.None, 0f); } @@ -54,6 +72,17 @@ public void DrawText(SpriteFont font, string text, in Vector2 position, in Color /// The origin. /// The opacity. /// The effects. +#if NETSTANDARD2_1 + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + ReadOnlySpan text, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects) +#else [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, string text, @@ -63,6 +92,7 @@ public void DrawText(SpriteFont font, in Vector2 origin, float opacity, TextureEffects effects) +#endif { font.Draw(DrawTextInternal, text, position, color, rotation, origin, opacity, effects, 0f); } @@ -80,114 +110,31 @@ public void DrawText(SpriteFont font, /// The origin. /// The opacity. /// The effects. +#if NETSTANDARD2_1 [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - string text, - int start, - int end, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - TextureEffects effects) - { - font.Draw(DrawTextInternal, text, start, end, position, color, rotation, origin, opacity, effects, 0f); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The start. - /// The end. - /// The position. - /// The dimension. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. + public void DrawText(SpriteFont font, + ReadOnlySpan text, + int start, + int end, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects) +#else [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, string text, int start, int end, in Vector2 position, - in Size2F dimension, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - TextureEffects effects) - { - font.Draw( - DrawTextInternal, text, start, end, position, dimension, color, rotation, origin, opacity, effects, 0f); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, in Color color, float rotation) - { - font.Draw(DrawTextInternal, text, position, color, rotation, Vector2.Zero, 1.0f, TextureEffects.None, 0f); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - StringBuilder text, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - TextureEffects effects) - { - font.Draw(DrawTextInternal, text, position, color, rotation, origin, opacity, effects, 0f); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The start. - /// The end. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - StringBuilder text, - int start, - int end, - in Vector2 position, in Color color, float rotation, in Vector2 origin, float opacity, TextureEffects effects) +#endif { font.Draw(DrawTextInternal, text, start, end, position, color, rotation, origin, opacity, effects, 0f); } @@ -206,9 +153,23 @@ public void DrawText(SpriteFont font, /// The origin. /// The opacity. /// The effects. +#if NETSTANDARD2_1 + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + ReadOnlySpan text, + int start, + int end, + in Vector2 position, + in Size2F dimension, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects) +#else [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, - StringBuilder text, + string text, int start, int end, in Vector2 position, @@ -218,24 +179,12 @@ public void DrawText(SpriteFont font, in Vector2 origin, float opacity, TextureEffects effects) +#endif { font.Draw( DrawTextInternal, text, start, end, position, dimension, color, rotation, origin, opacity, effects, 0f); } - /// - /// Draw text internal. - /// - /// The texture. - /// The position. - /// The source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The scale. - /// The opacity. - /// The effects. - /// The depth of the layer. [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void DrawTextInternal(Texture texture, in Vector2 position, @@ -252,18 +201,5 @@ internal void DrawTextInternal(Texture texture, texture, new RectangleF(position.X, position.Y, scale, scale), true, sourceRectangle, color, rotation, origin, opacity, effects, FONT_TEXTURE_MODE); } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, in Color color) - { - font.Draw(DrawTextInternal, text, position, color, 0f, Vector2.Zero, 1.0f, TextureEffects.None, 0f); - } } } \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/Canvas.Structs.cs b/src/Exomia.Framework/Graphics/Canvas.Structs.cs index 04fb31f7..1e795fd1 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Structs.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Structs.cs @@ -39,7 +39,7 @@ private struct VertexPositionColorTextureMode [FieldOffset(4)] public float Y; - + [FieldOffset(0)] public Vector2 XY; @@ -53,16 +53,19 @@ private struct VertexPositionColorTextureMode public long ZW; [FieldOffset(16)] - public float R; + public readonly float R; [FieldOffset(20)] - public float G; + public readonly float G; [FieldOffset(24)] - public float B; + public readonly float B; [FieldOffset(28)] - public float A; + public readonly float A; + + [FieldOffset(16)] + public Vector4 RGBA; [FieldOffset(32)] public float U; diff --git a/src/Exomia.Framework/Graphics/Canvas.Texture.cs b/src/Exomia.Framework/Graphics/Canvas.Texture.cs index f9db2dbe..6368ae73 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Texture.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Texture.cs @@ -192,7 +192,11 @@ private void DrawTexture(Texture texture, } } - Color scaledColor = color * opacity; + Vector4 scaledColor; + scaledColor.X = color.R * opacity; + scaledColor.Y = color.G * opacity; + scaledColor.Z = color.B * opacity; + scaledColor.W = color.A * opacity; Rectangle s = sourceRectangle ?? new Rectangle(0, 0, texture.Width, texture.Height); RectangleF d = destination; @@ -226,18 +230,13 @@ private void DrawTexture(Texture texture, Vector2 corner = s_rectangleCornerOffsets[j]; - vertex->X = d.X + ((corner.X - origin.X) * d.Width); - vertex->Y = d.Y + ((corner.Y - origin.Y) * d.Height); - vertex->ZW = tp; - - vertex->R = scaledColor.R; - vertex->G = scaledColor.G; - vertex->B = scaledColor.B; - vertex->A = scaledColor.A; - - corner = s_rectangleCornerOffsets[j ^ (int)effects]; - vertex->U = (s.X + (corner.X * s.Width)) * deltaX; - vertex->V = (s.Y + (corner.Y * s.Height)) * deltaY; + vertex->X = d.X + ((corner.X - origin.X) * d.Width); + vertex->Y = d.Y + ((corner.Y - origin.Y) * d.Height); + vertex->ZW = tp; + vertex->RGBA = scaledColor; + corner = s_rectangleCornerOffsets[j ^ (int)effects]; + vertex->U = (s.X + (corner.X * s.Width)) * deltaX; + vertex->V = (s.Y + (corner.Y * s.Height)) * deltaY; vertex->M = mode; } @@ -255,18 +254,13 @@ private void DrawTexture(Texture texture, float posX = (corner.X - origin.X) * d.Width; float posY = (corner.Y - origin.Y) * d.Height; - vertex->X = (float)((d.X + (posX * cos)) - (posY * sin)); - vertex->Y = (float)(d.Y + (posX * sin) + (posY * cos)); - vertex->ZW = tp; - - vertex->R = scaledColor.R; - vertex->G = scaledColor.G; - vertex->B = scaledColor.B; - vertex->A = scaledColor.A; - - corner = s_rectangleCornerOffsets[j ^ (int)effects]; - vertex->U = (s.X + (corner.X * s.Width)) * deltaX; - vertex->V = (s.Y + (corner.Y * s.Height)) * deltaY; + vertex->X = (float)((d.X + (posX * cos)) - (posY * sin)); + vertex->Y = (float)(d.Y + (posX * sin) + (posY * cos)); + vertex->ZW = tp; + vertex->RGBA = scaledColor; + corner = s_rectangleCornerOffsets[j ^ (int)effects]; + vertex->U = (s.X + (corner.X * s.Width)) * deltaX; + vertex->V = (s.Y + (corner.Y * s.Height)) * deltaY; vertex->M = mode; } diff --git a/src/Exomia.Framework/Graphics/Canvas.Triangle.cs b/src/Exomia.Framework/Graphics/Canvas.Triangle.cs index 8264048c..c5765ae0 100644 --- a/src/Exomia.Framework/Graphics/Canvas.Triangle.cs +++ b/src/Exomia.Framework/Graphics/Canvas.Triangle.cs @@ -49,7 +49,8 @@ public void DrawTriangle(in Vector2 point1, in Vector2 origin, float opacity) { - DrawTriangle(new Triangle2(in point1, in point2, in point3), color, lineWidth, rotation, in origin, opacity); + DrawTriangle( + new Triangle2(in point1, in point2, in point3), color, lineWidth, rotation, in origin, opacity); } /// @@ -79,12 +80,17 @@ public void DrawTriangle(in Triangle2 triangle, in Vector2 origin, float opacity) { - Triangle2 t = rotation == 0.0 ? triangle : Triangle2.RotateAround(in triangle, rotation, in origin); - Color scaledColor = color * opacity; + Triangle2 t = rotation == 0.0 ? triangle : Triangle2.RotateAround(in triangle, rotation, in origin); + + Vector4 scaledColor; + scaledColor.X = color.R * opacity; + scaledColor.Y = color.G * opacity; + scaledColor.Z = color.B * opacity; + scaledColor.W = color.A * opacity; Line2 a = new Line2(in t.XY1, in t.XY2); Line2 perpendicularA = a.GetPerpendicular(lineWidth); - + Line2 b = new Line2(in t.XY2, in t.XY3); Line2 perpendicularB = b.GetPerpendicular(lineWidth); @@ -169,7 +175,11 @@ public void DrawFillTriangle(in Triangle2 triangle, in Vector2 origin, float opacity) { - Color scaledColor = color * opacity; + Vector4 scaledColor; + scaledColor.X = color.R * opacity; + scaledColor.Y = color.G * opacity; + scaledColor.Z = color.B * opacity; + scaledColor.W = color.A * opacity; Item* ptr = Reserve(1); @@ -182,15 +192,11 @@ public void DrawFillTriangle(in Triangle2 triangle, fixed (Triangle2* t = &triangle) { Vector2* tf = (Vector2*)t; - vertex->XY = *(tf + i ); + vertex->XY = *(tf + i); } - vertex->R = scaledColor.R; - vertex->G = scaledColor.G; - vertex->B = scaledColor.B; - vertex->A = scaledColor.A; - - vertex->M = COLOR_MODE; + vertex->RGBA = scaledColor; + vertex->M = COLOR_MODE; } } else @@ -210,12 +216,8 @@ public void DrawFillTriangle(in Triangle2 triangle, vertex->Y = (float)((sin * v.X) + (cos * v.Y) + origin.Y); } - vertex->R = scaledColor.R; - vertex->G = scaledColor.G; - vertex->B = scaledColor.B; - vertex->A = scaledColor.A; - - vertex->M = COLOR_MODE; + vertex->RGBA = scaledColor; + vertex->M = COLOR_MODE; } } diff --git a/src/Exomia.Framework/Graphics/SpriteBatch.SpriteFont.cs b/src/Exomia.Framework/Graphics/SpriteBatch.SpriteFont.cs index a15fa802..b407a234 100644 --- a/src/Exomia.Framework/Graphics/SpriteBatch.SpriteFont.cs +++ b/src/Exomia.Framework/Graphics/SpriteBatch.SpriteFont.cs @@ -9,8 +9,12 @@ #endregion using System.Runtime.CompilerServices; -using System.Text; using SharpDX; + +#if NETSTANDARD2_1 +using System; + +#endif namespace Exomia.Framework.Graphics { @@ -19,218 +23,127 @@ public sealed partial class SpriteBatch /// /// Draw text. /// - /// The font. - /// The text. - /// The position. - /// The color. + /// The font. + /// The text. + /// The position. + /// The color. /// The depth of the layer. +#if NETSTANDARD2_1 [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, string text, in Vector2 position, in Color color, float layerDepth) + public void DrawText(SpriteFont font, + ReadOnlySpan text, + in Vector2 position, + in Color color, + float layerDepth = 1.0f) +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, string text, in Vector2 position, in Color color, float layerDepth = 1.0f) +#endif { - font.Draw( - DrawTextInternal, text, position, - color, 0f, Vector2.Zero, 1.0f, TextureEffects.None, layerDepth); + font.Draw(DrawTextInternal, text, position, color, 0f, Vector2.Zero, 1.0f, TextureEffects.None, layerDepth); } /// /// Draw text. /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. + /// The font. + /// The text. + /// The position. + /// The color. + /// The rotation. /// The depth of the layer. +#if NETSTANDARD2_1 + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + ReadOnlySpan text, + in Vector2 position, + in Color color, + float rotation, + float layerDepth = 1.0f) +#else [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, string text, in Vector2 position, in Color color, float rotation, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, position, - color, rotation, Vector2.Zero, 1.0f, TextureEffects.None, layerDepth); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// The depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - string text, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - TextureEffects effects, - float layerDepth) + float layerDepth = 1.0f) +#endif { font.Draw( - DrawTextInternal, text, position, - color, rotation, origin, opacity, effects, layerDepth); + DrawTextInternal, text, position, color, rotation, Vector2.Zero, 1.0f, TextureEffects.None, layerDepth); } /// /// Draw text. /// - /// The font. - /// The text. - /// The start. - /// The end. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. + /// The font. + /// The text. + /// The position. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. /// The depth of the layer. +#if NETSTANDARD2_1 [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - string text, - int start, - int end, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - TextureEffects effects, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, start, end, position, - color, rotation, origin, opacity, effects, layerDepth); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The start. - /// The end. - /// The position. - /// The dimension. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// The depth of the layer. + public void DrawText(SpriteFont font, + ReadOnlySpan text, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth = 1.0f) +#else [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, string text, - int start, - int end, in Vector2 position, - in Size2F dimension, in Color color, float rotation, in Vector2 origin, float opacity, TextureEffects effects, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, start, end, position, dimension, - color, rotation, origin, opacity, effects, layerDepth); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, StringBuilder text, in Vector2 position, in Color color, float layerDepth) + float layerDepth = 1.0f) +#endif { - font.Draw( - DrawTextInternal, text, position, - color, 0f, Vector2.Zero, 1.0f, TextureEffects.None, layerDepth); + font.Draw(DrawTextInternal, text, position, color, rotation, origin, opacity, effects, layerDepth); } /// /// Draw text. /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. - /// The depth of the layer. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - StringBuilder text, - in Vector2 position, - in Color color, - float rotation, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, position, - color, rotation, Vector2.Zero, 1.0f, TextureEffects.None, layerDepth); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. + /// The font. + /// The text. + /// The start. + /// The end. + /// The position. + /// The color. + /// The rotation. + /// The origin. + /// The opacity. + /// The effects. /// The depth of the layer. +#if NETSTANDARD2_1 [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void DrawText(SpriteFont font, - StringBuilder text, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - TextureEffects effects, - float layerDepth) - { - font.Draw( - DrawTextInternal, text, position, - color, rotation, origin, opacity, effects, layerDepth); - } - - /// - /// Draw text. - /// - /// The font. - /// The text. - /// The start. - /// The end. - /// The position. - /// The color. - /// The rotation. - /// The origin. - /// The opacity. - /// The effects. - /// The depth of the layer. + public void DrawText(SpriteFont font, + ReadOnlySpan text, + int start, + int end, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth = 1.0f) +#else [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, - StringBuilder text, + string text, int start, int end, in Vector2 position, @@ -239,11 +152,11 @@ public void DrawText(SpriteFont font, in Vector2 origin, float opacity, TextureEffects effects, - float layerDepth) + float layerDepth = 1.0f) +#endif { font.Draw( - DrawTextInternal, text, start, end, position, - color, rotation, origin, opacity, effects, layerDepth); + DrawTextInternal, text, start, end, position, color, rotation, origin, opacity, effects, layerDepth); } /// @@ -261,9 +174,24 @@ public void DrawText(SpriteFont font, /// The opacity. /// The effects. /// The depth of the layer. +#if NETSTANDARD2_1 + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void DrawText(SpriteFont font, + ReadOnlySpan text, + int start, + int end, + in Vector2 position, + in Size2F dimension, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth = 1.0f) +#else [MethodImpl(MethodImplOptions.AggressiveInlining)] public void DrawText(SpriteFont font, - StringBuilder text, + string text, int start, int end, in Vector2 position, @@ -273,26 +201,14 @@ public void DrawText(SpriteFont font, in Vector2 origin, float opacity, TextureEffects effects, - float layerDepth) + float layerDepth = 1.0f) +#endif { font.Draw( - DrawTextInternal, text, start, end, position, dimension, - color, rotation, origin, opacity, effects, layerDepth); + DrawTextInternal, text, start, end, position, dimension, color, rotation, origin, opacity, effects, + layerDepth); } - /// - /// Draw text internal. - /// - /// The texture. - /// The position. - /// The source rectangle. - /// The color. - /// The rotation. - /// The origin. - /// The scale. - /// The opacity. - /// The effects. - /// The depth of the layer. [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void DrawTextInternal(Texture texture, in Vector2 position, diff --git a/src/Exomia.Framework/Graphics/SpriteFont.Glyph.cs b/src/Exomia.Framework/Graphics/SpriteFont.Glyph.cs new file mode 100644 index 00000000..cf2c264a --- /dev/null +++ b/src/Exomia.Framework/Graphics/SpriteFont.Glyph.cs @@ -0,0 +1,50 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using Exomia.Framework.ContentSerialization; +using SharpDX; + +namespace Exomia.Framework.Graphics +{ + public sealed partial class SpriteFont + { + /// + /// A glyph. + /// + [ContentSerializable(typeof(SpriteFontGlyphCR), typeof(SpriteFontGlyphCW))] + public struct Glyph + { + /// + /// The character. + /// + public int Character; + + /// + /// The subrect. + /// + public Rectangle Subrect; + + /// + /// The offset x coordinate. + /// + public int OffsetX; + + /// + /// The offset y coordinate. + /// + public int OffsetY; + + /// + /// The advance. + /// + public int XAdvance; + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteFont.Kerning.cs b/src/Exomia.Framework/Graphics/SpriteFont.Kerning.cs new file mode 100644 index 00000000..74dff3b0 --- /dev/null +++ b/src/Exomia.Framework/Graphics/SpriteFont.Kerning.cs @@ -0,0 +1,39 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using Exomia.Framework.ContentSerialization; + +namespace Exomia.Framework.Graphics +{ + public sealed partial class SpriteFont + { + /// + /// A kerning. + /// + [ContentSerializable(typeof(SpriteFontKerningCR), typeof(SpriteFontKerningCW))] + public struct Kerning + { + /// + /// The first. + /// + public int First; + + /// + /// The second. + /// + public int Second; + + /// + /// The offset. + /// + public int Offset; + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteFont.Methods.cs b/src/Exomia.Framework/Graphics/SpriteFont.Methods.cs new file mode 100644 index 00000000..32084504 --- /dev/null +++ b/src/Exomia.Framework/Graphics/SpriteFont.Methods.cs @@ -0,0 +1,531 @@ +#region License + +// Copyright (c) 2018-2020, exomia +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#endregion + +using System; +using System.Runtime.CompilerServices; +using SharpDX; + +namespace Exomia.Framework.Graphics +{ + public sealed partial class SpriteFont + { + /// + /// Returns the size of this text. + /// + /// The text. + /// + /// A with x and y set to width and height of + /// +#if NETSTANDARD2_1 + public Vector2 MeasureText(ReadOnlySpan text) +#else + public Vector2 MeasureText(string text) +#endif + { + return MeasureText(text, 0, text.Length); + } + + /// + /// Returns the size of this text from to . + /// + /// The text. + /// The start. + /// The end. + /// + /// A with x and y set to width and height of + /// +#if NETSTANDARD2_1 + public Vector2 MeasureText(ReadOnlySpan text, int start, int end) +#else + public Vector2 MeasureText(string text, int start, int end) +#endif + { + Vector2 size = Vector2.Zero; + + if (start >= end) { return size; } + if (end > text.Length) { end = text.Length; } + if (start < 0) { start = 0; } + + float x = 0; + float y = 0; + + int key = 0; + + for (int i = start; i < end; i++) + { + char c = text[i]; + switch (c) + { + case '\r': + { + key |= c; + continue; + } + case '\n': + { + key = 0; + x = 0; + y += LineSpacing; + } + break; + default: + { + if (!_glyphs.TryGetValue(c, out Glyph glyph)) + { + if (IgnoreUnknownCharacters) + { + continue; + } + + glyph = _defaultGlyph; + } + key |= c; + + float dx = glyph.OffsetX; + if (Kernings.TryGetValue(key, out Kerning kerning)) + { + dx += kerning.Offset; + } + + float nextX = x + glyph.XAdvance + SpacingX; + + float h = y + LineSpacing; + if (nextX + dx > size.X) + { + size.X = nextX; + } + if (h > size.Y) + { + size.Y = h; + } + + x = nextX; + } + break; + } + + key <<= 16; + } + + return size; + } + + /// + /// Determines which item (if any) has been hit. + /// + /// The text. + /// The start. + /// The end. + /// The position. + /// The position. + /// + /// An int. + /// +#if NETSTANDARD2_1 + public int HitTest(ReadOnlySpan text, int start, int end, float xPos, float yPos) +#else + public int HitTest(string text, int start, int end, float xPos, float yPos) +#endif + { + if (start >= end) { return end; } + if (end > text.Length) { end = text.Length; } + if (start < 0) { start = 0; } + + if (xPos < 0) { return -1; } + if (yPos < 0) { return -1; } + + float x = 0; + float y = 0; + + int key = 0; + + for (int i = start; i < end; i++) + { + char c = text[i]; + switch (c) + { + case '\r': + { + key |= c; + continue; + } + case '\n': + { + key = 0; + x = 0; + y += LineSpacing; + } + break; + default: + { + if (!_glyphs.TryGetValue(c, out Glyph glyph)) + { + if (IgnoreUnknownCharacters) + { + continue; + } + glyph = _defaultGlyph; + } + key |= c; + + float dx = glyph.OffsetX; + if (Kernings.TryGetValue(key, out Kerning kerning)) + { + dx += kerning.Offset; + } + + float nextX = x + glyph.XAdvance + SpacingX; + float h = y + LineSpacing; + + if (xPos >= x && xPos <= nextX + dx && yPos <= h && yPos >= y) + { + if (xPos < (x + nextX + dx) * 0.5f) { return i; } + return i + 1; + } + x = nextX; + } + break; + } + key <<= 16; + } + + return end; + } + +#if NETSTANDARD2_1 + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void Draw(DrawFont drawCallback, + ReadOnlySpan text, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) +#else + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void Draw(DrawFont drawCallback, + string text, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) +#endif + { + Draw( + drawCallback, text, 0, text.Length, + in position, in color, rotation, in origin, + opacity, effects, layerDepth); + } + +#if NETSTANDARD2_1 + internal void Draw(DrawFont drawCallback, + ReadOnlySpan text, + int start, + int end, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) +#else + internal void Draw(DrawFont drawCallback, + string text, + int start, + int end, + in Vector2 position, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) +#endif + { + if (end <= start || end > text.Length) { end = text.Length; } + + float x = 0; + float y = 0; + + int key = 0; + + if (rotation == 0) + { + for (int i = start; i < end; i++) + { + char c = text[i]; + switch (c) + { + case '\r': + { + key |= c; + continue; + } + case '\n': + { + key = 0; + x = 0; + y += LineSpacing; + } + break; + default: + { + if (!_glyphs.TryGetValue(c, out Glyph glyph)) + { + if (IgnoreUnknownCharacters) + { + continue; + } + + glyph = _defaultGlyph; + } + key |= c; + + float dx = glyph.OffsetX; + if (Kernings.TryGetValue(key, out Kerning kerning)) + { + dx += kerning.Offset; + } + + drawCallback( + _texture, + new Vector2(position.X + x + dx, position.Y + y + glyph.OffsetY), + glyph.Subrect, color, rotation, origin, + 1.0f, opacity, effects, layerDepth); + + x += glyph.XAdvance + SpacingX; + } + break; + } + + key <<= 16; + } + } + else + { + double cos = Math.Cos(rotation); + double sin = Math.Sin(rotation); + + for (int i = start; i < end; i++) + { + char c = text[i]; + switch (c) + { + case '\r': + { + key |= c; + continue; + } + case '\n': + { + key = 0; + x = 0; + y += LineSpacing; + } + break; + default: + { + if (!_glyphs.TryGetValue(c, out Glyph glyph)) + { + if (IgnoreUnknownCharacters) + { + continue; + } + + glyph = _defaultGlyph; + } + key |= c; + + float dx = glyph.OffsetX; + if (Kernings.TryGetValue(key, out Kerning kerning)) + { + dx += kerning.Offset; + } + + float ox = (position.X + x + dx) - origin.X; + float oy = (position.Y + y + glyph.OffsetY) - origin.Y; + drawCallback( + _texture, + new Vector2( + (float)(((cos * ox) - (sin * oy)) + origin.X), + (float)((sin * ox) + (cos * oy) + origin.Y)), + glyph.Subrect, + color, rotation, Vector2.Zero, 1.0f, opacity, effects, layerDepth); + + x += glyph.XAdvance + SpacingX; + } + break; + } + + key <<= 16; + } + } + } + +#if NETSTANDARD2_1 + internal void Draw(DrawFont drawCallback, + ReadOnlySpan text, + int start, + int end, + in Vector2 position, + in Size2F dimension, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) +#else + internal void Draw(DrawFont drawCallback, + string text, + int start, + int end, + in Vector2 position, + in Size2F dimension, + in Color color, + float rotation, + in Vector2 origin, + float opacity, + TextureEffects effects, + float layerDepth) +#endif + { + if (end <= start || end > text.Length) { end = text.Length; } + + float x = 0; + float y = 0; + + int key = 0; + if (rotation == 0) + { + for (int i = start; i < end; i++) + { + char c = text[i]; + switch (c) + { + case '\r': + { + key |= c; + continue; + } + case '\n': + { + key = 0; + x = 0; + y += LineSpacing; + } + break; + default: + { + if (!_glyphs.TryGetValue(c, out Glyph glyph)) + { + if (IgnoreUnknownCharacters) + { + continue; + } + + glyph = _defaultGlyph; + } + key |= c; + + float dx = glyph.OffsetX; + if (Kernings.TryGetValue(key, out Kerning kerning)) + { + dx += kerning.Offset; + } + + if (x + dx + glyph.Subrect.Width > dimension.Width) { return; } + if (y + glyph.OffsetY + glyph.Subrect.Height > dimension.Height) { return; } + + drawCallback( + _texture, + new Vector2(position.X + x + dx, position.Y + y + glyph.OffsetY), + glyph.Subrect, color, rotation, origin, + 1.0f, opacity, effects, layerDepth); + + x += glyph.XAdvance + SpacingX; + } + break; + } + + key <<= 16; + } + } + else + { + double cos = Math.Cos(rotation); + double sin = Math.Sin(rotation); + + for (int i = start; i < end; i++) + { + char c = text[i]; + switch (c) + { + case '\r': + { + key |= c; + continue; + } + case '\n': + { + key = 0; + x = 0; + y += LineSpacing; + } + break; + default: + { + if (!_glyphs.TryGetValue(c, out Glyph glyph)) + { + if (IgnoreUnknownCharacters) + { + continue; + } + + glyph = _defaultGlyph; + } + key |= c; + + float dx = glyph.OffsetX; + if (Kernings.TryGetValue(key, out Kerning kerning)) + { + dx += kerning.Offset; + } + + if (x + dx + glyph.Subrect.Width > dimension.Width) { return; } + if (y + glyph.OffsetY + glyph.Subrect.Height > dimension.Height) { return; } + + float ox = (position.X + x + dx) - origin.X; + float oy = (position.Y + y + glyph.OffsetY) - origin.Y; + drawCallback( + _texture, + new Vector2( + (float)(((cos * ox) - (sin * oy)) + origin.X), + (float)((sin * ox) + (cos * oy) + origin.Y)), + glyph.Subrect, color, rotation, Vector2.Zero, + 1.0f, opacity, effects, layerDepth); + + x += glyph.XAdvance + SpacingX; + } + break; + } + + key <<= 16; + } + } + } + } +} \ No newline at end of file diff --git a/src/Exomia.Framework/Graphics/SpriteFont.cs b/src/Exomia.Framework/Graphics/SpriteFont.cs index 39dd8f31..0ee162c3 100644 --- a/src/Exomia.Framework/Graphics/SpriteFont.cs +++ b/src/Exomia.Framework/Graphics/SpriteFont.cs @@ -10,7 +10,6 @@ using System; using System.Collections.Generic; -using System.Text; using Exomia.Framework.Content; using Exomia.Framework.ContentSerialization; using SharpDX; @@ -22,8 +21,19 @@ namespace Exomia.Framework.Graphics /// [ContentReadable(typeof(SpriteFontContentReader))] [ContentSerializable(typeof(SpriteFontContentSerializationReader), typeof(SpriteFontContentSerializationWriter))] - public sealed class SpriteFont : IDisposable + public sealed partial class SpriteFont : IDisposable { + internal delegate void DrawFont(Texture texture, + in Vector2 position, + in Rectangle? sourceRectangle, + in Color color, + float rotation, + in Vector2 origin, + float scale, + float opacity, + TextureEffects effects, + float layerDepth); + private Glyph _defaultGlyph; private Dictionary _glyphs; private Texture _texture; @@ -172,865 +182,10 @@ public SpriteFont() _texture = Texture.Empty; } - /// - /// Finalizes an instance of the class. - /// - ~SpriteFont() - { - Dispose(false); - } - - internal delegate void DrawFont(Texture texture, - in Vector2 position, - in Rectangle? sourceRectangle, - in Color color, - float rotation, - in Vector2 origin, - float scale, - float opacity, - TextureEffects effects, - float layerDepth); - - /// - /// A glyph. - /// - [ContentSerializable(typeof(SpriteFontGlyphCR), typeof(SpriteFontGlyphCW))] - public struct Glyph - { - /// - /// The character. - /// - public int Character; - - /// - /// The subrect. - /// - public Rectangle Subrect; - - /// - /// The offset x coordinate. - /// - public int OffsetX; - - /// - /// The offset y coordinate. - /// - public int OffsetY; - - /// - /// The advance. - /// - public int XAdvance; - } - - /// - /// A kerning. - /// - [ContentSerializable(typeof(SpriteFontKerningCR), typeof(SpriteFontKerningCW))] - public struct Kerning - { - /// - /// The first. - /// - public int First; - - /// - /// The second. - /// - public int Second; - - /// - /// The offset. - /// - public int Offset; - } - - #region String - - /// - /// Measure text. - /// - /// The text. - /// - /// A Vector2. - /// - public Vector2 MeasureText(string text) - { - return MeasureText(text, 0, text.Length); - } - - /// - /// Measure text. - /// - /// The text. - /// The start. - /// The end. - /// - /// A Vector2. - /// - public Vector2 MeasureText(string text, int start, int end) - { - Vector2 size = Vector2.Zero; - - if (start >= end) { return size; } - if (end > text.Length) { end = text.Length; } - if (start < 0) { start = 0; } - - float x = 0; - float y = 0; - - int key = 0; - - for (int i = start; i < end; i++) - { - char c = text[i]; - switch (c) - { - case '\r': - { - key |= c; - continue; - } - case '\n': - { - key = 0; - x = 0; - y += LineSpacing; - } - break; - default: - { - if (!_glyphs.TryGetValue(c, out Glyph glyph)) - { - if (IgnoreUnknownCharacters) - { - continue; - } - - glyph = _defaultGlyph; - } - key |= c; - - float dx = glyph.OffsetX; - if (Kernings.TryGetValue(key, out Kerning kerning)) - { - dx += kerning.Offset; - } - - float nextX = x + glyph.XAdvance + SpacingX; - - float h = y + LineSpacing; - if (nextX + dx > size.X) - { - size.X = nextX; - } - if (h > size.Y) - { - size.Y = h; - } - - x = nextX; - } - break; - } - - key <<= 16; - } - - return size; - } - - /// - /// Determines which item (if any) has been hit. - /// - /// The text. - /// The start. - /// The end. - /// The position. - /// The position. - /// - /// An int. - /// - public int HitTest(string text, int start, int end, float xPos, float yPos) - { - if (start >= end) { return end; } - if (end > text.Length) { end = text.Length; } - if (start < 0) { start = 0; } - - if (xPos < 0) { return -1; } - if (yPos < 0) { return -1; } - - float x = 0; - float y = 0; - - int key = 0; - - for (int i = start; i < end; i++) - { - char c = text[i]; - switch (c) - { - case '\r': - { - key |= c; - continue; - } - case '\n': - { - key = 0; - x = 0; - y += LineSpacing; - } - break; - default: - { - if (!_glyphs.TryGetValue(c, out Glyph glyph)) - { - if (IgnoreUnknownCharacters) - { - continue; - } - glyph = _defaultGlyph; - } - key |= c; - - float dx = glyph.OffsetX; - if (Kernings.TryGetValue(key, out Kerning kerning)) - { - dx += kerning.Offset; - } - - float nextX = x + glyph.XAdvance + SpacingX; - float h = y + LineSpacing; - - if (xPos >= x && xPos <= nextX + dx && yPos <= h && yPos >= y) - { - if (xPos < (x + nextX + dx) * 0.5f) { return i; } - return i + 1; - } - x = nextX; - } - break; - } - key <<= 16; - } - - return end; - } - - internal void Draw(DrawFont drawCallback, - string text, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - TextureEffects effects, - float layerDepth) - { - float x = 0; - float y = 0; - - int key = 0; - - int l = text.Length; - for (int i = 0; i < l; i++) - { - char c = text[i]; - switch (c) - { - case '\r': - { - key |= c; - continue; - } - case '\n': - { - key = 0; - x = 0; - y += LineSpacing; - } - break; - default: - { - if (!_glyphs.TryGetValue(c, out Glyph glyph)) - { - if (IgnoreUnknownCharacters) - { - continue; - } - - glyph = _defaultGlyph; - } - key |= c; - - float dx = glyph.OffsetX; - if (Kernings.TryGetValue(key, out Kerning kerning)) - { - dx += kerning.Offset; - } - - drawCallback( - _texture, - new Vector2(position.X + x + dx, position.Y + y + glyph.OffsetY), - glyph.Subrect, - color, rotation, origin, 1.0f, opacity, effects, layerDepth); - - x += glyph.XAdvance + SpacingX; - } - break; - } - - key <<= 16; - } - } - - internal void Draw(DrawFont drawCallback, - string text, - int start, - int end, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - TextureEffects effects, - float layerDepth) - { - if (end <= start || end > text.Length) { end = text.Length; } - - float x = 0; - float y = 0; - - int key = 0; - - for (int i = start; i < end; i++) - { - char c = text[i]; - switch (c) - { - case '\r': - { - key |= c; - continue; - } - case '\n': - { - key = 0; - x = 0; - y += LineSpacing; - } - break; - default: - { - if (!_glyphs.TryGetValue(c, out Glyph glyph)) - { - if (IgnoreUnknownCharacters) - { - continue; - } - - glyph = _defaultGlyph; - } - key |= c; - - float dx = glyph.OffsetX; - if (Kernings.TryGetValue(key, out Kerning kerning)) - { - dx += kerning.Offset; - } - - drawCallback( - _texture, - new Vector2(position.X + x + dx, position.Y + y + glyph.OffsetY), - glyph.Subrect, - color, rotation, origin, 1.0f, opacity, effects, layerDepth); - - x += glyph.XAdvance + SpacingX; - } - break; - } - - key <<= 16; - } - } - - internal void Draw(DrawFont drawCallback, - string text, - int start, - int end, - in Vector2 position, - in Size2F dimension, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - TextureEffects effects, - float layerDepth) - { - if (end <= start || end > text.Length) { end = text.Length; } - - float x = 0; - float y = 0; - - int key = 0; - - for (int i = start; i < end; i++) - { - char c = text[i]; - switch (c) - { - case '\r': - { - key |= c; - continue; - } - case '\n': - { - key = 0; - x = 0; - y += LineSpacing; - } - break; - default: - { - if (!_glyphs.TryGetValue(c, out Glyph glyph)) - { - if (IgnoreUnknownCharacters) - { - continue; - } - - glyph = _defaultGlyph; - } - key |= c; - - float dx = glyph.OffsetX; - if (Kernings.TryGetValue(key, out Kerning kerning)) - { - dx += kerning.Offset; - } - - if (x + dx + glyph.Subrect.Width > dimension.Width) { return; } - if (y + glyph.OffsetY + glyph.Subrect.Height > dimension.Height) { return; } - - drawCallback( - _texture, - new Vector2(position.X + x + dx, position.Y + y + glyph.OffsetY), - glyph.Subrect, - color, rotation, origin, 1.0f, opacity, effects, layerDepth); - - x += glyph.XAdvance + SpacingX; - } - break; - } - - key <<= 16; - } - } - - #endregion - - #region StringBuilder - - /// - /// Measure text. - /// - /// The text. - /// - /// A Vector2. - /// - public Vector2 MeasureText(StringBuilder text) - { - return MeasureText(text, 0, text.Length); - } - - /// - /// Measure text. - /// - /// The text. - /// The start. - /// The end. - /// - /// A Vector2. - /// - public Vector2 MeasureText(StringBuilder text, int start, int end) - { - Vector2 size = Vector2.Zero; - - if (start >= end) { return size; } - if (end > text.Length) { end = text.Length; } - if (start < 0) { start = 0; } - - float x = 0; - float y = 0; - - int key = 0; - - for (int i = start; i < end; i++) - { - char c = text[i]; - switch (c) - { - case '\r': - { - key |= c; - continue; - } - case '\n': - { - key = 0; - x = 0; - y += LineSpacing; - } - break; - default: - { - if (!_glyphs.TryGetValue(c, out Glyph glyph)) - { - if (IgnoreUnknownCharacters) - { - continue; - } - - glyph = _defaultGlyph; - } - key |= c; - - float dx = glyph.OffsetX; - if (Kernings.TryGetValue(key, out Kerning kerning)) - { - dx += kerning.Offset; - } - - float nextX = x + glyph.XAdvance + SpacingX; - - float h = y + LineSpacing; - if (nextX + dx > size.X) - { - size.X = nextX; - } - if (h > size.Y) - { - size.Y = h; - } - - x = nextX; - } - break; - } - - key <<= 16; - } - - return size; - } - - /// - /// Determines which item (if any) has been hit. - /// - /// The text. - /// The start. - /// The end. - /// The position. - /// The position. - /// - /// An int. - /// - public int HitTest(StringBuilder text, int start, int end, float xPos, float yPos) - { - if (start >= end) { return end; } - if (end > text.Length) { end = text.Length; } - if (start < 0) { start = 0; } - - if (xPos < 0) { return -1; } - if (yPos < 0) { return -1; } - - float x = 0; - float y = 0; - - int key = 0; - - for (int i = start; i < end; i++) - { - char c = text[i]; - switch (c) - { - case '\r': - { - key |= c; - continue; - } - case '\n': - { - key = 0; - x = 0; - y += LineSpacing; - } - break; - default: - { - if (!_glyphs.TryGetValue(c, out Glyph glyph)) - { - if (IgnoreUnknownCharacters) - { - continue; - } - glyph = _defaultGlyph; - } - key |= c; - - float dx = glyph.OffsetX; - if (Kernings.TryGetValue(key, out Kerning kerning)) - { - dx += kerning.Offset; - } - - float nextX = x + glyph.XAdvance + SpacingX; - float h = y + LineSpacing; - - if (xPos >= x && xPos <= nextX + dx && yPos <= h && yPos >= y) - { - if (xPos < (x + nextX + dx) * 0.5f) { return i; } - return i + 1; - } - x = nextX; - } - break; - } - key <<= 16; - } - - return end; - } - - internal void Draw(DrawFont drawCallback, - StringBuilder text, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - TextureEffects effects, - float layerDepth) - { - float x = 0; - float y = 0; - - int key = 0; - - int l = text.Length; - for (int i = 0; i < l; i++) - { - char c = text[i]; - switch (c) - { - case '\r': - { - key |= c; - continue; - } - case '\n': - { - key = 0; - x = 0; - y += LineSpacing; - break; - } - default: - { - if (!_glyphs.TryGetValue(c, out Glyph glyph)) - { - if (IgnoreUnknownCharacters) - { - continue; - } - - glyph = _defaultGlyph; - } - key |= c; - - float dx = glyph.OffsetX; - if (Kernings.TryGetValue(key, out Kerning kerning)) - { - dx += kerning.Offset; - } - - drawCallback( - _texture, new Vector2(position.X + x + dx, position.Y + y + glyph.OffsetY), - glyph.Subrect, - color, rotation, origin, 1.0f, opacity, effects, layerDepth); - - x += glyph.XAdvance + SpacingX; - break; - } - } - - key <<= 16; - } - } - - internal void Draw(DrawFont drawCallback, - StringBuilder text, - int start, - int end, - in Vector2 position, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - TextureEffects effects, - float layerDepth) - { - if (end <= start || end > text.Length) { end = text.Length; } - - float x = 0; - float y = 0; - - int key = 0; - - for (int i = start; i < end; i++) - { - char c = text[i]; - switch (c) - { - case '\r': - { - key |= c; - continue; - } - case '\n': - { - key = 0; - x = 0; - y += LineSpacing; - } - break; - default: - { - if (!_glyphs.TryGetValue(c, out Glyph glyph)) - { - if (IgnoreUnknownCharacters) - { - continue; - } - - glyph = _defaultGlyph; - } - key |= c; - - float dx = glyph.OffsetX; - if (Kernings.TryGetValue(key, out Kerning kerning)) - { - dx += kerning.Offset; - } - - drawCallback( - _texture, - new Vector2(position.X + x + dx, position.Y + y + glyph.OffsetY), - glyph.Subrect, - color, rotation, origin, 1.0f, opacity, effects, layerDepth); - - x += glyph.XAdvance + SpacingX; - } - break; - } - - key <<= 16; - } - } - - internal void Draw(DrawFont drawCallback, - StringBuilder text, - int start, - int end, - in Vector2 position, - in Size2F dimension, - in Color color, - float rotation, - in Vector2 origin, - float opacity, - TextureEffects effects, - float layerDepth) - { - if (end <= start || end > text.Length) { end = text.Length; } - - float x = 0; - float y = 0; - - int key = 0; - - for (int i = start; i < end; i++) - { - char c = text[i]; - switch (c) - { - case '\r': - { - key |= c; - continue; - } - case '\n': - { - key = 0; - x = 0; - y += LineSpacing; - } - break; - default: - { - if (!_glyphs.TryGetValue(c, out Glyph glyph)) - { - if (IgnoreUnknownCharacters) - { - continue; - } - - glyph = _defaultGlyph; - } - key |= c; - - float dx = glyph.OffsetX; - if (Kernings.TryGetValue(key, out Kerning kerning)) - { - dx += kerning.Offset; - } - - if (x + dx + glyph.Subrect.Width > dimension.Width) { return; } - if (y + glyph.OffsetY + glyph.Subrect.Height > dimension.Height) { return; } - - drawCallback( - _texture, - new Vector2(position.X + x + dx, position.Y + y + glyph.OffsetY), - glyph.Subrect, - color, rotation, origin, 1.0f, opacity, effects, layerDepth); - - x += glyph.XAdvance + SpacingX; - } - break; - } - - key <<= 16; - } - } - - #endregion - #region IDisposable Support - - /// - /// True if disposed. - /// + private bool _disposed; - - /// - /// Releases the unmanaged resources used by the Exomia.Framework.Graphics.SpriteFont and - /// optionally releases the managed resources. - /// - /// - /// True to release both managed and unmanaged resources; false to - /// release only unmanaged resources. - /// + private void Dispose(bool disposing) { if (!_disposed) @@ -1049,6 +204,14 @@ private void Dispose(bool disposing) } } + /// + /// Finalizes an instance of the class. + /// + ~SpriteFont() + { + Dispose(false); + } + /// public void Dispose() { diff --git a/src/Exomia.Framework/Mathematics/Line2.cs b/src/Exomia.Framework/Mathematics/Line2.cs index a8651241..18658738 100644 --- a/src/Exomia.Framework/Mathematics/Line2.cs +++ b/src/Exomia.Framework/Mathematics/Line2.cs @@ -66,28 +66,30 @@ namespace Exomia.Framework.Mathematics /// The first y value. /// The second x value. /// The second y value. - public Line2(float x1, float y1, float x2, float y2) : this() + public Line2(float x1, float y1, float x2, float y2) + : this() { - X1 = x1; - Y1 = y1; - X2 = x2; - Y2 = y2; + X1 = x1; + Y1 = y1; + X2 = x2; + Y2 = y2; } /// /// Initializes a new instance of the struct. /// - /// [in,out] The to process. - /// [in,out] The to process. + /// [in,out] The to process. + /// [in,out] The to process. public Line2(in VectorI2 a, in VectorI2 b) : this(a.X, a.Y, b.X, b.Y) { } /// /// Initializes a new instance of the struct. /// - /// [in,out] The to process. - /// [in,out] The to process. - public Line2(in Vector2 a, in Vector2 b) : this() + /// [in,out] The to process. + /// [in,out] The to process. + public Line2(in Vector2 a, in Vector2 b) + : this() { XY1 = a; XY2 = b; @@ -266,17 +268,20 @@ public static Line2 RotateAround(in Line2 line, float rotation, in Vector2 origi } /// - /// Creates a line out of and , as well the perpendicular from this line. + /// Creates a line out of and , as well the perpendicular from this line. /// - /// [in,out] The first ref . - /// [in,out] The second ref . + /// [in,out] The first ref . + /// [in,out] The second ref . /// The offset. /// [out] The perpendicular. /// - /// The line created from and . + /// The line created from and . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Line2 CreateWithPerpendicular(ref Vector2 p1, ref Vector2 p2, float offset, out Line2 perpendicular) + public static Line2 CreateWithPerpendicular(ref Vector2 p1, + ref Vector2 p2, + float offset, + out Line2 perpendicular) { float dx = p2.X - p1.X; float dy = p2.Y - p1.Y; diff --git a/src/Exomia.Framework/Mathematics/Triangle2.cs b/src/Exomia.Framework/Mathematics/Triangle2.cs index bd6b3289..19b207d3 100644 --- a/src/Exomia.Framework/Mathematics/Triangle2.cs +++ b/src/Exomia.Framework/Mathematics/Triangle2.cs @@ -32,7 +32,7 @@ namespace Exomia.Framework.Mathematics /// /// The first y value. /// - [FieldOffset(4)] + [FieldOffset(4)] public readonly float Y1; /// @@ -44,13 +44,13 @@ namespace Exomia.Framework.Mathematics /// /// The second y value. /// - [FieldOffset(8)] + [FieldOffset(8)] public readonly float X2; /// /// The second x value. /// - [FieldOffset(12)] + [FieldOffset(12)] public readonly float Y2; /// @@ -62,13 +62,13 @@ namespace Exomia.Framework.Mathematics /// /// The third x value. /// - [FieldOffset(16)] + [FieldOffset(16)] public readonly float X3; /// /// The third y value. /// - [FieldOffset(20)] + [FieldOffset(20)] public readonly float Y3; /// @@ -76,7 +76,7 @@ namespace Exomia.Framework.Mathematics /// [FieldOffset(16)] public readonly Vector2 XY3; - + /// /// Initializes a new instance of the struct. /// @@ -86,7 +86,8 @@ namespace Exomia.Framework.Mathematics /// The second y value. /// The third x value. /// The third y value. - public Triangle2(float x1, float y1, float x2, float y2, float x3, float y3) : this() + public Triangle2(float x1, float y1, float x2, float y2, float x3, float y3) + : this() { X1 = x1; Y1 = y1; diff --git a/src/Exomia.Framework/Win32/Mem.cs b/src/Exomia.Framework/Win32/Mem.cs index e10c5a0f..31a240f5 100644 --- a/src/Exomia.Framework/Win32/Mem.cs +++ b/src/Exomia.Framework/Win32/Mem.cs @@ -52,7 +52,7 @@ public static extern void Move(void* dest, /// /// memset call - /// Sets the first num bytes of the block of memory pointed by ptr to the specified value + /// Sets the first num bytes of the block of memory pointed by ptr to the specified value /// (interpreted as an unsigned char). /// /// [in,out] destination addr. @@ -67,9 +67,10 @@ public static extern void Move(void* dest, public static extern void* Set(void* dest, int value, int count); - + /// - /// Resizes the given array with the given to the given . + /// Resizes the given array with the given to the given + /// . /// /// Generic type parameter. /// [in,out] The source array ptr. @@ -79,7 +80,7 @@ public static extern void Move(void* dest, public static void Resize(ref T* src, ref int srcLength, int newLength) where T : unmanaged { T* ptr = (T*)Marshal.AllocHGlobal(sizeof(T) * newLength); - Mem.Cpy(ptr, src, srcLength * sizeof(T)); + Cpy(ptr, src, srcLength * sizeof(T)); Marshal.FreeHGlobal(new IntPtr(src)); src = ptr;