From a7ef40a241f5e058793236a37ce532320b9511f1 Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sat, 4 Apr 2020 16:27:56 +0200 Subject: [PATCH 01/18] Remove unused usings. --- Everlook/Database/ClientDatabaseProvider.cs | 1 - Everlook/Viewport/Camera/ViewportCamera.cs | 1 - Everlook/Viewport/Rendering/Core/Texture2D.cs | 3 --- Everlook/Viewport/Rendering/RenderableWorldModel.cs | 1 - Everlook/Viewport/ViewportRenderer.cs | 1 - 5 files changed, 7 deletions(-) diff --git a/Everlook/Database/ClientDatabaseProvider.cs b/Everlook/Database/ClientDatabaseProvider.cs index e230b3d..6906d74 100644 --- a/Everlook/Database/ClientDatabaseProvider.cs +++ b/Everlook/Database/ClientDatabaseProvider.cs @@ -22,7 +22,6 @@ using System; using System.Collections.Generic; -using System.IO; using Warcraft.Core; using Warcraft.DBC; using Warcraft.DBC.Definitions; diff --git a/Everlook/Viewport/Camera/ViewportCamera.cs b/Everlook/Viewport/Camera/ViewportCamera.cs index 2cd42ec..512a0e0 100644 --- a/Everlook/Viewport/Camera/ViewportCamera.cs +++ b/Everlook/Viewport/Camera/ViewportCamera.cs @@ -25,7 +25,6 @@ using Everlook.Configuration; using Everlook.Viewport.Rendering.Core; using OpenTK; -using OpenTK.Graphics.ES10; namespace Everlook.Viewport.Camera { diff --git a/Everlook/Viewport/Rendering/Core/Texture2D.cs b/Everlook/Viewport/Rendering/Core/Texture2D.cs index 0b507da..b41d56d 100644 --- a/Everlook/Viewport/Rendering/Core/Texture2D.cs +++ b/Everlook/Viewport/Rendering/Core/Texture2D.cs @@ -23,8 +23,6 @@ using System; using System.Drawing; using System.Drawing.Imaging; -using System.IO; - using log4net; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; @@ -32,7 +30,6 @@ using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using Warcraft.BLP; -using Warcraft.Core.Structures; using GLPixelFormat = OpenTK.Graphics.OpenGL.PixelFormat; using Image = System.Drawing.Image; using Rectangle = System.Drawing.Rectangle; diff --git a/Everlook/Viewport/Rendering/RenderableWorldModel.cs b/Everlook/Viewport/Rendering/RenderableWorldModel.cs index ff1edb6..2245a27 100644 --- a/Everlook/Viewport/Rendering/RenderableWorldModel.cs +++ b/Everlook/Viewport/Rendering/RenderableWorldModel.cs @@ -34,7 +34,6 @@ using OpenTK; using Warcraft.WMO; using Warcraft.WMO.GroupFile; -using Warcraft.WMO.GroupFile.Chunks; using Warcraft.WMO.RootFile.Chunks; using BufferTarget = OpenTK.Graphics.OpenGL.BufferTarget; using BufferUsageHint = OpenTK.Graphics.OpenGL.BufferUsageHint; diff --git a/Everlook/Viewport/ViewportRenderer.cs b/Everlook/Viewport/ViewportRenderer.cs index e363984..f1671af 100644 --- a/Everlook/Viewport/ViewportRenderer.cs +++ b/Everlook/Viewport/ViewportRenderer.cs @@ -30,7 +30,6 @@ using Everlook.Viewport.Rendering.Interfaces; using Gdk; using log4net; -using OpenTK; using OpenTK.Graphics.OpenGL; using OpenTK.Input; From 6d7288092fe4a5ed6e0328b998c73f33918f8df0 Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sat, 4 Apr 2020 16:33:45 +0200 Subject: [PATCH 02/18] Upgrade a number of nuget packages, and swap out GtkSharp. --- .idea/.idea.Everlook/.idea/contentModel.xml | 2 +- Directory.Build.props | 2 +- Everlook/Everlook.csproj | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.idea/.idea.Everlook/.idea/contentModel.xml b/.idea/.idea.Everlook/.idea/contentModel.xml index 7b6b4ea..4064eb5 100644 --- a/.idea/.idea.Everlook/.idea/contentModel.xml +++ b/.idea/.idea.Everlook/.idea/contentModel.xml @@ -330,7 +330,7 @@ - + diff --git a/Directory.Build.props b/Directory.Build.props index d8f86ec..48212c1 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -89,7 +89,7 @@ - + diff --git a/Everlook/Everlook.csproj b/Everlook/Everlook.csproj index ca1baf7..c8991ff 100644 --- a/Everlook/Everlook.csproj +++ b/Everlook/Everlook.csproj @@ -55,19 +55,19 @@ - + - + - + - + From 87dad575248f982dd08cae4ff360a6293f6a6e87 Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sat, 4 Apr 2020 16:33:57 +0200 Subject: [PATCH 03/18] Explicitly close the dialog. --- Everlook/UI/MainWindow.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Everlook/UI/MainWindow.cs b/Everlook/UI/MainWindow.cs index 4dd85a5..4a99762 100644 --- a/Everlook/UI/MainWindow.cs +++ b/Everlook/UI/MainWindow.cs @@ -563,6 +563,7 @@ private async Task LoadGames() } } + dialog.Hide(); dialog.Destroy(); sw.Stop(); From 3021af9602fa0ea79d82e2c27f600672c6eaa79d Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sat, 4 Apr 2020 18:10:22 +0200 Subject: [PATCH 04/18] Begin initial porting to Silk.NET. --- .idea/.idea.Everlook/.idea/contentModel.xml | 6 + Everlook.sln.DotSettings | 1 + Everlook/Audio/AudioGroup.cs | 2 +- Everlook/Audio/AudioManager.cs | 2 +- Everlook/Audio/AudioSource.cs | 128 +++++++------ Everlook/Audio/IAudioAsset.cs | 6 +- Everlook/Audio/MP3/MP3AudioAsset.cs | 8 +- Everlook/Audio/Wave/WaveAudioAsset.cs | 8 +- Everlook/Everlook.csproj | 6 +- .../Shader/ShaderCompilationException.cs | 2 +- Everlook/Native/IGTKGLExt.cs | 42 +++++ Everlook/Program.cs | 77 ++------ Everlook/Silk/GDKGLSymbolLoader.cs | 71 +++++++ Everlook/UI/MainWindow.cs | 19 +- Everlook/UI/Widgets/ViewportArea.cs | 175 ++++-------------- Everlook/Utility/ExtensionMethods.cs | 60 +----- Everlook/Viewport/Camera/CameraMovement.cs | 2 + Everlook/Viewport/Camera/ViewportCamera.cs | 18 +- .../Rendering/Core/ActorInstanceSet.cs | 20 +- Everlook/Viewport/Rendering/Core/BaseGrid.cs | 11 +- Everlook/Viewport/Rendering/Core/Buffer.cs | 8 +- .../Rendering/Core/DynamicInterpolator.cs | 8 +- .../Rendering/Core/Lights/AmbientLight.cs | 4 +- .../Rendering/Core/Lights/DirectionalLight.cs | 3 +- Everlook/Viewport/Rendering/Core/Plane.cs | 2 +- .../Core/RenderableActorReference.cs | 4 +- .../Viewport/Rendering/Core/ShaderProgram.cs | 19 +- Everlook/Viewport/Rendering/Core/Texture2D.cs | 24 +-- Everlook/Viewport/Rendering/Core/Timeline.cs | 1 - Everlook/Viewport/Rendering/Core/Transform.cs | 12 +- .../Rendering/Core/VertexAttributePointer.cs | 2 +- .../Viewport/Rendering/Interfaces/IBuffer.cs | 6 +- .../IDefaultCameraPositionProvider.cs | 2 +- .../Interfaces/IInstancedRenderable.cs | 4 +- .../Rendering/Interfaces/IRenderable.cs | 4 +- Everlook/Viewport/Rendering/RenderCache.cs | 7 +- .../Rendering/RenderableBoundingBox.cs | 46 +++-- .../Viewport/Rendering/RenderableGameModel.cs | 52 +++--- .../Viewport/Rendering/RenderableImage.cs | 58 +++--- .../Rendering/RenderableWorldModel.cs | 58 +++--- .../Rendering/Shaders/BoundingBoxShader.cs | 5 +- .../Shaders/Components/AmbientLighting.cs | 1 + .../Shaders/Components/GlobalLighting.cs | 2 + .../Shaders/Components/SolidWireframe.cs | 1 + .../Rendering/Shaders/GameModelShader.cs | 16 +- .../Rendering/Shaders/Plain2DShader.cs | 2 + .../Rendering/Shaders/WorldModelShader.cs | 9 +- Everlook/Viewport/ViewportRenderer.cs | 11 +- 48 files changed, 498 insertions(+), 537 deletions(-) create mode 100644 Everlook/Native/IGTKGLExt.cs create mode 100644 Everlook/Silk/GDKGLSymbolLoader.cs diff --git a/.idea/.idea.Everlook/.idea/contentModel.xml b/.idea/.idea.Everlook/.idea/contentModel.xml index 4064eb5..b8221f4 100644 --- a/.idea/.idea.Everlook/.idea/contentModel.xml +++ b/.idea/.idea.Everlook/.idea/contentModel.xml @@ -213,12 +213,18 @@ + + + + + + diff --git a/Everlook.sln.DotSettings b/Everlook.sln.DotSettings index 1f6e240..4b98638 100644 --- a/Everlook.sln.DotSettings +++ b/Everlook.sln.DotSettings @@ -88,4 +88,5 @@ True True True + True True \ No newline at end of file diff --git a/Everlook/Audio/AudioGroup.cs b/Everlook/Audio/AudioGroup.cs index fe7c537..cc63b36 100644 --- a/Everlook/Audio/AudioGroup.cs +++ b/Everlook/Audio/AudioGroup.cs @@ -22,7 +22,7 @@ using System; using System.Collections.Generic; -using OpenTK; +using System.Numerics; namespace Everlook.Audio { diff --git a/Everlook/Audio/AudioManager.cs b/Everlook/Audio/AudioManager.cs index dd2a6b6..e8715fa 100644 --- a/Everlook/Audio/AudioManager.cs +++ b/Everlook/Audio/AudioManager.cs @@ -22,7 +22,7 @@ using System; using System.Collections.Generic; -using OpenTK.Audio; +using Silk.NET.OpenAL; namespace Everlook.Audio { diff --git a/Everlook/Audio/AudioSource.cs b/Everlook/Audio/AudioSource.cs index 9d200b4..7ed5759 100644 --- a/Everlook/Audio/AudioSource.cs +++ b/Everlook/Audio/AudioSource.cs @@ -21,12 +21,13 @@ // using System; +using System.Numerics; using System.Threading.Tasks; using Everlook.Audio.MP3; using Everlook.Audio.Wave; using Everlook.Explorer; -using OpenTK; -using OpenTK.Audio.OpenAL; +using JetBrains.Annotations; +using Silk.NET.OpenAL; using Warcraft.Core; using Warcraft.DBC.Definitions; @@ -35,16 +36,18 @@ namespace Everlook.Audio /// /// Represents a single audio source in 3D space. /// + [PublicAPI] public sealed class AudioSource : IDisposable, IEquatable { + private AL _al = AL.GetApi(); private IAudioAsset? _audioAsset; - private int _soundBufferID; - private int _soundSourceID; + private uint _soundBufferID; + private uint _soundSourceID; /// /// Gets the format of the current audio source. /// - public ALFormat SoundFormat { get; private set; } + public BufferFormat SoundFormat { get; private set; } /// /// Gets the sample rate of the current audio source. @@ -54,7 +57,14 @@ public sealed class AudioSource : IDisposable, IEquatable /// /// Gets the current state of the sound source. /// - public ALSourceState State => AL.GetSourceState(_soundSourceID); + public SourceState State + { + get + { + _al.GetSourceProperty(_soundSourceID, GetSourceInteger.SourceState, out var value); + return (SourceState)value; + } + } /// /// Gets or sets the offset of the audio source into the sound (in seconds). @@ -63,10 +73,10 @@ public float TimeOffset { get { - AL.GetSource(_soundSourceID, ALSourcef.SecOffset, out var value); + _al.GetSourceProperty(_soundSourceID, SourceFloat.SecOffset, out var value); return value; } - set => AL.Source(_soundSourceID, ALSourcef.SecOffset, value); + set => _al.SetSourceProperty(_soundSourceID, SourceFloat.SecOffset, value); } /// @@ -76,10 +86,10 @@ public bool Looping { get { - AL.GetSource(_soundSourceID, ALSourceb.Looping, out var value); - return value; + _al.GetSourceProperty(_soundSourceID, SourceBoolean.Looping, out var temp); + return temp > 0; } - set => AL.Source(_soundSourceID, ALSourceb.Looping, value); + set => _al.SetSourceProperty(_soundSourceID, SourceBoolean.Looping, value ? 1 : 0); } /// @@ -89,10 +99,10 @@ public Vector3 Position { get { - AL.GetSource(_soundSourceID, ALSource3f.Position, out var value); + _al.GetSourceProperty(_soundSourceID, SourceVector3.Position, out var value); return value; } - set => AL.Source(_soundSourceID, ALSource3f.Position, ref value); + set => _al.SetSourceProperty(_soundSourceID, SourceVector3.Position, value); } /// @@ -102,10 +112,10 @@ public Vector3 Direction { get { - AL.GetSource(_soundSourceID, ALSource3f.Direction, out var value); + _al.GetSourceProperty(_soundSourceID, SourceVector3.Direction, out var value); return value; } - set => AL.Source(_soundSourceID, ALSource3f.Direction, ref value); + set => _al.SetSourceProperty(_soundSourceID, SourceVector3.Direction, value); } /// @@ -115,10 +125,10 @@ public Vector3 Velocity { get { - AL.GetSource(_soundSourceID, ALSource3f.Direction, out var value); + _al.GetSourceProperty(_soundSourceID, SourceVector3.Direction, out var value); return value; } - set => AL.Source(_soundSourceID, ALSource3f.Direction, ref value); + set => _al.SetSourceProperty(_soundSourceID, SourceVector3.Direction, value); } /// @@ -128,10 +138,10 @@ public bool RelativePositioning { get { - AL.GetSource(_soundSourceID, ALSourceb.SourceRelative, out var value); - return value; + _al.GetSourceProperty(_soundSourceID, SourceBoolean.SourceRelative, out var value); + return value > 0; } - set => AL.Source(_soundSourceID, ALSourceb.SourceRelative, value); + set => _al.SetSourceProperty(_soundSourceID, SourceBoolean.SourceRelative, value ? 1 : 0); } /// @@ -142,10 +152,10 @@ public float Attenuation { get { - AL.GetSource(_soundSourceID, ALSourcef.MaxDistance, out var value); + _al.GetSourceProperty(_soundSourceID, SourceFloat.MaxDistance, out var value); return value; } - set => AL.Source(_soundSourceID, ALSourcef.MaxDistance, value); + set => _al.SetSourceProperty(_soundSourceID, SourceFloat.MaxDistance, value); } /// @@ -155,10 +165,10 @@ public float MinGain { get { - AL.GetSource(_soundSourceID, ALSourcef.MinGain, out var value); + _al.GetSourceProperty(_soundSourceID, SourceFloat.MinGain, out var value); return value; } - set => AL.Source(_soundSourceID, ALSourcef.MinGain, value); + set => _al.SetSourceProperty(_soundSourceID, SourceFloat.MinGain, value); } /// @@ -168,10 +178,10 @@ public float MaxGain { get { - AL.GetSource(_soundSourceID, ALSourcef.MaxGain, out var value); + _al.GetSourceProperty(_soundSourceID, SourceFloat.MaxGain, out var value); return value; } - set => AL.Source(_soundSourceID, ALSourcef.MaxGain, value); + set => _al.SetSourceProperty(_soundSourceID, SourceFloat.MaxGain, value); } /// @@ -181,10 +191,10 @@ public float ConeOuterGain { get { - AL.GetSource(_soundSourceID, ALSourcef.ConeOuterGain, out var value); + _al.GetSourceProperty(_soundSourceID, SourceFloat.ConeOuterGain, out var value); return value; } - set => AL.Source(_soundSourceID, ALSourcef.ConeOuterGain, value); + set => _al.SetSourceProperty(_soundSourceID, SourceFloat.ConeOuterGain, value); } /// @@ -194,10 +204,10 @@ public float ConeInnerAngle { get { - AL.GetSource(_soundSourceID, ALSourcef.ConeInnerAngle, out var value); + _al.GetSourceProperty(_soundSourceID, SourceFloat.ConeInnerAngle, out var value); return value; } - set => AL.Source(_soundSourceID, ALSourcef.ConeInnerAngle, value); + set => _al.SetSourceProperty(_soundSourceID, SourceFloat.ConeInnerAngle, value); } /// @@ -207,10 +217,10 @@ public float ConeOuterAngle { get { - AL.GetSource(_soundSourceID, ALSourcef.ConeOuterAngle, out var value); + _al.GetSourceProperty(_soundSourceID, SourceFloat.ConeOuterAngle, out var value); return value; } - set => AL.Source(_soundSourceID, ALSourcef.ConeOuterAngle, value); + set => _al.SetSourceProperty(_soundSourceID, SourceFloat.ConeOuterAngle, value); } /// @@ -220,10 +230,10 @@ public float Pitch { get { - AL.GetSource(_soundSourceID, ALSourcef.Pitch, out var value); + _al.GetSourceProperty(_soundSourceID, SourceFloat.Pitch, out var value); return value; } - set => AL.Source(_soundSourceID, ALSourcef.Pitch, value); + set => _al.SetSourceProperty(_soundSourceID, SourceFloat.Pitch, value); } /// @@ -234,10 +244,10 @@ public float Gain { get { - AL.GetSource(_soundSourceID, ALSourcef.Gain, out var value); + _al.GetSourceProperty(_soundSourceID, SourceFloat.Gain, out var value); return value; } - set => AL.Source(_soundSourceID, ALSourcef.Gain, value); + set => _al.SetSourceProperty(_soundSourceID, SourceFloat.Gain, value); } /// @@ -247,10 +257,10 @@ public float RolloffFactor { get { - AL.GetSource(_soundSourceID, ALSourcef.RolloffFactor, out var value); + _al.GetSourceProperty(_soundSourceID, SourceFloat.RolloffFactor, out var value); return value; } - set => AL.Source(_soundSourceID, ALSourcef.RolloffFactor, value); + set => _al.SetSourceProperty(_soundSourceID, SourceFloat.RolloffFactor, value); } /// @@ -262,10 +272,10 @@ public float ReferenceDistance { get { - AL.GetSource(_soundSourceID, ALSourcef.ReferenceDistance, out var value); + _al.GetSourceProperty(_soundSourceID, SourceFloat.ReferenceDistance, out var value); return value; } - set => AL.Source(_soundSourceID, ALSourcef.ReferenceDistance, value); + set => _al.SetSourceProperty(_soundSourceID, SourceFloat.ReferenceDistance, value); } /// @@ -313,8 +323,8 @@ public static AudioSource CreateFromSoundEntry(SoundEntriesRecord soundEntry) /// public void Play() { - AL.SourceRewind(_soundSourceID); - AL.SourcePlay(_soundSourceID); + _al.SourceRewind(_soundSourceID); + _al.SourcePlay(_soundSourceID); } /// @@ -322,7 +332,7 @@ public void Play() /// public void Resume() { - AL.SourcePlay(_soundSourceID); + _al.SourcePlay(_soundSourceID); } /// @@ -330,7 +340,7 @@ public void Resume() /// public void Pause() { - AL.SourcePause(_soundSourceID); + _al.SourcePause(_soundSourceID); } /// @@ -338,8 +348,8 @@ public void Pause() /// public void Stop() { - AL.SourceStop(_soundSourceID); - AL.SourceRewind(_soundSourceID); + _al.SourceStop(_soundSourceID); + _al.SourceRewind(_soundSourceID); } /// @@ -381,11 +391,19 @@ public async Task SetAudioAsync(FileReference fileReference) this.SampleRate = _audioAsset.SampleRate; // Create new AL data - _soundBufferID = AL.GenBuffer(); - _soundSourceID = AL.GenSource(); + _soundBufferID = _al.GenBuffer(); + _soundSourceID = _al.GenSource(); + + unsafe + { + fixed (void* ptr = soundData) + { + _al.BufferData(_soundBufferID, this.SoundFormat, ptr, soundData.Length, this.SampleRate); + } + } - AL.BufferData(_soundBufferID, this.SoundFormat, soundData, soundData.Length, this.SampleRate); - AL.Source(_soundSourceID, ALSourcei.Buffer, _soundBufferID); + // TODO: Use correct overload + _al.SetSourceProperty(_soundSourceID, SourceInteger.Buffer, (int)_soundBufferID); } /// @@ -393,10 +411,10 @@ public async Task SetAudioAsync(FileReference fileReference) /// private void ClearAudio() { - AL.SourceStop(_soundSourceID); + _al.SourceStop(_soundSourceID); - AL.DeleteSource(_soundSourceID); - AL.DeleteBuffer(_soundBufferID); + _al.DeleteSource(_soundSourceID); + _al.DeleteBuffer(_soundBufferID); _audioAsset?.Dispose(); } @@ -413,11 +431,11 @@ public override int GetHashCode() { unchecked { - var hash = 17; + long hash = 17; hash *= 23 + _soundBufferID; hash *= 23 + _soundSourceID; - return hash; + return (int)hash; } } diff --git a/Everlook/Audio/IAudioAsset.cs b/Everlook/Audio/IAudioAsset.cs index d8dfec2..21b3e10 100644 --- a/Everlook/Audio/IAudioAsset.cs +++ b/Everlook/Audio/IAudioAsset.cs @@ -22,7 +22,7 @@ using System; using System.IO; -using OpenTK.Audio.OpenAL; +using Silk.NET.OpenAL; namespace Everlook.Audio { @@ -32,9 +32,9 @@ namespace Everlook.Audio public interface IAudioAsset : IDisposable { /// - /// Gets the that the PCM data is in. + /// Gets the that the PCM data is in. /// - ALFormat Format { get; } + BufferFormat Format { get; } /// /// Gets the raw PCM data of the audio asset. diff --git a/Everlook/Audio/MP3/MP3AudioAsset.cs b/Everlook/Audio/MP3/MP3AudioAsset.cs index 8b26ecf..ec8c1d8 100644 --- a/Everlook/Audio/MP3/MP3AudioAsset.cs +++ b/Everlook/Audio/MP3/MP3AudioAsset.cs @@ -25,7 +25,7 @@ using System.Threading.Tasks; using Everlook.Explorer; using MP3Sharp; -using OpenTK.Audio.OpenAL; +using Silk.NET.OpenAL; using Warcraft.Core; namespace Everlook.Audio.MP3 @@ -41,7 +41,7 @@ public sealed class MP3AudioAsset : IAudioAsset private bool _isDisposed; /// - public ALFormat Format + public BufferFormat Format { get { @@ -49,11 +49,11 @@ public ALFormat Format { case 1: { - return ALFormat.Mono16; + return BufferFormat.Mono16; } case 2: { - return ALFormat.Stereo16; + return BufferFormat.Stereo16; } default: { diff --git a/Everlook/Audio/Wave/WaveAudioAsset.cs b/Everlook/Audio/Wave/WaveAudioAsset.cs index 42fa641..e511ee5 100644 --- a/Everlook/Audio/Wave/WaveAudioAsset.cs +++ b/Everlook/Audio/Wave/WaveAudioAsset.cs @@ -24,7 +24,7 @@ using System.IO; using System.Threading.Tasks; using Everlook.Explorer; -using OpenTK.Audio.OpenAL; +using Silk.NET.OpenAL; using Warcraft.Core; namespace Everlook.Audio.Wave @@ -40,7 +40,7 @@ public sealed class WaveAudioAsset : IAudioAsset private bool _isDisposed; /// - public ALFormat Format + public BufferFormat Format { get { @@ -48,11 +48,11 @@ public ALFormat Format { case 1: { - return this.BitsPerSample == 8 ? ALFormat.Mono8 : ALFormat.Mono16; + return this.BitsPerSample == 8 ? BufferFormat.Mono8 : BufferFormat.Mono16; } case 2: { - return this.BitsPerSample == 8 ? ALFormat.Stereo8 : ALFormat.Stereo16; + return this.BitsPerSample == 8 ? BufferFormat.Stereo8 : BufferFormat.Stereo16; } default: { diff --git a/Everlook/Everlook.csproj b/Everlook/Everlook.csproj index c8991ff..28c1457 100644 --- a/Everlook/Everlook.csproj +++ b/Everlook/Everlook.csproj @@ -54,6 +54,7 @@ + @@ -61,10 +62,13 @@ - + + + + diff --git a/Everlook/Exceptions/Shader/ShaderCompilationException.cs b/Everlook/Exceptions/Shader/ShaderCompilationException.cs index da7fac2..68af3d3 100644 --- a/Everlook/Exceptions/Shader/ShaderCompilationException.cs +++ b/Everlook/Exceptions/Shader/ShaderCompilationException.cs @@ -21,7 +21,7 @@ // using System; -using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; namespace Everlook.Exceptions.Shader { diff --git a/Everlook/Native/IGTKGLExt.cs b/Everlook/Native/IGTKGLExt.cs new file mode 100644 index 0000000..d3447a0 --- /dev/null +++ b/Everlook/Native/IGTKGLExt.cs @@ -0,0 +1,42 @@ +// +// IGTKGLExt.cs +// +// Author: +// Jarl Gullberg +// +// Copyright (c) 2017 Jarl Gullberg +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +using System; +using AdvancedDLSupport; + +// ReSharper disable ExplicitCallerInfoArgument +namespace Everlook.Native +{ + /// + /// Represents the native interface to the GTK GL Extensions library. + /// + public interface IGTKGLExt + { + /// + /// Gets a function pointer to the named symbol via GDK. + /// + /// The name of the symbol. + /// A pointer to the symbol, or IntPtr.Zero. + [NativeSymbol("gdk_gl_get_proc_address")] + IntPtr GetProcAddress(string functionName); + } +} diff --git a/Everlook/Program.cs b/Everlook/Program.cs index c42806d..a432bdf 100644 --- a/Everlook/Program.cs +++ b/Everlook/Program.cs @@ -25,12 +25,13 @@ using System.IO; using System.Runtime.InteropServices; using Everlook.Explorer; +using Everlook.Silk; using Everlook.UI; using Everlook.Utility; using FileTree.Tree.Serialized; using GLib; using log4net; -using OpenTK; +using Silk.NET.Core.Platform; using Application = Gtk.Application; namespace Everlook @@ -66,57 +67,27 @@ public static void Main() Log.Info("----------------"); Log.Info("Initializing Everlook..."); - Log.Info("Initializing OpenTK..."); + Log.Info("Initializing Silk..."); + SilkManager.Register(new GDKGLSymbolLoader()); - // OpenGL - var toolkitOptions = new ToolkitOptions - { - Backend = PlatformBackend.PreferNative, - EnableHighResolution = true - }; - - using (Toolkit.Init(toolkitOptions)) - { - Log.Info($"OpenTK initialized using the {GetOpenTKBackend()} backend."); - - Log.Info("Initializing GTK..."); - - // Bind any unhandled exceptions in the GTK UI so that they are logged. - ExceptionManager.UnhandledException += OnGLibUnhandledException; - - Log.Info("Registering treeview types with the native backend..."); - var nodeType = (GType)typeof(SerializedNode); - GType.Register(nodeType, typeof(SerializedNode)); + Log.Info("Initializing GTK..."); - var referenceType = (GType)typeof(FileReference); - GType.Register(referenceType, typeof(FileReference)); + // Bind any unhandled exceptions in the GTK UI so that they are logged. + ExceptionManager.UnhandledException += OnGLibUnhandledException; - // GTK - IconManager.LoadEmbeddedIcons(); - Application.Init(); - var win = MainWindow.Create(); - win.Show(); - Application.Run(); - } - } - - /// - /// Gets the backend used by OpenTK. - /// - /// The name of the backend. - private static string GetOpenTKBackend() - { - if (OpenTK.Configuration.RunningOnSdl2) - { - return "SDL2"; - } + Log.Info("Registering treeview types with the native backend..."); + var nodeType = (GType)typeof(SerializedNode); + GType.Register(nodeType, typeof(SerializedNode)); - if (OpenTK.Configuration.RunningOnX11) - { - return "X11"; - } + var referenceType = (GType)typeof(FileReference); + GType.Register(referenceType, typeof(FileReference)); - return "native"; + // GTK + IconManager.LoadEmbeddedIcons(); + Application.Init(); + var win = MainWindow.Create(); + win.Show(); + Application.Run(); } /// @@ -170,18 +141,6 @@ private static void OnUnhandledException(object? sender, UnhandledExceptionEvent ); break; } - case GraphicsException _: - { - Log.Fatal - ( - "Some type of graphics error occurred. On macOS, this is usally indicative of an OpenGL " + - "context which doesn't meet Everlook's requirements. Please note that Everlook requires at " + - "least OpenGL 3.3.\n" + - "If you're running via XQuartz, please note that XQuartz does not provide contexts above " + - "OpenGL 2.1." - ); - break; - } } Log.Fatal($"Exception type: {unhandledException!.GetType().FullName}"); diff --git a/Everlook/Silk/GDKGLSymbolLoader.cs b/Everlook/Silk/GDKGLSymbolLoader.cs new file mode 100644 index 0000000..d31930f --- /dev/null +++ b/Everlook/Silk/GDKGLSymbolLoader.cs @@ -0,0 +1,71 @@ +// +// GDKGLSymbolLoader.cs +// +// Author: +// Jarl Gullberg +// +// Copyright (c) 2017 Jarl Gullberg +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +using System; +using System.Runtime.InteropServices; +using AdvancedDLSupport; +using Everlook.Native; +using Silk.NET.Core.Loader; + +namespace Everlook.Silk +{ + /// + /// Handles loading OpenGL symbols via GDK. + /// + public class GDKGLSymbolLoader : GLSymbolLoader + { + private readonly IGTKGLExt _gtkglExt; + + /// + /// Initializes a new instance of the class. + /// + public GDKGLSymbolLoader() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + _gtkglExt = NativeLibraryBuilder.Default.ActivateInterface("libgtkglext-x11-1.0"); + } + else + { + _gtkglExt = NativeLibraryBuilder.Default.ActivateInterface("gtkglext-1.0"); + } + } + + /// + protected override IntPtr CoreLoadFunctionPointer(IntPtr handle, string functionName) + { + var glFunction = _gtkglExt.GetProcAddress(functionName); + if (glFunction != IntPtr.Zero) + { + return glFunction; + } + + var systemFunction = this.UnderlyingLoader.LoadFunctionPointer(handle, functionName); + if (systemFunction != IntPtr.Zero) + { + return systemFunction; + } + + throw new SymbolLoadingException(); + } + } +} diff --git a/Everlook/UI/MainWindow.cs b/Everlook/UI/MainWindow.cs index 4a99762..54c917e 100644 --- a/Everlook/UI/MainWindow.cs +++ b/Everlook/UI/MainWindow.cs @@ -43,8 +43,6 @@ using GLib; using Gtk; using log4net; -using OpenTK.Graphics; -using OpenTK.Input; using Warcraft.Core; using static Everlook.Utility.DataLoadingDelegates; @@ -126,18 +124,7 @@ private MainWindow(Builder builder, IntPtr handle) _uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); _fileLoadingCancellationSource = new CancellationTokenSource(); - var graphicsMode = new GraphicsMode - ( - new ColorFormat(24), - 24, - 0, - 4, - 0, - 2, - false - ); - - _viewportWidget = new ViewportArea(graphicsMode, 3, 3, GraphicsContextFlags.Default) + _viewportWidget = new ViewportArea(3, 3) { AutoRender = true, CanFocus = true @@ -904,8 +891,8 @@ private void OnViewportButtonPressed(object o, ButtonPressEventArgs args) _viewportWidget.GrabFocus(); - _renderingEngine.InitialMouseX = Mouse.GetCursorState().X; - _renderingEngine.InitialMouseY = Mouse.GetCursorState().Y; + _renderingEngine.InitialMouseX = args.Event.X; + _renderingEngine.InitialMouseY = args.Event.Y; _renderingEngine.WantsToMove = true; } diff --git a/Everlook/UI/Widgets/ViewportArea.cs b/Everlook/UI/Widgets/ViewportArea.cs index 3fe4680..f518ec9 100644 --- a/Everlook/UI/Widgets/ViewportArea.cs +++ b/Everlook/UI/Widgets/ViewportArea.cs @@ -22,11 +22,8 @@ using System; using System.ComponentModel; -using System.Threading; using Gdk; using Gtk; -using OpenTK; -using OpenTK.Graphics; namespace Everlook.UI.Widgets { @@ -38,10 +35,12 @@ namespace Everlook.UI.Widgets [ToolboxItem(true)] public class ViewportArea : GLArea { - private static int _graphicsContextCount; - private static bool _isSharedContextInitialized; + private readonly bool _isDebugEnabled; + private readonly bool _isForwardCompatible; + private readonly bool _withDepthBuffer; + private readonly bool _withStencilBuffer; + private readonly bool _withAlpha; - private IGraphicsContext? _tkGraphicsContext; private bool _isInitialized; /// @@ -55,69 +54,44 @@ public class ViewportArea : GLArea public double DeltaTime { get; private set; } /// - /// Gets the context flags used in the creation of this widget. + /// Called when this has finished initializing. /// - public GraphicsContextFlags ContextFlags { get; } - - /// - /// Initializes a new instance of the class. - /// - public ViewportArea() - : this(GraphicsMode.Default) - { - } - - /// - /// Initializes a new instance of the class. The given is - /// used to hint the area about context creation. - /// - /// - /// The which the widget should be constructed with. - /// - public ViewportArea(GraphicsMode graphicsMode) - : this(graphicsMode, 1, 0, GraphicsContextFlags.Default) - { - } + public event EventHandler? Initialized; /// /// Initializes a new instance of the class. /// - /// - /// The which the widget should be constructed with. - /// - /// The major OpenGL version to attempt to initialize. - /// The minor OpenGL version to attempt to initialize. - /// - /// Any flags which should be used during initialization of the . - /// + /// The major version of OpenGL to request. + /// The minor version of OpenGL to request. + /// Whether the OpenGL context should be debuggable. + /// Whether the OpenGL context should be forward compatible. + /// Whether the viewport area should have a depth buffer. + /// Whether the viewport area should have a stencil buffer. + /// Whether the viewport area should have an alpha channel. public ViewportArea ( - GraphicsMode graphicsMode, int glVersionMajor, int glVersionMinor, - GraphicsContextFlags contextFlags + bool isDebugEnabled = false, + bool isForwardCompatible = false, + bool withDepthBuffer = true, + bool withStencilBuffer = true, + bool withAlpha = true ) { - this.ContextFlags = contextFlags; + _isDebugEnabled = isDebugEnabled; + _isForwardCompatible = isForwardCompatible; + _withDepthBuffer = withDepthBuffer; + _withStencilBuffer = withStencilBuffer; + _withAlpha = withAlpha; AddTickCallback(UpdateFrameTime); SetRequiredVersion(glVersionMajor, glVersionMinor); - if (graphicsMode.Depth > 0) - { - this.HasDepthBuffer = true; - } - - if (graphicsMode.Stencil > 0) - { - this.HasStencilBuffer = true; - } - - if (graphicsMode.ColorFormat.Alpha > 0) - { - this.HasAlpha = true; - } + this.HasDepthBuffer = _withDepthBuffer; + this.HasStencilBuffer = _withStencilBuffer; + this.HasAlpha = _withAlpha; } /// @@ -152,21 +126,17 @@ protected override GLContext OnCreateContext() GetRequiredVersion(out var major, out var minor); gdkGLContext.SetRequiredVersion(major, minor); - - gdkGLContext.DebugEnabled = this.ContextFlags.HasFlag(GraphicsContextFlags.Debug); - gdkGLContext.ForwardCompatible = this.ContextFlags.HasFlag(GraphicsContextFlags.ForwardCompatible); + gdkGLContext.DebugEnabled = _isDebugEnabled; + gdkGLContext.ForwardCompatible = _isForwardCompatible; gdkGLContext.Realize(); return gdkGLContext; } - /// - public override void Destroy() + /// + protected override void OnDestroyed() { - GC.SuppressFinalize(this); Dispose(true); - - base.Destroy(); } /// @@ -180,53 +150,6 @@ protected override void Dispose(bool disposing) } MakeCurrent(); - OnShuttingDown(); - if (!GraphicsContext.ShareContexts || (Interlocked.Decrement(ref _graphicsContextCount) != 0)) - { - return; - } - - OnGraphicsContextShuttingDown(); - _isSharedContextInitialized = false; - } - - /// - /// Called when the first is created in the case where - /// GraphicsContext.ShareContexts == true; - /// - public static event EventHandler? GraphicsContextInitialized; - - /// - /// Called when the first is being destroyed in the case where - /// GraphicsContext.ShareContext == true; - /// - public static event EventHandler? GraphicsContextShuttingDown; - - /// - /// Called when this has finished initializing and has a valid - /// . - /// - public event EventHandler? Initialized; - - /// - /// Called when this is being disposed. - /// - public event EventHandler? ShuttingDown; - - /// - /// Invokes the event. - /// - private static void OnGraphicsContextInitialized() - { - GraphicsContextInitialized?.Invoke(null, EventArgs.Empty); - } - - /// - /// Invokes the event. - /// - private static void OnGraphicsContextShuttingDown() - { - GraphicsContextShuttingDown?.Invoke(null, EventArgs.Empty); } /// @@ -237,14 +160,6 @@ protected virtual void OnInitialized() this.Initialized?.Invoke(this, EventArgs.Empty); } - /// - /// Invokes the event. - /// - protected virtual void OnShuttingDown() - { - this.ShuttingDown?.Invoke(this, EventArgs.Empty); - } - /// protected override bool OnDrawn(Cairo.Context cr) { @@ -258,8 +173,7 @@ protected override bool OnDrawn(Cairo.Context cr) } /// - /// Initializes the with its given values and creates a - /// . + /// Initializes the with its given values. /// private void Initialize() { @@ -268,31 +182,6 @@ private void Initialize() // Make the GDK GL context current MakeCurrent(); - // Create a dummy context that will grab the GdkGLContext that is current on the thread - _tkGraphicsContext = new GraphicsContext(ContextHandle.Zero, null); - - if (this.ContextFlags.HasFlag(GraphicsContextFlags.Debug)) - { - _tkGraphicsContext.ErrorChecking = true; - } - - if (GraphicsContext.ShareContexts) - { - Interlocked.Increment(ref _graphicsContextCount); - - if (!_isSharedContextInitialized) - { - _isSharedContextInitialized = true; - ((IGraphicsContextInternal)_tkGraphicsContext).LoadAll(); - OnGraphicsContextInitialized(); - } - } - else - { - ((IGraphicsContextInternal)_tkGraphicsContext).LoadAll(); - OnGraphicsContextInitialized(); - } - OnInitialized(); } } diff --git a/Everlook/Utility/ExtensionMethods.cs b/Everlook/Utility/ExtensionMethods.cs index 277d5fc..8c28941 100644 --- a/Everlook/Utility/ExtensionMethods.cs +++ b/Everlook/Utility/ExtensionMethods.cs @@ -22,9 +22,9 @@ using System; using System.Collections.Generic; +using System.Numerics; using Everlook.Explorer; using Gdk; -using OpenTK; using Warcraft.Core.Structures; namespace Everlook.Utility @@ -53,7 +53,7 @@ public static void ClearPages(this Gtk.Notebook notebook) /// /// Converts any non-native path separators to the current native path separator, - /// e.g backslashes to forwardslashes on *nix, and vice versa. + /// e.g backslashes to forward slashes on *nix, and vice versa. /// /// The path. /// Input path. @@ -97,46 +97,6 @@ public static Pixbuf GetIcon(this FileReference fileReference) return IconManager.GetIconForFiletype(fileReference.FilePath); } - /// - /// Converts the current OpenGL vector to a Warcraft vector structure. - /// - /// An -type vector. - /// A System.Numerics vector. - public static System.Numerics.Vector3 ToSystemVector(this Vector3 vector3) - { - return new System.Numerics.Vector3(vector3.X, vector3.Y, vector3.Z); - } - - /// - /// Converts the current Warcraft vector to an OpenGL vector structure. - /// - /// A -type vector. - /// An OpenTK vector. - public static Vector3 ToOpenGLVector(this System.Numerics.Vector3 vector3) - { - return new Vector3(vector3.X, vector3.Y, vector3.Z); - } - - /// - /// Converts the current Warcraft vector to an OpenGL vector structure. - /// - /// A -type vector. - /// An OpenTK vector. - public static Vector2 ToOpenGLVector(this System.Numerics.Vector2 vector2) - { - return new Vector2(vector2.X, vector2.Y); - } - - /// - /// Converts the current Warcraft quaternion to an OpenGL quaternion structure. - /// - /// A -type vector. - /// An OpenTK vector. - public static Quaternion ToOpenGLQuaternion(this System.Numerics.Quaternion quaternion) - { - return new Quaternion(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W); - } - /// /// Gets the coordinates of all corners in the box. /// @@ -150,15 +110,15 @@ public static IEnumerable GetCorners(this Box box) var xDiff = top.X - bottom.X; var yDiff = top.Y - bottom.Y; - yield return top.ToOpenGLVector(); - yield return top.ToOpenGLVector() - new Vector3(xDiff, 0, 0); - yield return top.ToOpenGLVector() - new Vector3(xDiff, yDiff, 0); - yield return top.ToOpenGLVector() - new Vector3(0, yDiff, 0); + yield return top; + yield return top - new Vector3(xDiff, 0, 0); + yield return top - new Vector3(xDiff, yDiff, 0); + yield return top - new Vector3(0, yDiff, 0); - yield return bottom.ToOpenGLVector(); - yield return bottom.ToOpenGLVector() + new Vector3(xDiff, 0, 0); - yield return bottom.ToOpenGLVector() + new Vector3(xDiff, yDiff, 0); - yield return bottom.ToOpenGLVector() + new Vector3(0, yDiff, 0); + yield return bottom; + yield return bottom + new Vector3(xDiff, 0, 0); + yield return bottom + new Vector3(xDiff, yDiff, 0); + yield return bottom + new Vector3(0, yDiff, 0); } } } diff --git a/Everlook/Viewport/Camera/CameraMovement.cs b/Everlook/Viewport/Camera/CameraMovement.cs index 358c22f..7e8a2dc 100644 --- a/Everlook/Viewport/Camera/CameraMovement.cs +++ b/Everlook/Viewport/Camera/CameraMovement.cs @@ -21,7 +21,9 @@ // using System; +using System.Numerics; using Everlook.Configuration; +using Gdk; using OpenTK; using OpenTK.Input; diff --git a/Everlook/Viewport/Camera/ViewportCamera.cs b/Everlook/Viewport/Camera/ViewportCamera.cs index 512a0e0..abb4aae 100644 --- a/Everlook/Viewport/Camera/ViewportCamera.cs +++ b/Everlook/Viewport/Camera/ViewportCamera.cs @@ -22,9 +22,9 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.Numerics; using Everlook.Configuration; using Everlook.Viewport.Rendering.Core; -using OpenTK; namespace Everlook.Viewport.Camera { @@ -196,13 +196,13 @@ private void RecalculateInternals() /// /// Gets the calculated projection matrix for this camera, using the values contained inside it. /// - /// A projection matrix. - public Matrix4 GetProjectionMatrix() + /// A projection matrix. + public Matrix4x4 GetProjectionMatrix() { - Matrix4 projectionMatrix; + Matrix4x4 projectionMatrix; if (this.Projection == ProjectionType.Orthographic) { - projectionMatrix = Matrix4.CreateOrthographic + projectionMatrix = Matrix4x4.CreateOrthographic ( this.ViewportWidth, this.ViewportHeight, @@ -213,7 +213,7 @@ public Matrix4 GetProjectionMatrix() else { var aspectRatio = (float)this.ViewportWidth / this.ViewportHeight; - projectionMatrix = Matrix4.CreatePerspectiveFieldOfView + projectionMatrix = Matrix4x4.CreatePerspectiveFieldOfView ( MathHelper.DegreesToRadians((float)EverlookConfiguration.Instance.CameraFOV), aspectRatio, @@ -228,10 +228,10 @@ public Matrix4 GetProjectionMatrix() /// /// Gets the view matrix of this camera (i.e, where it is looking). /// - /// A view matrix. - public Matrix4 GetViewMatrix() + /// A view matrix. + public Matrix4x4 GetViewMatrix() { - return Matrix4.LookAt + return Matrix4x4.LookAt ( this.Position, this.Position + this.LookDirectionVector, diff --git a/Everlook/Viewport/Rendering/Core/ActorInstanceSet.cs b/Everlook/Viewport/Rendering/Core/ActorInstanceSet.cs index 9eee907..b5e57b6 100644 --- a/Everlook/Viewport/Rendering/Core/ActorInstanceSet.cs +++ b/Everlook/Viewport/Rendering/Core/ActorInstanceSet.cs @@ -23,16 +23,16 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Numerics; using System.Runtime.InteropServices; using Everlook.Viewport.Camera; using Everlook.Viewport.Rendering.Interfaces; -using OpenTK; -using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; namespace Everlook.Viewport.Rendering.Core { /// - /// Represets a set of actor instances, differing by their transforms. + /// Represents a set of actor instances, differing by their transforms. /// /// A renderable supporting instanced rendering. public class ActorInstanceSet : IRenderable, IBoundedModel @@ -64,7 +64,7 @@ public bool ShouldRenderBounds /// public int Count => _instanceTransforms.Count; - private Buffer? _instanceModelMatrices; + private Buffer? _instanceModelMatrices; private List _instanceTransforms; @@ -92,26 +92,26 @@ public void SetInstances(IEnumerable instanceTransforms) /// public void Initialize() { - _instanceModelMatrices = new Buffer(BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw); + _instanceModelMatrices = new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw); _instanceModelMatrices.AttachAttributePointer ( - new VertexAttributePointer(6, 4, VertexAttribPointerType.Float, Marshal.SizeOf(), 0) + new VertexAttributePointer(6, 4, VertexAttribPointerType.Float, Marshal.SizeOf(), 0) ); _instanceModelMatrices.AttachAttributePointer ( - new VertexAttributePointer(7, 4, VertexAttribPointerType.Float, Marshal.SizeOf(), 16) + new VertexAttributePointer(7, 4, VertexAttribPointerType.Float, Marshal.SizeOf(), 16) ); _instanceModelMatrices.AttachAttributePointer ( - new VertexAttributePointer(8, 4, VertexAttribPointerType.Float, Marshal.SizeOf(), 32) + new VertexAttributePointer(8, 4, VertexAttribPointerType.Float, Marshal.SizeOf(), 32) ); _instanceModelMatrices.AttachAttributePointer ( - new VertexAttributePointer(9, 4, VertexAttribPointerType.Float, Marshal.SizeOf(), 48) + new VertexAttributePointer(9, 4, VertexAttribPointerType.Float, Marshal.SizeOf(), 48) ); _instanceModelMatrices.Bind(); @@ -127,7 +127,7 @@ public void Initialize() } /// - public void Render(Matrix4 viewMatrix, Matrix4 projectionMatrix, ViewportCamera camera) + public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCamera camera) { if (!this.IsInitialized || _instanceModelMatrices is null) { diff --git a/Everlook/Viewport/Rendering/Core/BaseGrid.cs b/Everlook/Viewport/Rendering/Core/BaseGrid.cs index 3ae30f1..bc20f30 100644 --- a/Everlook/Viewport/Rendering/Core/BaseGrid.cs +++ b/Everlook/Viewport/Rendering/Core/BaseGrid.cs @@ -22,12 +22,11 @@ using System; using System.Collections.Generic; +using System.Numerics; using Everlook.Viewport.Camera; using Everlook.Viewport.Rendering.Interfaces; using Everlook.Viewport.Rendering.Shaders; -using OpenTK; -using OpenTK.Graphics; -using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; namespace Everlook.Viewport.Rendering.Core { @@ -119,7 +118,7 @@ public void Initialize() vertexIndexes.AddRange(new ushort[] { 0, Quads * 2 }); vertexIndexes.AddRange(new ushort[] { 1, (Quads * 2) + 1 }); - _vertices = new Buffer(BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw) + _vertices = new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw) { Data = vertices.ToArray() }; @@ -130,14 +129,14 @@ public void Initialize() new VertexAttributePointer(0, 3, VertexAttribPointerType.Float, 0, 0) ); - _vertexIndexes = new Buffer(BufferTarget.ElementArrayBuffer, BufferUsageHint.StaticDraw) + _vertexIndexes = new Buffer(BufferTargetARB.ElementArrayBuffer, BufferUsageARB.StaticDraw) { Data = vertexIndexes.ToArray() }; } /// - public void Render(Matrix4 viewMatrix, Matrix4 projectionMatrix, ViewportCamera camera) + public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCamera camera) { ThrowIfDisposed(); diff --git a/Everlook/Viewport/Rendering/Core/Buffer.cs b/Everlook/Viewport/Rendering/Core/Buffer.cs index 7d842f2..0c1e54c 100644 --- a/Everlook/Viewport/Rendering/Core/Buffer.cs +++ b/Everlook/Viewport/Rendering/Core/Buffer.cs @@ -24,7 +24,7 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using Everlook.Viewport.Rendering.Interfaces; -using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; namespace Everlook.Viewport.Rendering.Core { @@ -37,10 +37,10 @@ public sealed class Buffer : IDisposable, IBuffer where T : struct private readonly int _nativeBufferID; /// - public BufferTarget Target { get; } + public BufferTargetARB Target { get; } /// - public BufferUsageHint Usage { get; } + public BufferUsageARB Usage { get; } /// public int Length { get; private set; } @@ -79,7 +79,7 @@ public T[] Data /// /// The intended use of the buffer. /// A hint as to how the buffer's data might be read or written. - public Buffer(BufferTarget target, BufferUsageHint usage) + public Buffer(BufferTargetARB target, BufferUsageARB usage) { this.Target = target; this.Usage = usage; diff --git a/Everlook/Viewport/Rendering/Core/DynamicInterpolator.cs b/Everlook/Viewport/Rendering/Core/DynamicInterpolator.cs index 6dce840..0fd3880 100644 --- a/Everlook/Viewport/Rendering/Core/DynamicInterpolator.cs +++ b/Everlook/Viewport/Rendering/Core/DynamicInterpolator.cs @@ -23,7 +23,7 @@ using System; using System.Collections.Generic; using System.Linq; -using OpenTK; +using System.Numerics; using Warcraft.Core.Interpolation; using Warcraft.Core.Structures; @@ -56,16 +56,13 @@ public class DynamicInterpolator // Two-component vector types { typeof(Vector2), v => new []{ (float)v.X, (float)v.Y } }, - { typeof(System.Numerics.Vector2), v => new []{ (float)v.X, (float)v.Y } }, // Three-component vector types { typeof(Vector3), v => new []{ (float)v.X, (float)v.Y, (float)v.Z } }, - { typeof(System.Numerics.Vector3), v => new []{ (float)v.X, (float)v.Y, (float)v.Z } }, { typeof(RGB), v => new []{ (float)v.R, (float)v.G, (float)v.B } }, // Four-component vector types { typeof(Quaternion), v => new []{ (float)v.X, (float)v.Y, (float)v.Z, (float)v.W } }, - { typeof(System.Numerics.Quaternion), v => new []{ (float)v.X, (float)v.Y, (float)v.Z, (float)v.W } }, }; private static readonly Dictionary> TypeCoalescers = @@ -86,16 +83,13 @@ public class DynamicInterpolator // Two-component vector types { typeof(Vector2), v => new Vector2(v[0], v[1]) }, - { typeof(System.Numerics.Vector2), v => new System.Numerics.Vector2(v[0], v[1]) }, // Three-component vector types { typeof(Vector3), v => new Vector3(v[0], v[1], v[2]) }, - { typeof(System.Numerics.Vector3), v => new System.Numerics.Vector3(v[0], v[1], v[2]) }, { typeof(RGB), v => new RGB(v[0], v[1], v[2]) }, // Four-component vector types { typeof(Quaternion), v => new Quaternion(v[0], v[1], v[2], v[3]) }, - { typeof(System.Numerics.Quaternion), v => new System.Numerics.Quaternion(v[0], v[1], v[2], v[3]) }, }; /// diff --git a/Everlook/Viewport/Rendering/Core/Lights/AmbientLight.cs b/Everlook/Viewport/Rendering/Core/Lights/AmbientLight.cs index bb1cf53..22ed522 100644 --- a/Everlook/Viewport/Rendering/Core/Lights/AmbientLight.cs +++ b/Everlook/Viewport/Rendering/Core/Lights/AmbientLight.cs @@ -20,7 +20,7 @@ // along with this program. If not, see . // -using OpenTK.Graphics; +using System.Numerics; namespace Everlook.Viewport.Rendering.Core.Lights { @@ -32,7 +32,7 @@ public class AmbientLight /// /// Gets or sets the colour of the light. /// - public Color4 LightColour { get; set; } + public Vector4 LightColour { get; set; } /// /// Gets or sets the intensity, in lux, of the light. diff --git a/Everlook/Viewport/Rendering/Core/Lights/DirectionalLight.cs b/Everlook/Viewport/Rendering/Core/Lights/DirectionalLight.cs index a72775e..f7c72fd 100644 --- a/Everlook/Viewport/Rendering/Core/Lights/DirectionalLight.cs +++ b/Everlook/Viewport/Rendering/Core/Lights/DirectionalLight.cs @@ -21,6 +21,7 @@ // using System; +using System.Numerics; using OpenTK; using OpenTK.Graphics; @@ -56,7 +57,7 @@ public class DirectionalLight /// /// Gets or sets the colour of the light. /// - public Color4 LightColour { get; set; } + public Vector4 LightColour { get; set; } /// /// Gets or sets the intensity, in lux, of the light. diff --git a/Everlook/Viewport/Rendering/Core/Plane.cs b/Everlook/Viewport/Rendering/Core/Plane.cs index 7d3533b..263043c 100644 --- a/Everlook/Viewport/Rendering/Core/Plane.cs +++ b/Everlook/Viewport/Rendering/Core/Plane.cs @@ -20,7 +20,7 @@ // along with this program. If not, see . // -using OpenTK; +using System.Numerics; namespace Everlook.Viewport.Rendering.Core { diff --git a/Everlook/Viewport/Rendering/Core/RenderableActorReference.cs b/Everlook/Viewport/Rendering/Core/RenderableActorReference.cs index 0f279f5..920dfc1 100644 --- a/Everlook/Viewport/Rendering/Core/RenderableActorReference.cs +++ b/Everlook/Viewport/Rendering/Core/RenderableActorReference.cs @@ -21,9 +21,9 @@ // using System; +using System.Numerics; using Everlook.Viewport.Camera; using Everlook.Viewport.Rendering.Interfaces; -using OpenTK; namespace Everlook.Viewport.Rendering.Core { @@ -88,7 +88,7 @@ public void Initialize() } /// - public void Render(Matrix4 viewMatrix, Matrix4 projectionMatrix, ViewportCamera camera) + public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCamera camera) { _target.ActorTransform = this.ActorTransform; _target.Render(viewMatrix, projectionMatrix, camera); diff --git a/Everlook/Viewport/Rendering/Core/ShaderProgram.cs b/Everlook/Viewport/Rendering/Core/ShaderProgram.cs index 5d78f94..8acfe29 100644 --- a/Everlook/Viewport/Rendering/Core/ShaderProgram.cs +++ b/Everlook/Viewport/Rendering/Core/ShaderProgram.cs @@ -21,13 +21,12 @@ // using System; +using System.Numerics; using Everlook.Exceptions.Shader; using Everlook.Utility; using Everlook.Viewport.Rendering.Shaders.GLSLExtended; using log4net; -using OpenTK; -using OpenTK.Graphics; -using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; namespace Everlook.Viewport.Rendering.Core { @@ -88,7 +87,7 @@ protected ShaderProgram() /// Sets the Model-View-Projection matrix of this shader. /// /// The ModelViewProjection matrix. - public void SetMVPMatrix(Matrix4 mvpMatrix) + public void SetMVPMatrix(Matrix4x4 mvpMatrix) { SetMatrix(mvpMatrix, MVPIdentifier); } @@ -112,12 +111,12 @@ protected void SetBoolean(bool value, string uniformName) /// The matrix. /// The name of the uniform variable. /// Whether or not the matrix should be transposed. - protected void SetMatrix(Matrix4 matrix, string uniformName, bool shouldTranspose = false) + protected void SetMatrix(Matrix4x4 matrix, string uniformName, bool shouldTranspose = false) { Enable(); var variableHandle = GL.GetUniformLocation(this.NativeShaderProgramID, uniformName); - GL.UniformMatrix4(variableHandle, shouldTranspose, ref matrix); + GL.UniformMatrix4x4(variableHandle, shouldTranspose, ref matrix); } /// @@ -247,10 +246,10 @@ private static int LinkShader(int vertexShaderID, int fragmentShaderID, int geom GL.LinkProgram(program); - GL.GetProgram(program, GetProgramParameterName.LinkStatus, out var result); + GL.GetProgram(program, ProgramPropertyARB.LinkStatus, out var result); var linkingSucceeded = result > 0; - GL.GetProgram(program, GetProgramParameterName.InfoLogLength, out var linkingLogLength); + GL.GetProgram(program, ProgramPropertyARB.InfoLogLength, out var linkingLogLength); GL.GetProgramInfoLog(program, out var linkingLog); // Clean up the shader source code and unlinked object files from graphics memory @@ -298,10 +297,10 @@ private static int CompileShader(ShaderType shaderType, string shaderSource) GL.ShaderSource(shader, shaderSource); GL.CompileShader(shader); - GL.GetShader(shader, ShaderParameter.CompileStatus, out var result); + GL.GetShader(shader, ShaderParameterName.CompileStatus, out var result); var compilationSucceeded = result > 0; - GL.GetShader(shader, ShaderParameter.InfoLogLength, out var compilationLogLength); + GL.GetShader(shader, ShaderParameterName.InfoLogLength, out var compilationLogLength); GL.GetShaderInfoLog(shader, out var compilationLog); if (!compilationSucceeded) diff --git a/Everlook/Viewport/Rendering/Core/Texture2D.cs b/Everlook/Viewport/Rendering/Core/Texture2D.cs index b41d56d..9c91edf 100644 --- a/Everlook/Viewport/Rendering/Core/Texture2D.cs +++ b/Everlook/Viewport/Rendering/Core/Texture2D.cs @@ -24,14 +24,14 @@ using System.Drawing; using System.Drawing.Imaging; using log4net; -using OpenTK.Graphics; -using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using Warcraft.BLP; -using GLPixelFormat = OpenTK.Graphics.OpenGL.PixelFormat; + using Image = System.Drawing.Image; +using PixelFormat = Silk.NET.OpenGL.PixelFormat; using Rectangle = System.Drawing.Rectangle; using SysPixelFormat = System.Drawing.Imaging.PixelFormat; @@ -360,17 +360,17 @@ private void CreateFromDXT(BLP inTextureData) { case BLPPixelFormat.DXT1: { - compressionFormat = InternalFormat.CompressedRgbaS3tcDxt1Ext; + compressionFormat = InternalFormat.CompressedRgbaS3TCDxt1Ext; break; } case BLPPixelFormat.DXT3: { - compressionFormat = InternalFormat.CompressedRgbaS3tcDxt3Ext; + compressionFormat = InternalFormat.CompressedRgbaS3TCDxt3Ext; break; } case BLPPixelFormat.DXT5: { - compressionFormat = InternalFormat.CompressedRgbaS3tcDxt5Ext; + compressionFormat = InternalFormat.CompressedRgbaS3TCDxt5Ext; break; } default: @@ -451,18 +451,18 @@ private void CreateFromImage(Image inTextureData) ( TextureTarget.Texture2D, 0, // level - PixelInternalFormat.Rgba, - inTextureData.Width, - inTextureData.Height, + (int)InternalFormat.Rgba, + (uint)inTextureData.Width, + (uint)inTextureData.Height, 0, // border - GLPixelFormat.Rgba, + PixelFormat.Rgba, PixelType.UnsignedByte, - new IntPtr(ptr) + ptr ); } } - GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); + GL.GenerateMipmap(TextureTarget.Texture2D); } } diff --git a/Everlook/Viewport/Rendering/Core/Timeline.cs b/Everlook/Viewport/Rendering/Core/Timeline.cs index acb45cf..b8dd5d6 100644 --- a/Everlook/Viewport/Rendering/Core/Timeline.cs +++ b/Everlook/Viewport/Rendering/Core/Timeline.cs @@ -24,7 +24,6 @@ using System.Collections.Generic; using System.Linq; using Everlook.Viewport.Rendering.Interfaces; -using OpenTK; using Warcraft.Core.Interpolation; namespace Everlook.Viewport.Rendering.Core diff --git a/Everlook/Viewport/Rendering/Core/Transform.cs b/Everlook/Viewport/Rendering/Core/Transform.cs index 44c61a9..daf6e2c 100644 --- a/Everlook/Viewport/Rendering/Core/Transform.cs +++ b/Everlook/Viewport/Rendering/Core/Transform.cs @@ -20,7 +20,7 @@ // along with this program. If not, see . // -using OpenTK; +using System.Numerics; namespace Everlook.Viewport.Rendering.Core { @@ -94,14 +94,14 @@ public Transform(Vector3 translation, Quaternion orientation, Vector3 scale) } /// - /// Gets the object representing the model matrix of this transform. + /// Gets the object representing the model matrix of this transform. /// /// A matrix containing model-space transformation data. - public Matrix4 GetModelMatrix() + public Matrix4x4 GetModelMatrix() { - var modelScale = Matrix4.CreateScale(this.Scale); - var modelOrientation = Matrix4.CreateFromQuaternion(this.Orientation); - var modelTranslation = Matrix4.CreateTranslation(this.Translation); + var modelScale = Matrix4x4.CreateScale(this.Scale); + var modelOrientation = Matrix4x4.CreateFromQuaternion(this.Orientation); + var modelTranslation = Matrix4x4.CreateTranslation(this.Translation); return modelScale * modelOrientation * modelTranslation; } diff --git a/Everlook/Viewport/Rendering/Core/VertexAttributePointer.cs b/Everlook/Viewport/Rendering/Core/VertexAttributePointer.cs index 5a6d1ca..f67e395 100644 --- a/Everlook/Viewport/Rendering/Core/VertexAttributePointer.cs +++ b/Everlook/Viewport/Rendering/Core/VertexAttributePointer.cs @@ -20,7 +20,7 @@ // along with this program. If not, see . // -using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; namespace Everlook.Viewport.Rendering.Core { diff --git a/Everlook/Viewport/Rendering/Interfaces/IBuffer.cs b/Everlook/Viewport/Rendering/Interfaces/IBuffer.cs index 526c55c..b67a14c 100644 --- a/Everlook/Viewport/Rendering/Interfaces/IBuffer.cs +++ b/Everlook/Viewport/Rendering/Interfaces/IBuffer.cs @@ -23,7 +23,7 @@ using System; using System.Collections.Generic; using Everlook.Viewport.Rendering.Core; -using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; namespace Everlook.Viewport.Rendering.Interfaces { @@ -35,12 +35,12 @@ public interface IBuffer /// /// Gets the intended use of the buffer. /// - BufferTarget Target { get; } + BufferTargetARB Target { get; } /// /// Gets a hinting value as to how the buffer's data might be read or written. /// - BufferUsageHint Usage { get; } + BufferUsageARB Usage { get; } /// /// Gets the byte count of the data in the buffer. diff --git a/Everlook/Viewport/Rendering/Interfaces/IDefaultCameraPositionProvider.cs b/Everlook/Viewport/Rendering/Interfaces/IDefaultCameraPositionProvider.cs index c603c45..e380e41 100644 --- a/Everlook/Viewport/Rendering/Interfaces/IDefaultCameraPositionProvider.cs +++ b/Everlook/Viewport/Rendering/Interfaces/IDefaultCameraPositionProvider.cs @@ -20,7 +20,7 @@ // along with this program. If not, see . // -using OpenTK; +using System.Numerics; namespace Everlook.Viewport.Rendering.Interfaces { diff --git a/Everlook/Viewport/Rendering/Interfaces/IInstancedRenderable.cs b/Everlook/Viewport/Rendering/Interfaces/IInstancedRenderable.cs index a8b1e5c..6663ad3 100644 --- a/Everlook/Viewport/Rendering/Interfaces/IInstancedRenderable.cs +++ b/Everlook/Viewport/Rendering/Interfaces/IInstancedRenderable.cs @@ -20,8 +20,8 @@ // along with this program. If not, see . // +using System.Numerics; using Everlook.Viewport.Camera; -using OpenTK; namespace Everlook.Viewport.Rendering.Interfaces { @@ -37,6 +37,6 @@ public interface IInstancedRenderable : IRenderable /// The projection matrix. /// The user camera. /// The number of instances to render. - void RenderInstances(Matrix4 viewMatrix, Matrix4 projectionMatrix, ViewportCamera camera, int count); + void RenderInstances(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCamera camera, int count); } } diff --git a/Everlook/Viewport/Rendering/Interfaces/IRenderable.cs b/Everlook/Viewport/Rendering/Interfaces/IRenderable.cs index 1e56373..55187ff 100644 --- a/Everlook/Viewport/Rendering/Interfaces/IRenderable.cs +++ b/Everlook/Viewport/Rendering/Interfaces/IRenderable.cs @@ -21,9 +21,9 @@ // using System; +using System.Numerics; using Everlook.Viewport.Camera; using Everlook.Viewport.Rendering.Core; -using OpenTK; namespace Everlook.Viewport.Rendering.Interfaces { @@ -72,6 +72,6 @@ ProjectionType Projection /// The view matrix. /// The projection matrix. /// The user camera. - void Render(Matrix4 viewMatrix, Matrix4 projectionMatrix, ViewportCamera camera); + void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCamera camera); } } diff --git a/Everlook/Viewport/Rendering/RenderCache.cs b/Everlook/Viewport/Rendering/RenderCache.cs index b320dd1..64b0a3a 100644 --- a/Everlook/Viewport/Rendering/RenderCache.cs +++ b/Everlook/Viewport/Rendering/RenderCache.cs @@ -27,12 +27,11 @@ using Everlook.Viewport.Rendering.Core; using Everlook.Viewport.Rendering.Shaders; using log4net; -using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; using Warcraft.BLP; using Warcraft.Core; using Warcraft.MDX.Visual; using Warcraft.MPQ; -using GLPixelFormat = OpenTK.Graphics.OpenGL.PixelFormat; using SysPixelFormat = System.Drawing.Imaging.PixelFormat; namespace Everlook.Viewport.Rendering @@ -207,11 +206,11 @@ public Texture2D GetTexture(MDXTexture texture, IGameContext gameContext, string var wrapS = texture.Flags.HasFlag(MDXTextureFlags.TextureWrapX) ? TextureWrapMode.Repeat - : TextureWrapMode.Clamp; + : TextureWrapMode.ClampToBorder; var wrapT = texture.Flags.HasFlag(MDXTextureFlags.TextureWrapY) ? TextureWrapMode.Repeat - : TextureWrapMode.Clamp; + : TextureWrapMode.ClampToBorder; return GetTexture(filename!, gameContext.Assets, wrapS, wrapT); } diff --git a/Everlook/Viewport/Rendering/RenderableBoundingBox.cs b/Everlook/Viewport/Rendering/RenderableBoundingBox.cs index ea82b37..18d3c6b 100644 --- a/Everlook/Viewport/Rendering/RenderableBoundingBox.cs +++ b/Everlook/Viewport/Rendering/RenderableBoundingBox.cs @@ -22,6 +22,7 @@ using System; using System.Linq; +using System.Numerics; using Everlook.Exceptions.Shader; using Everlook.Utility; using Everlook.Viewport.Camera; @@ -31,6 +32,7 @@ using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; using Warcraft.Core.Structures; namespace Everlook.Viewport.Rendering @@ -100,7 +102,7 @@ public void Initialize() throw new ShaderNullException(typeof(BoundingBoxShader)); } - _vertexBuffer = new Buffer(BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw) + _vertexBuffer = new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw) { Data = _boundingBoxData.GetCorners().ToArray() }; @@ -126,7 +128,7 @@ public void Initialize() 5, 3 }; - _vertexIndexesBuffer = new Buffer(BufferTarget.ElementArrayBuffer, BufferUsageHint.StaticDraw) + _vertexIndexesBuffer = new Buffer(BufferTargetARB.ElementArrayBuffer, BufferUsageARB.StaticDraw) { Data = boundingBoxIndexValues }; @@ -135,7 +137,7 @@ public void Initialize() } /// - public void RenderInstances(Matrix4 viewMatrix, Matrix4 projectionMatrix, ViewportCamera camera, int count) + public void RenderInstances(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCamera camera, int count) { ThrowIfDisposed(); @@ -163,20 +165,23 @@ public void RenderInstances(Matrix4 viewMatrix, Matrix4 projectionMatrix, Viewpo _boxShader.SetProjectionMatrix(projectionMatrix); // Now draw the box - GL.DrawElementsInstanced - ( - PrimitiveType.LineLoop, - 24, - DrawElementsType.UnsignedByte, - new IntPtr(0), - count - ); + unsafe + { + GL.DrawElementsInstanced + ( + PrimitiveType.LineLoop, + 24, + DrawElementsType.UnsignedByte, + (void*)0, + (uint)count + ); + } _vertexBuffer.DisableAttributes(); } /// - public void Render(Matrix4 viewMatrix, Matrix4 projectionMatrix, ViewportCamera camera) + public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCamera camera) { ThrowIfDisposed(); @@ -201,13 +206,16 @@ public void Render(Matrix4 viewMatrix, Matrix4 projectionMatrix, ViewportCamera _boxShader.SetLineColour(this.LineColour); // Now draw the box - GL.DrawElements - ( - PrimitiveType.LineLoop, - 24, - DrawElementsType.UnsignedByte, - new IntPtr(0) - ); + unsafe + { + GL.DrawElements + ( + PrimitiveType.LineLoop, + 24, + DrawElementsType.UnsignedByte, + (void*)0 + ); + } _vertexBuffer.DisableAttributes(); } diff --git a/Everlook/Viewport/Rendering/RenderableGameModel.cs b/Everlook/Viewport/Rendering/RenderableGameModel.cs index 5d6b0e5..d0ea905 100644 --- a/Everlook/Viewport/Rendering/RenderableGameModel.cs +++ b/Everlook/Viewport/Rendering/RenderableGameModel.cs @@ -24,6 +24,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Numerics; using Everlook.Configuration; using Everlook.Exceptions.Shader; using Everlook.Utility; @@ -31,9 +32,7 @@ using Everlook.Viewport.Rendering.Core; using Everlook.Viewport.Rendering.Interfaces; using Everlook.Viewport.Rendering.Shaders; -using OpenTK; -using OpenTK.Graphics; -using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; using Warcraft.Core; using Warcraft.Core.Extensions; using Warcraft.Core.Shading.MDX; @@ -78,7 +77,7 @@ public Vector3 DefaultCameraPosition this.ActorTransform.GetModelMatrix() * new Vector4 ( - _model.BoundingBox.GetCenterCoordinates().ToOpenGLVector(), + _model.BoundingBox.GetCenterCoordinates(), 1.0f ) ) @@ -190,7 +189,7 @@ public void Initialize() throw new ShaderNullException(typeof(GameModelShader)); } - _vertexBuffer = new Buffer(BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw) + _vertexBuffer = new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw) { Data = _model.Vertices.Select(v => v.PackForOpenGL()).SelectMany(b => b).ToArray() }; @@ -235,7 +234,7 @@ public void Initialize() relativeIndex => skin.VertexIndices[relativeIndex] ).ToArray(); - var skinIndexBuffer = new Buffer(BufferTarget.ElementArrayBuffer, BufferUsageHint.StaticDraw) + var skinIndexBuffer = new Buffer(BufferTargetARB.ElementArrayBuffer, BufferUsageARB.StaticDraw) { Data = absoluteTriangleVertexIndexes }; @@ -275,7 +274,7 @@ public void Tick(float deltaTime) } /// - public void RenderInstances(Matrix4 viewMatrix, Matrix4 projectionMatrix, ViewportCamera camera, int count) + public void RenderInstances(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCamera camera, int count) { ThrowIfDisposed(); @@ -333,14 +332,18 @@ public void RenderInstances(Matrix4 viewMatrix, Matrix4 projectionMatrix, Viewpo PrepareBatchForRender(renderBatch); var skinSection = skin.Sections[renderBatch.SkinSectionIndex]; - GL.DrawElementsInstanced - ( - PrimitiveType.Triangles, - skinSection.TriangleCount, - DrawElementsType.UnsignedShort, - new IntPtr(skinSection.StartTriangleIndex * 2), - count - ); + + unsafe + { + GL.DrawElementsInstanced + ( + PrimitiveType.Triangles, + skinSection.TriangleCount, + DrawElementsType.UnsignedShort, + (void*)(skinSection.StartTriangleIndex * 2), + (uint)count + ); + } } } @@ -355,7 +358,7 @@ public void RenderInstances(Matrix4 viewMatrix, Matrix4 projectionMatrix, Viewpo } /// - public void Render(Matrix4 viewMatrix, Matrix4 projectionMatrix, ViewportCamera camera) + public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCamera camera) { ThrowIfDisposed(); @@ -413,13 +416,16 @@ public void Render(Matrix4 viewMatrix, Matrix4 projectionMatrix, ViewportCamera PrepareBatchForRender(renderBatch); var skinSection = skin.Sections[renderBatch.SkinSectionIndex]; - GL.DrawElements - ( - PrimitiveType.Triangles, - skinSection.TriangleCount, - DrawElementsType.UnsignedShort, - new IntPtr(skinSection.StartTriangleIndex * 2) - ); + unsafe + { + GL.DrawElements + ( + PrimitiveType.Triangles, + skinSection.TriangleCount, + DrawElementsType.UnsignedShort, + (void*)(skinSection.StartTriangleIndex * 2) + ); + } } } diff --git a/Everlook/Viewport/Rendering/RenderableImage.cs b/Everlook/Viewport/Rendering/RenderableImage.cs index 235a0bb..ee35f3d 100644 --- a/Everlook/Viewport/Rendering/RenderableImage.cs +++ b/Everlook/Viewport/Rendering/RenderableImage.cs @@ -22,12 +22,12 @@ using System; using System.Collections.Generic; +using System.Numerics; using Everlook.Viewport.Camera; using Everlook.Viewport.Rendering.Core; using Everlook.Viewport.Rendering.Interfaces; using Everlook.Viewport.Rendering.Shaders; -using OpenTK; -using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; using Warcraft.Core.Extensions; using Warcraft.Core.Structures; @@ -177,7 +177,7 @@ public void Initialize() this.ActorTransform = new Transform(); GL.Enable(EnableCap.Blend); - GL.BlendEquation(BlendEquationMode.FuncAdd); + GL.BlendEquation(BlendEquationModeEXT.FuncAdd); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); this.IsInitialized = true; @@ -191,7 +191,7 @@ public void Initialize() protected abstract Texture2D LoadTexture(); /// - public void Render(Matrix4 viewMatrix, Matrix4 projectionMatrix, ViewportCamera camera) + public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCamera camera) { ThrowIfDisposed(); @@ -218,24 +218,35 @@ this.Texture is null // Send the vertices to the shader GL.EnableVertexAttribArray(0); this.VertexBuffer.Bind(); - GL.VertexAttribPointer( - 0, - 2, - VertexAttribPointerType.Float, - false, - 0, - 0); + + unsafe + { + GL.VertexAttribPointer + ( + 0u, + 2, + VertexAttribPointerType.Float, + false, + 0u, + (void*)0 + ); + } // Send the UV coordinates to the shader GL.EnableVertexAttribArray(1); this.UVBuffer.Bind(); - GL.VertexAttribPointer( - 1, - 2, - VertexAttribPointerType.Float, - false, - 0, - 0); + unsafe + { + GL.VertexAttribPointer + ( + 1u, + 2, + VertexAttribPointerType.Float, + false, + 0u, + (void*)0 + ); + } // Set the channel mask this.Shader.SetChannelMask(this.ChannelMask); @@ -253,7 +264,10 @@ this.Texture is null // Finally, draw the image this.VertexIndexBuffer.Bind(); - GL.DrawElements(BeginMode.Triangles, 6, DrawElementsType.UnsignedShort, 0); + unsafe + { + GL.DrawElements(PrimitiveType.Triangles, 6u, DrawElementsType.UnsignedShort, (void*)0); + } // Release the attribute arrays GL.DisableVertexAttribArray(0); @@ -285,7 +299,7 @@ protected Buffer GenerateVertices() }; // Buffer the generated vertices in the GPU - return new Buffer(BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw) + return new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw) { Data = vertexPositions.ToArray() }; @@ -300,7 +314,7 @@ protected static Buffer GenerateVertexIndexes() // Generate vertex indexes var vertexIndexes = new List { 1, 0, 2, 2, 3, 1 }; - return new Buffer(BufferTarget.ElementArrayBuffer, BufferUsageHint.StaticDraw) + return new Buffer(BufferTargetARB.ElementArrayBuffer, BufferUsageARB.StaticDraw) { Data = vertexIndexes.ToArray() }; @@ -322,7 +336,7 @@ protected static Buffer GenerateTextureCoordinates() }; // Buffer the generated UV coordinates in the GPU - return new Buffer(BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw) + return new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw) { Data = textureCoordinates.ToArray() }; diff --git a/Everlook/Viewport/Rendering/RenderableWorldModel.cs b/Everlook/Viewport/Rendering/RenderableWorldModel.cs index 2245a27..1c64181 100644 --- a/Everlook/Viewport/Rendering/RenderableWorldModel.cs +++ b/Everlook/Viewport/Rendering/RenderableWorldModel.cs @@ -23,6 +23,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Numerics; using Everlook.Configuration; using Everlook.Exceptions.Shader; using Everlook.Utility; @@ -31,19 +32,10 @@ using Everlook.Viewport.Rendering.Interfaces; using Everlook.Viewport.Rendering.Shaders; using log4net; -using OpenTK; +using Silk.NET.OpenGL; using Warcraft.WMO; using Warcraft.WMO.GroupFile; using Warcraft.WMO.RootFile.Chunks; -using BufferTarget = OpenTK.Graphics.OpenGL.BufferTarget; -using BufferUsageHint = OpenTK.Graphics.OpenGL.BufferUsageHint; -using DrawElementsType = OpenTK.Graphics.OpenGL.DrawElementsType; -using EnableCap = OpenTK.Graphics.OpenGL.EnableCap; -using GL = OpenTK.Graphics.OpenGL.GL; -using PrimitiveType = OpenTK.Graphics.OpenGL.PrimitiveType; -using TextureUnit = OpenTK.Graphics.OpenGL.TextureUnit; -using TextureWrapMode = OpenTK.Graphics.OpenGL.TextureWrapMode; -using VertexAttribPointerType = OpenTK.Graphics.OpenGL.VertexAttribPointerType; namespace Everlook.Viewport.Rendering { @@ -95,8 +87,7 @@ public Vector3 DefaultCameraPosition _model.Groups .First() .GetBoundingBox() - .GetCenterCoordinates() - .ToOpenGLVector(), + .GetCenterCoordinates(), 1.0f ) ) @@ -314,8 +305,8 @@ public void LoadDoodads() ( new Transform ( - doodadInstance.Position.ToOpenGLVector(), - doodadInstance.Orientation.ToOpenGLQuaternion(), + doodadInstance.Position, + doodadInstance.Orientation, new Vector3(doodadInstance.Scale) ) ); @@ -341,25 +332,25 @@ private void InitializeModelGroup(ModelGroup modelGroup) Buffers */ - var vertexBuffer = new Buffer(BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw); - var normalBuffer = new Buffer(BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw); - var coordinateBuffer = new Buffer(BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw); - var vertexIndexes = new Buffer(BufferTarget.ElementArrayBuffer, BufferUsageHint.StaticDraw); + var vertexBuffer = new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw); + var normalBuffer = new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw); + var coordinateBuffer = new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw); + var vertexIndexes = new Buffer(BufferTargetARB.ElementArrayBuffer, BufferUsageARB.StaticDraw); // Upload all of the vertices in this group - vertexBuffer.Data = modelGroup.GetVertices().Select(v => v.ToOpenGLVector()).ToArray(); + vertexBuffer.Data = modelGroup.GetVertices().Select(v => v).ToArray(); _vertexBufferLookup.Add(modelGroup, vertexBuffer); vertexBuffer.AttachAttributePointer(new VertexAttributePointer(0, 3, VertexAttribPointerType.Float, 0, 0)); // Upload all of the normals in this group - normalBuffer.Data = modelGroup.GetNormals().Select(v => v.ToOpenGLVector()).ToArray(); + normalBuffer.Data = modelGroup.GetNormals().Select(v => v).ToArray(); _normalBufferLookup.Add(modelGroup, normalBuffer); normalBuffer.AttachAttributePointer(new VertexAttributePointer(1, 3, VertexAttribPointerType.Float, 0, 0)); // Upload all of the UVs in this group - coordinateBuffer.Data = modelGroup.GetTextureCoordinates().Select(v => v.ToOpenGLVector()).ToArray(); + coordinateBuffer.Data = modelGroup.GetTextureCoordinates().Select(v => v).ToArray(); _textureCoordinateBufferLookup.Add(modelGroup, coordinateBuffer); coordinateBuffer.AttachAttributePointer @@ -397,7 +388,7 @@ public void Tick(float deltaTime) } /// - public void Render(Matrix4 viewMatrix, Matrix4 projectionMatrix, ViewportCamera camera) + public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCamera camera) { ThrowIfDisposed(); @@ -466,7 +457,7 @@ public void Render(Matrix4 viewMatrix, Matrix4 projectionMatrix, ViewportCamera /// /// Renders the specified model group on a batch basis. /// - private void RenderGroup(ModelGroup modelGroup, Matrix4 modelViewProjection) + private void RenderGroup(ModelGroup modelGroup, Matrix4x4 modelViewProjection) { if (_shader is null || this.DoodadSet is null) { @@ -524,15 +515,18 @@ private void RenderGroup(ModelGroup modelGroup, Matrix4 modelViewProjection) _shader.BindTexture2D(TextureUnit.Texture0, TextureUniform.Texture0, texture); // Finally, draw the model - GL.DrawRangeElements - ( - PrimitiveType.Triangles, - renderBatch.FirstPolygonIndex, - renderBatch.FirstPolygonIndex + renderBatch.PolygonIndexCount - 1, - renderBatch.PolygonIndexCount, - DrawElementsType.UnsignedShort, - new IntPtr(renderBatch.FirstPolygonIndex * 2) - ); + unsafe + { + GL.DrawRangeElements + ( + PrimitiveType.Triangles, + renderBatch.FirstPolygonIndex, + renderBatch.FirstPolygonIndex + renderBatch.PolygonIndexCount - 1, + renderBatch.PolygonIndexCount, + DrawElementsType.UnsignedShort, + (void*)(renderBatch.FirstPolygonIndex * 2) + ); + } } // Release the attribute arrays diff --git a/Everlook/Viewport/Rendering/Shaders/BoundingBoxShader.cs b/Everlook/Viewport/Rendering/Shaders/BoundingBoxShader.cs index f633555..761de84 100644 --- a/Everlook/Viewport/Rendering/Shaders/BoundingBoxShader.cs +++ b/Everlook/Viewport/Rendering/Shaders/BoundingBoxShader.cs @@ -20,6 +20,7 @@ // along with this program. If not, see . // +using System.Numerics; using Everlook.Viewport.Rendering.Core; using OpenTK; using OpenTK.Graphics; @@ -60,7 +61,7 @@ public void SetIsInstance(bool isInstanced) /// Sets the current view matrix of the shader. /// /// The model-view matrix. - public void SetViewMatrix(Matrix4 viewMatrix) + public void SetViewMatrix(Matrix4x4 viewMatrix) { SetMatrix(viewMatrix, ViewMatrix); } @@ -69,7 +70,7 @@ public void SetViewMatrix(Matrix4 viewMatrix) /// Sets the current projection matrix of the shader. /// /// The projection matrix. - public void SetProjectionMatrix(Matrix4 projectionMatrix) + public void SetProjectionMatrix(Matrix4x4 projectionMatrix) { SetMatrix(projectionMatrix, ProjectionMatrix); } diff --git a/Everlook/Viewport/Rendering/Shaders/Components/AmbientLighting.cs b/Everlook/Viewport/Rendering/Shaders/Components/AmbientLighting.cs index 5df393d..36399de 100644 --- a/Everlook/Viewport/Rendering/Shaders/Components/AmbientLighting.cs +++ b/Everlook/Viewport/Rendering/Shaders/Components/AmbientLighting.cs @@ -22,6 +22,7 @@ using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; namespace Everlook.Viewport.Rendering.Shaders.Components { diff --git a/Everlook/Viewport/Rendering/Shaders/Components/GlobalLighting.cs b/Everlook/Viewport/Rendering/Shaders/Components/GlobalLighting.cs index 81026ad..a778cc2 100644 --- a/Everlook/Viewport/Rendering/Shaders/Components/GlobalLighting.cs +++ b/Everlook/Viewport/Rendering/Shaders/Components/GlobalLighting.cs @@ -20,9 +20,11 @@ // along with this program. If not, see . // +using System.Numerics; using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; namespace Everlook.Viewport.Rendering.Shaders.Components { diff --git a/Everlook/Viewport/Rendering/Shaders/Components/SolidWireframe.cs b/Everlook/Viewport/Rendering/Shaders/Components/SolidWireframe.cs index e680e52..d712ffd 100644 --- a/Everlook/Viewport/Rendering/Shaders/Components/SolidWireframe.cs +++ b/Everlook/Viewport/Rendering/Shaders/Components/SolidWireframe.cs @@ -24,6 +24,7 @@ using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; namespace Everlook.Viewport.Rendering.Shaders.Components { diff --git a/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs b/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs index 6944184..3769ec6 100644 --- a/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs +++ b/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs @@ -21,11 +21,13 @@ // using System; +using System.Numerics; using Everlook.Viewport.Rendering.Core; using Everlook.Viewport.Rendering.Shaders.Components; using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; using Warcraft.Core.Shading.Blending; using Warcraft.Core.Shading.MDX; using Warcraft.MDX.Visual; @@ -85,7 +87,7 @@ public void SetIsInstance(bool isInstanced) /// Sets the current model matrix of the shader. /// /// The model matrix. - public void SetModelMatrix(Matrix4 modelMatrix) + public void SetModelMatrix(Matrix4x4 modelMatrix) { SetMatrix(modelMatrix, ModelMatrix); } @@ -94,7 +96,7 @@ public void SetModelMatrix(Matrix4 modelMatrix) /// Sets the current view matrix of the shader. /// /// The model-view matrix. - public void SetViewMatrix(Matrix4 viewMatrix) + public void SetViewMatrix(Matrix4x4 viewMatrix) { SetMatrix(viewMatrix, ViewMatrix); } @@ -103,7 +105,7 @@ public void SetViewMatrix(Matrix4 viewMatrix) /// Sets the current projection matrix of the shader. /// /// The projection matrix. - public void SetProjectionMatrix(Matrix4 projectionMatrix) + public void SetProjectionMatrix(Matrix4x4 projectionMatrix) { SetMatrix(projectionMatrix, ProjectionMatrix); } @@ -211,10 +213,10 @@ public void SetMaterial(MDXMaterial modelMaterial) GL.BlendFuncSeparate ( - (BlendingFactorSrc)srcC, - (BlendingFactorDest)dstC, - (BlendingFactorSrc)srcA, - (BlendingFactorDest)dstA + (BlendingFactor)srcC, + (BlendingFactor)dstC, + (BlendingFactor)srcA, + (BlendingFactor)dstA ); switch (modelMaterial.BlendMode) diff --git a/Everlook/Viewport/Rendering/Shaders/Plain2DShader.cs b/Everlook/Viewport/Rendering/Shaders/Plain2DShader.cs index dc6fa13..54d9429 100644 --- a/Everlook/Viewport/Rendering/Shaders/Plain2DShader.cs +++ b/Everlook/Viewport/Rendering/Shaders/Plain2DShader.cs @@ -20,9 +20,11 @@ // along with this program. If not, see . // +using System.Numerics; using Everlook.Viewport.Rendering.Core; using OpenTK; using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; namespace Everlook.Viewport.Rendering.Shaders { diff --git a/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs b/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs index 1a62bd0..002fe66 100644 --- a/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs +++ b/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs @@ -24,6 +24,7 @@ using Everlook.Viewport.Rendering.Core; using Everlook.Viewport.Rendering.Shaders.Components; using OpenTK.Graphics.OpenGL; +using Silk.NET.OpenGL; using Warcraft.Core.Shading.Blending; using Warcraft.WMO.RootFile.Chunks; @@ -98,10 +99,10 @@ public void SetMaterial(ModelMaterial modelMaterial) GL.BlendFuncSeparate ( - (BlendingFactorSrc)srcC, - (BlendingFactorDest)dstC, - (BlendingFactorSrc)srcA, - (BlendingFactorDest)dstA + (BlendingFactor)srcC, + (BlendingFactor)dstC, + (BlendingFactor)srcA, + (BlendingFactor)dstA ); switch (modelMaterial.BlendMode) diff --git a/Everlook/Viewport/ViewportRenderer.cs b/Everlook/Viewport/ViewportRenderer.cs index f1671af..c4c7569 100644 --- a/Everlook/Viewport/ViewportRenderer.cs +++ b/Everlook/Viewport/ViewportRenderer.cs @@ -30,8 +30,7 @@ using Everlook.Viewport.Rendering.Interfaces; using Gdk; using log4net; -using OpenTK.Graphics.OpenGL; -using OpenTK.Input; +using Silk.NET.OpenGL; namespace Everlook.Viewport { @@ -101,12 +100,12 @@ RenderTarget and related control flow data. /// /// Gets or sets the X position of the mouse during the last frame, relative to the . /// - public int InitialMouseX { get; set; } + public double InitialMouseX { get; set; } /// /// Gets or sets the Y position of the mouse during the last frame, relative to the . /// - public int InitialMouseY { get; set; } + public double InitialMouseY { get; set; } /* Runtime transitional OpenGL data. @@ -167,7 +166,7 @@ public void Initialize() var extensions = new List(); for (var i = 0; i < numExtensions; ++i) { - extensions.Add(GL.GetString(StringNameIndexed.Extensions, i)); + extensions.Add(GL.GetString(StringName.Extensions, i)); } if (extensions.Contains("GL_KHR_debug")) @@ -193,7 +192,7 @@ public void Initialize() // Set a simple default blending function GL.Enable(EnableCap.Blend); - GL.BlendEquation(BlendEquationMode.FuncAdd); + GL.BlendEquation(BlendEquationModeEXT.FuncAdd); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); // Initialize the viewport From fc361c5e847880ade5996f6592c2e50ed8deb69a Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sat, 4 Apr 2020 20:19:29 +0200 Subject: [PATCH 05/18] Port most of the graphics, and switch target over to netcoreapp3.1. --- .idea/.idea.Everlook/.idea/contentModel.xml | 15 +-- Everlook.sln.DotSettings | 7 +- Everlook/Audio/MP3/MP3AudioAsset.cs | 2 +- Everlook/Audio/Wave/WaveAudioAsset.cs | 2 +- Everlook/Everlook.csproj | 7 +- Everlook/UI/MainWindow.cs | 6 +- Everlook/UI/Widgets/ViewportArea.cs | 16 +++ Everlook/Utility/MathHelper.cs | 52 ++++++++ Everlook/Viewport/Camera/CameraMovement.cs | 45 +++---- Everlook/Viewport/Camera/ViewportCamera.cs | 36 ++--- .../Rendering/Core/ActorInstanceSet.cs | 61 +++++++-- Everlook/Viewport/Rendering/Core/BaseGrid.cs | 46 ++++--- Everlook/Viewport/Rendering/Core/Buffer.cs | 43 ++++-- .../Viewport/Rendering/Core/GraphicsObject.cs | 48 +++++++ .../Rendering/Core/Lights/DirectionalLight.cs | 23 ++-- .../Viewport/Rendering/Core/ShaderProgram.cs | 102 +++++++------- Everlook/Viewport/Rendering/Core/Texture2D.cs | 124 +++++++++-------- Everlook/Viewport/Rendering/Core/Timeline.cs | 2 +- .../Rendering/Core/VertexAttributePointer.cs | 42 +++--- .../Viewport/Rendering/Interfaces/IBuffer.cs | 2 +- Everlook/Viewport/Rendering/RenderCache.cs | 35 +++-- Everlook/Viewport/Rendering/RenderableBLP.cs | 17 ++- .../Viewport/Rendering/RenderableBitmap.cs | 17 ++- .../Rendering/RenderableBoundingBox.cs | 52 +++++--- .../Viewport/Rendering/RenderableGameModel.cs | 105 ++++++++++----- .../Viewport/Rendering/RenderableImage.cs | 52 +++++--- .../Rendering/RenderableWorldModel.cs | 91 ++++++++----- .../Rendering/Shaders/BaseGridShader.cs | 17 ++- .../Rendering/Shaders/BoundingBoxShader.cs | 17 ++- .../Shaders/Components/AmbientLighting.cs | 22 +-- .../Shaders/Components/GlobalLighting.cs | 28 ++-- .../Shaders/Components/SolidWireframe.cs | 48 ++++--- .../Rendering/Shaders/GameModelShader.cs | 25 ++-- .../Rendering/Shaders/Plain2DShader.cs | 12 +- .../Rendering/Shaders/WorldModelShader.cs | 17 +-- Everlook/Viewport/ViewportRenderer.cs | 125 ++++++++++++------ 36 files changed, 864 insertions(+), 497 deletions(-) create mode 100644 Everlook/Utility/MathHelper.cs create mode 100644 Everlook/Viewport/Rendering/Core/GraphicsObject.cs diff --git a/.idea/.idea.Everlook/.idea/contentModel.xml b/.idea/.idea.Everlook/.idea/contentModel.xml index b8221f4..1a3117d 100644 --- a/.idea/.idea.Everlook/.idea/contentModel.xml +++ b/.idea/.idea.Everlook/.idea/contentModel.xml @@ -251,6 +251,7 @@ + @@ -268,6 +269,7 @@ + @@ -331,19 +333,8 @@ - + - - - - - - - - - - - diff --git a/Everlook.sln.DotSettings b/Everlook.sln.DotSettings index 4b98638..22d1aeb 100644 --- a/Everlook.sln.DotSettings +++ b/Everlook.sln.DotSettings @@ -41,6 +41,7 @@ CHOP_IF_LONG UseExplicitType UseExplicitType + API BLP BMP BPP @@ -87,6 +88,10 @@ True True True + True + True True - True \ No newline at end of file + True + True + True \ No newline at end of file diff --git a/Everlook/Audio/MP3/MP3AudioAsset.cs b/Everlook/Audio/MP3/MP3AudioAsset.cs index ec8c1d8..221ec67 100644 --- a/Everlook/Audio/MP3/MP3AudioAsset.cs +++ b/Everlook/Audio/MP3/MP3AudioAsset.cs @@ -151,7 +151,7 @@ public void ThrowIfDisposed() { if (_isDisposed) { - throw new ObjectDisposedException(ToString()); + throw new ObjectDisposedException(ToString() ?? nameof(MP3AudioAsset)); } } diff --git a/Everlook/Audio/Wave/WaveAudioAsset.cs b/Everlook/Audio/Wave/WaveAudioAsset.cs index e511ee5..1c3eb54 100644 --- a/Everlook/Audio/Wave/WaveAudioAsset.cs +++ b/Everlook/Audio/Wave/WaveAudioAsset.cs @@ -201,7 +201,7 @@ public void ThrowIfDisposed() { if (_isDisposed) { - throw new ObjectDisposedException(ToString()); + throw new ObjectDisposedException(ToString() ?? nameof(WaveAudioAsset)); } } diff --git a/Everlook/Everlook.csproj b/Everlook/Everlook.csproj index 28c1457..d0b7523 100644 --- a/Everlook/Everlook.csproj +++ b/Everlook/Everlook.csproj @@ -1,11 +1,10 @@  - WinExe - net461 + Exe + netcoreapp3.1 false true - x86 $(DefineConstants);GTK3; true ..\stylecop.ruleset @@ -69,6 +68,8 @@ + + diff --git a/Everlook/UI/MainWindow.cs b/Everlook/UI/MainWindow.cs index 54c917e..db46f9c 100644 --- a/Everlook/UI/MainWindow.cs +++ b/Everlook/UI/MainWindow.cs @@ -891,8 +891,8 @@ private void OnViewportButtonPressed(object o, ButtonPressEventArgs args) _viewportWidget.GrabFocus(); - _renderingEngine.InitialMouseX = args.Event.X; - _renderingEngine.InitialMouseY = args.Event.Y; + _renderingEngine.InitialMouseX = args.Event.XRoot; + _renderingEngine.InitialMouseY = args.Event.YRoot; _renderingEngine.WantsToMove = true; } @@ -1298,8 +1298,6 @@ private void OnDeleteEvent(object sender, DeleteEventArgs a) _renderingEngine.SetRenderTarget(null); _renderingEngine.Dispose(); - RenderCache.Instance?.Dispose(); - _viewportWidget.Dispose(); Application.Quit(); diff --git a/Everlook/UI/Widgets/ViewportArea.cs b/Everlook/UI/Widgets/ViewportArea.cs index f518ec9..7bd0c08 100644 --- a/Everlook/UI/Widgets/ViewportArea.cs +++ b/Everlook/UI/Widgets/ViewportArea.cs @@ -24,6 +24,7 @@ using System.ComponentModel; using Gdk; using Gtk; +using Silk.NET.OpenGL; namespace Everlook.UI.Widgets { @@ -94,6 +95,21 @@ public ViewportArea this.HasAlpha = _withAlpha; } + /// + /// Gets an instance of the OpenGL API. + /// + /// The API instance. + /// Thrown if the viewport area has not been initialized. + public GL GetAPI() + { + if (_isInitialized) + { + return GL.GetApi(); + } + + throw new InvalidOperationException(); + } + /// /// Updates the time delta with a new value from the last frame. /// diff --git a/Everlook/Utility/MathHelper.cs b/Everlook/Utility/MathHelper.cs new file mode 100644 index 0000000..eecfffa --- /dev/null +++ b/Everlook/Utility/MathHelper.cs @@ -0,0 +1,52 @@ +// +// MathHelper.cs +// +// Author: +// Jarl Gullberg +// +// Copyright (c) 2017 Jarl Gullberg +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +using System; + +namespace Everlook.Utility +{ + /// + /// Various mathematical helper functions. + /// + public static class MathHelper + { + /// + /// Converts degrees to radians. + /// + /// The value in degrees. + /// The value in radians. + public static double DegreesToRadians(double degrees) + { + return degrees * (Math.PI / 180.0); + } + + /// + /// Converts radians to degrees. + /// + /// The value in radians. + /// The value in degrees. + public static double RadiansToDegrees(double radians) + { + return radians / (Math.PI / 180.0); + } + } +} diff --git a/Everlook/Viewport/Camera/CameraMovement.cs b/Everlook/Viewport/Camera/CameraMovement.cs index 7e8a2dc..a7101bf 100644 --- a/Everlook/Viewport/Camera/CameraMovement.cs +++ b/Everlook/Viewport/Camera/CameraMovement.cs @@ -23,9 +23,8 @@ using System; using System.Numerics; using Everlook.Configuration; +using Everlook.Utility; using Gdk; -using OpenTK; -using OpenTK.Input; namespace Everlook.Viewport.Camera { @@ -57,8 +56,8 @@ public Vector3 Orientation { return new Vector3 ( - MathHelper.RadiansToDegrees(_camera.VerticalViewAngle), - MathHelper.RadiansToDegrees(_camera.HorizontalViewAngle), + (float)MathHelper.RadiansToDegrees(_camera.VerticalViewAngle), + (float)MathHelper.RadiansToDegrees(_camera.HorizontalViewAngle), 0 ); } @@ -106,7 +105,7 @@ public CameraMovement(ViewportCamera inCamera) /// The motion delta along the X axis of the mouse in the last frame. /// The motion delta along the Y axis of the mouse in the last frame. /// The time delta between this frame and the previous one. - public void Calculate2DMovement(float deltaMouseX, float deltaMouseY, float deltaTime) + public void Calculate2DMovement(double deltaMouseX, double deltaMouseY, float deltaTime) { const float speedMultiplier = 6.0f; if (deltaMouseX < 0) @@ -135,7 +134,7 @@ public void Calculate2DMovement(float deltaMouseX, float deltaMouseY, float delt /// The motion delta along the X axis of the mouse in the last frame. /// The motion delta along the Y axis of the mouse in the last frame. /// The time delta between this frame and the previous one. - public void Calculate3DMovement(float deltaMouseX, float deltaMouseY, float deltaTime) + public void Calculate3DMovement(double deltaMouseX, double deltaMouseY, float deltaTime) { // Perform radial movement RotateHorizontal @@ -153,11 +152,11 @@ public void Calculate3DMovement(float deltaMouseX, float deltaMouseY, float delt { if (_camera.VerticalViewAngle > MathHelper.DegreesToRadians(90.0f)) { - _camera.VerticalViewAngle = MathHelper.DegreesToRadians(90.0f); + _camera.VerticalViewAngle = MathHelper.DegreesToRadians(90.0); } - else if (_camera.VerticalViewAngle < MathHelper.DegreesToRadians(-90.0f)) + else if (_camera.VerticalViewAngle < MathHelper.DegreesToRadians(-90.0)) { - _camera.VerticalViewAngle = MathHelper.DegreesToRadians(-90.0f); + _camera.VerticalViewAngle = MathHelper.DegreesToRadians(-90.0); } } @@ -206,7 +205,7 @@ public void Calculate3DMovement(float deltaMouseX, float deltaMouseY, float delt /// Rotates the camera on the horizontal axis by the provided amount of degrees. /// /// The number of degrees to rotate. - public void RotateHorizontal(float degrees) + public void RotateHorizontal(double degrees) { _camera.HorizontalViewAngle += degrees; } @@ -215,7 +214,7 @@ public void RotateHorizontal(float degrees) /// Rotates the camera on the vertical axis by the provided amount of degrees. /// /// The number of degrees to rotate. - public void RotateVertical(float degrees) + public void RotateVertical(double degrees) { _camera.VerticalViewAngle += degrees; } @@ -224,54 +223,54 @@ public void RotateVertical(float degrees) /// Moves the camera up along its local Y axis by units. /// /// The distance to move. - public void MoveUp(float distance) + public void MoveUp(double distance) { - _camera.Position += _camera.UpVector * Math.Abs(distance); + _camera.Position += _camera.UpVector * (float)Math.Abs(distance); } /// /// Moves the camera down along its local Y axis by units. /// /// The distance to move. - public void MoveDown(float distance) + public void MoveDown(double distance) { - _camera.Position -= _camera.UpVector * Math.Abs(distance); + _camera.Position -= _camera.UpVector * (float)Math.Abs(distance); } /// /// Moves the camera forward along its local Z axis by units. /// /// The distance to move. - public void MoveForward(float distance) + public void MoveForward(double distance) { - _camera.Position += _camera.LookDirectionVector * Math.Abs(distance); + _camera.Position += _camera.LookDirectionVector * (float)Math.Abs(distance); } /// /// Moves the camera backwards along its local Z axis by units. /// /// The distance to move. - public void MoveBackward(float distance) + public void MoveBackward(double distance) { - _camera.Position -= _camera.LookDirectionVector * Math.Abs(distance); + _camera.Position -= _camera.LookDirectionVector * (float)Math.Abs(distance); } /// /// Moves the camera left along its local X axis by units. /// /// The distance to move. - public void MoveLeft(float distance) + public void MoveLeft(double distance) { - _camera.Position -= _camera.RightVector * Math.Abs(distance); + _camera.Position -= _camera.RightVector * (float)Math.Abs(distance); } /// /// Moves the camera right along its local X axis by units. /// /// The distance to move. - public void MoveRight(float distance) + public void MoveRight(double distance) { - _camera.Position += _camera.RightVector * Math.Abs(distance); + _camera.Position += _camera.RightVector * (float)Math.Abs(distance); } } } diff --git a/Everlook/Viewport/Camera/ViewportCamera.cs b/Everlook/Viewport/Camera/ViewportCamera.cs index abb4aae..3d5cd0f 100644 --- a/Everlook/Viewport/Camera/ViewportCamera.cs +++ b/Everlook/Viewport/Camera/ViewportCamera.cs @@ -24,6 +24,7 @@ using System.Diagnostics.CodeAnalysis; using System.Numerics; using Everlook.Configuration; +using Everlook.Utility; using Everlook.Viewport.Rendering.Core; namespace Everlook.Viewport.Camera @@ -65,12 +66,12 @@ public ProjectionType Projection /// /// Gets or sets the width of the camera viewport in pixels. /// - public int ViewportWidth { get; set; } + public uint ViewportWidth { get; set; } /// /// Gets or sets the height of the camera viewport in pixels. /// - public int ViewportHeight { get; set; } + public uint ViewportHeight { get; set; } private Vector3 _positionInternal; @@ -116,12 +117,12 @@ public Vector3 UpVector private set; } - private float _horizontalViewAngleInternal; + private double _horizontalViewAngleInternal; /// /// Gets or sets the current horizontal view angle of the observer. /// - public float HorizontalViewAngle + public double HorizontalViewAngle { get => _horizontalViewAngleInternal; set @@ -131,13 +132,13 @@ public float HorizontalViewAngle } } - private float _verticalViewAngleInternal; + private double _verticalViewAngleInternal; /// /// Gets or sets the current vertical view angle of the observer. This angle is /// limited to -90 and 90 (straight down and straight up, respectively). /// - public float VerticalViewAngle + public double VerticalViewAngle { get => _verticalViewAngleInternal; set @@ -169,8 +170,8 @@ public void ResetPosition() /// public void ResetRotation() { - this.HorizontalViewAngle = MathHelper.DegreesToRadians(180.0f); - this.VerticalViewAngle = MathHelper.DegreesToRadians(0.0f); + this.HorizontalViewAngle = (float)MathHelper.DegreesToRadians(180.0); + this.VerticalViewAngle = (float)MathHelper.DegreesToRadians(0.0); } private void RecalculateInternals() @@ -185,9 +186,9 @@ private void RecalculateInternals() this.RightVector = new Vector3 ( - (float)Math.Sin(this.HorizontalViewAngle - MathHelper.PiOver2), + (float)Math.Sin(this.HorizontalViewAngle - (Math.PI / 2)), 0, - (float)Math.Cos(this.HorizontalViewAngle - MathHelper.PiOver2) + (float)Math.Cos(this.HorizontalViewAngle - (Math.PI / 2)) ); this.UpVector = Vector3.Cross(this.RightVector, this.LookDirectionVector); @@ -215,7 +216,7 @@ public Matrix4x4 GetProjectionMatrix() var aspectRatio = (float)this.ViewportWidth / this.ViewportHeight; projectionMatrix = Matrix4x4.CreatePerspectiveFieldOfView ( - MathHelper.DegreesToRadians((float)EverlookConfiguration.Instance.CameraFOV), + (float)MathHelper.DegreesToRadians(EverlookConfiguration.Instance.CameraFOV), aspectRatio, DefaultNearClippingDistance, DefaultFarClippingDistance @@ -231,7 +232,7 @@ public Matrix4x4 GetProjectionMatrix() /// A view matrix. public Matrix4x4 GetViewMatrix() { - return Matrix4x4.LookAt + return Matrix4x4.CreateLookAt ( this.Position, this.Position + this.LookDirectionVector, @@ -250,16 +251,17 @@ public Matrix4x4 GetViewMatrix() Justification = "Used for matrix parameter alignment." ) ] - public Matrix3 GetViewportMatrix() + public Matrix4x4 GetViewportMatrix() { var widthOver2 = this.ViewportWidth / 2.0f; var heightOver2 = this.ViewportHeight / 2.0f; - return new Matrix3 + return new Matrix4x4 ( - widthOver2, 0, widthOver2, - 0, heightOver2, heightOver2, - 0, 0, 1 + widthOver2, 0, widthOver2, 0, + 0, heightOver2, heightOver2, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 ); } } diff --git a/Everlook/Viewport/Rendering/Core/ActorInstanceSet.cs b/Everlook/Viewport/Rendering/Core/ActorInstanceSet.cs index b5e57b6..16c9afd 100644 --- a/Everlook/Viewport/Rendering/Core/ActorInstanceSet.cs +++ b/Everlook/Viewport/Rendering/Core/ActorInstanceSet.cs @@ -35,7 +35,7 @@ namespace Everlook.Viewport.Rendering.Core /// Represents a set of actor instances, differing by their transforms. /// /// A renderable supporting instanced rendering. - public class ActorInstanceSet : IRenderable, IBoundedModel + public class ActorInstanceSet : GraphicsObject, IRenderable, IBoundedModel where T : class, IInstancedRenderable, IActor, IBoundedModel { /// @@ -71,8 +71,10 @@ public bool ShouldRenderBounds /// /// Initializes a new instance of the class. /// + /// The OpenGL API. /// The target instanced renderable. - public ActorInstanceSet(T target) + public ActorInstanceSet(GL gl, T target) + : base(gl) { this.Target = target; _instanceTransforms = new List(); @@ -92,34 +94,71 @@ public void SetInstances(IEnumerable instanceTransforms) /// public void Initialize() { - _instanceModelMatrices = new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw); + _instanceModelMatrices = new Buffer + ( + this.GL, + BufferTargetARB.ArrayBuffer, + BufferUsageARB.StaticDraw); _instanceModelMatrices.AttachAttributePointer ( - new VertexAttributePointer(6, 4, VertexAttribPointerType.Float, Marshal.SizeOf(), 0) + new VertexAttributePointer + ( + this.GL, + 6, + 4, + VertexAttribPointerType.Float, + (uint)Marshal.SizeOf(), + 0 + ) ); _instanceModelMatrices.AttachAttributePointer ( - new VertexAttributePointer(7, 4, VertexAttribPointerType.Float, Marshal.SizeOf(), 16) + new VertexAttributePointer + ( + this.GL, + 7, + 4, + VertexAttribPointerType.Float, + (uint)Marshal.SizeOf(), + 16 + ) ); _instanceModelMatrices.AttachAttributePointer ( - new VertexAttributePointer(8, 4, VertexAttribPointerType.Float, Marshal.SizeOf(), 32) + new VertexAttributePointer + ( + this.GL, + 8, + 4, + VertexAttribPointerType.Float, + (uint)Marshal.SizeOf(), + 32 + ) ); _instanceModelMatrices.AttachAttributePointer ( - new VertexAttributePointer(9, 4, VertexAttribPointerType.Float, Marshal.SizeOf(), 48) + new VertexAttributePointer + ( + this.GL, + 9, + 4, + VertexAttribPointerType.Float, + (uint)Marshal.SizeOf(), + 48 + ) ); _instanceModelMatrices.Bind(); _instanceModelMatrices.EnableAttributes(); - GL.VertexAttribDivisor(6, 1); - GL.VertexAttribDivisor(7, 1); - GL.VertexAttribDivisor(8, 1); - GL.VertexAttribDivisor(9, 1); + + this.GL.VertexAttribDivisor(6, 1); + this.GL.VertexAttribDivisor(7, 1); + this.GL.VertexAttribDivisor(8, 1); + this.GL.VertexAttribDivisor(9, 1); _instanceModelMatrices.Data = _instanceTransforms.Select(t => t.GetModelMatrix()).ToArray(); diff --git a/Everlook/Viewport/Rendering/Core/BaseGrid.cs b/Everlook/Viewport/Rendering/Core/BaseGrid.cs index bc20f30..57aa28a 100644 --- a/Everlook/Viewport/Rendering/Core/BaseGrid.cs +++ b/Everlook/Viewport/Rendering/Core/BaseGrid.cs @@ -34,7 +34,7 @@ namespace Everlook.Viewport.Rendering.Core /// Represents a base grid in the viewport, centered at the world and spanning 100x100 world units, subdivided /// into squares. /// - public class BaseGrid : IActor, IRenderable + public class BaseGrid : GraphicsObject, IActor, IRenderable { /// /// The size of one side of the grid. @@ -71,9 +71,12 @@ public class BaseGrid : IActor, IRenderable /// /// Initializes a new instance of the class. /// - public BaseGrid() + /// The OpenGL API. + /// The rendering cache. + public BaseGrid(GL gl, RenderCache renderCache) + : base(gl) { - _shader = (BaseGridShader)RenderCache.Instance.GetShader(EverlookShader.BaseGrid); + _shader = (BaseGridShader)renderCache.GetShader(EverlookShader.BaseGrid); this.ActorTransform = new Transform(); this.IsInitialized = false; @@ -118,7 +121,7 @@ public void Initialize() vertexIndexes.AddRange(new ushort[] { 0, Quads * 2 }); vertexIndexes.AddRange(new ushort[] { 1, (Quads * 2) + 1 }); - _vertices = new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw) + _vertices = new Buffer(this.GL, BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw) { Data = vertices.ToArray() }; @@ -126,10 +129,10 @@ public void Initialize() // Attach the vertex pointer _vertices.AttachAttributePointer ( - new VertexAttributePointer(0, 3, VertexAttribPointerType.Float, 0, 0) + new VertexAttributePointer(this.GL, 0, 3, VertexAttribPointerType.Float, 0, 0) ); - _vertexIndexes = new Buffer(BufferTargetARB.ElementArrayBuffer, BufferUsageARB.StaticDraw) + _vertexIndexes = new Buffer(this.GL, BufferTargetARB.ElementArrayBuffer, BufferUsageARB.StaticDraw) { Data = vertexIndexes.ToArray() }; @@ -145,9 +148,9 @@ public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCam return; } - GL.Enable(EnableCap.Blend); - GL.Enable(EnableCap.DepthTest); - GL.Disable(EnableCap.CullFace); + this.GL.Enable(EnableCap.Blend); + this.GL.Enable(EnableCap.DepthTest); + this.GL.Disable(EnableCap.CullFace); _vertices.Bind(); _vertices.EnableAttributes(); @@ -157,20 +160,23 @@ public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCam _shader.Enable(); - GL.BlendFunc(BlendingFactor.One, BlendingFactor.Zero); + this.GL.BlendFunc(BlendingFactor.One, BlendingFactor.Zero); // Set the default line colour (a light gray) - _shader.SetLineColour(new Color4(64, 64, 64, 255)); + _shader.SetLineColour(new Vector4(64, 64, 64, 255)); _shader.SetMVPMatrix(modelViewProjection); - var lineCount = ((Quads * 2) + 2) * 2; - GL.DrawElements - ( - PrimitiveType.Lines, - lineCount, - DrawElementsType.UnsignedShort, - IntPtr.Zero - ); + uint lineCount = ((Quads * 2) + 2) * 2; + unsafe + { + this.GL.DrawElements + ( + PrimitiveType.Lines, + lineCount, + DrawElementsType.UnsignedShort, + (void*)0 + ); + } _vertices.DisableAttributes(); } @@ -183,7 +189,7 @@ private void ThrowIfDisposed() { if (this.IsDisposed) { - throw new ObjectDisposedException(ToString()); + throw new ObjectDisposedException(ToString() ?? nameof(BaseGrid)); } } diff --git a/Everlook/Viewport/Rendering/Core/Buffer.cs b/Everlook/Viewport/Rendering/Core/Buffer.cs index 0c1e54c..ba33905 100644 --- a/Everlook/Viewport/Rendering/Core/Buffer.cs +++ b/Everlook/Viewport/Rendering/Core/Buffer.cs @@ -32,9 +32,9 @@ namespace Everlook.Viewport.Rendering.Core /// Represents a native OpenGL data buffer. /// /// Any structure. - public sealed class Buffer : IDisposable, IBuffer where T : struct + public sealed class Buffer : GraphicsObject, IDisposable, IBuffer where T : unmanaged { - private readonly int _nativeBufferID; + private readonly uint _nativeBufferID; /// public BufferTargetARB Target { get; } @@ -43,7 +43,7 @@ public sealed class Buffer : IDisposable, IBuffer where T : struct public BufferUsageARB Usage { get; } /// - public int Length { get; private set; } + public ulong Length { get; private set; } /// /// Gets the attribute pointers of the buffer. @@ -59,8 +59,20 @@ public T[] Data { Bind(); - var bufferData = new T[this.Length / Marshal.SizeOf()]; - GL.GetBufferSubData(this.Target, IntPtr.Zero, this.Length, bufferData); + var bufferData = new T[this.Length / (ulong)Marshal.SizeOf()]; + unsafe + { + fixed (void* ptr = bufferData) + { + this.GL.GetBufferSubData + ( + this.Target, + IntPtr.Zero, + new UIntPtr(this.Length), + ptr + ); + } + } return bufferData; } @@ -69,23 +81,32 @@ public T[] Data { Bind(); - this.Length = value.Length * Marshal.SizeOf(); - GL.BufferData(this.Target, this.Length, value, this.Usage); + this.Length = (ulong)value.Length * (ulong)Marshal.SizeOf(); + + unsafe + { + fixed (void* ptr = value) + { + this.GL.BufferData(this.Target, new UIntPtr(this.Length), ptr, this.Usage); + } + } } } /// /// Initializes a new instance of the class. /// + /// The OpenGL API. /// The intended use of the buffer. /// A hint as to how the buffer's data might be read or written. - public Buffer(BufferTargetARB target, BufferUsageARB usage) + public Buffer(GL gl, BufferTargetARB target, BufferUsageARB usage) + : base(gl) { this.Target = target; this.Usage = usage; this.Attributes = new List(); - _nativeBufferID = GL.GenBuffer(); + _nativeBufferID = this.GL.GenBuffer(); } /// @@ -136,13 +157,13 @@ public void DisableAttributes() /// public void Bind() { - GL.BindBuffer(this.Target, _nativeBufferID); + this.GL.BindBuffer(this.Target, _nativeBufferID); } /// public void Dispose() { - GL.DeleteBuffer(_nativeBufferID); + this.GL.DeleteBuffer(_nativeBufferID); } } } diff --git a/Everlook/Viewport/Rendering/Core/GraphicsObject.cs b/Everlook/Viewport/Rendering/Core/GraphicsObject.cs new file mode 100644 index 0000000..03195dd --- /dev/null +++ b/Everlook/Viewport/Rendering/Core/GraphicsObject.cs @@ -0,0 +1,48 @@ +// +// GraphicsObject.cs +// +// Author: +// Jarl Gullberg +// +// Copyright (c) 2017 Jarl Gullberg +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +using JetBrains.Annotations; +using Silk.NET.OpenGL; + +namespace Everlook.Viewport.Rendering.Core +{ + /// + /// Represents the base class of any graphics-aware object. + /// + [PublicAPI] + public abstract class GraphicsObject + { + /// + /// Gets the OpenGL API available to this object. + /// + protected GL GL { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The OpenGL API. + public GraphicsObject(GL gl) + { + this.GL = gl; + } + } +} diff --git a/Everlook/Viewport/Rendering/Core/Lights/DirectionalLight.cs b/Everlook/Viewport/Rendering/Core/Lights/DirectionalLight.cs index f7c72fd..777777c 100644 --- a/Everlook/Viewport/Rendering/Core/Lights/DirectionalLight.cs +++ b/Everlook/Viewport/Rendering/Core/Lights/DirectionalLight.cs @@ -22,8 +22,6 @@ using System; using System.Numerics; -using OpenTK; -using OpenTK.Graphics; namespace Everlook.Viewport.Rendering.Core.Lights { @@ -46,13 +44,20 @@ public class DirectionalLight /// /// Gets the vector along which the light shines. /// - public Vector3 LightVector => new Vector3 - ( - (float)Math.Cos(this.HorizontalAngle) * (float)Math.Cos(this.VerticalAngle), - (float)Math.Sin(this.VerticalAngle), - (float)Math.Sin(this.HorizontalAngle) * (float)Math.Cos(this.VerticalAngle) - ) - .Normalized(); + public Vector3 LightVector + { + get + { + var vec = new Vector3 + ( + (float)Math.Cos(this.HorizontalAngle) * (float)Math.Cos(this.VerticalAngle), + (float)Math.Sin(this.VerticalAngle), + (float)Math.Sin(this.HorizontalAngle) * (float)Math.Cos(this.VerticalAngle) + ); + + return vec / vec.Length(); + } + } /// /// Gets or sets the colour of the light. diff --git a/Everlook/Viewport/Rendering/Core/ShaderProgram.cs b/Everlook/Viewport/Rendering/Core/ShaderProgram.cs index 8acfe29..4bda9ea 100644 --- a/Everlook/Viewport/Rendering/Core/ShaderProgram.cs +++ b/Everlook/Viewport/Rendering/Core/ShaderProgram.cs @@ -21,6 +21,7 @@ // using System; +using System.Diagnostics.CodeAnalysis; using System.Numerics; using Everlook.Exceptions.Shader; using Everlook.Utility; @@ -34,7 +35,7 @@ namespace Everlook.Viewport.Rendering.Core /// Wraps basic OpenGL functionality for a shader program. This class is made to be extended out into /// more advanced shaders with specific functionality. /// - public abstract class ShaderProgram : IDisposable + public abstract class ShaderProgram : GraphicsObject, IDisposable { private const string MVPIdentifier = "ModelViewProjection"; @@ -46,13 +47,16 @@ public abstract class ShaderProgram : IDisposable /// /// Gets the native OpenGL ID of the shader program. /// - protected int NativeShaderProgramID { get; private set; } + protected uint NativeShaderProgramID { get; private set; } /// /// Initializes a new instance of the class, compiling and linking its associated /// shader sources into a shader program on the GPU. /// - protected ShaderProgram() + /// The OpenGL API. + [SuppressMessage("ReSharper", "VirtualMemberCallInConstructor", Justification = "Required.")] + protected ShaderProgram(GL gl) + : base(gl) { var vertexShaderSource = GetShaderSource(this.VertexShaderResourceName); var fragmentShaderSource = GetShaderSource(this.FragmentShaderResourceName); @@ -101,8 +105,8 @@ protected void SetBoolean(bool value, string uniformName) { Enable(); - var variableHandle = GL.GetUniformLocation(this.NativeShaderProgramID, uniformName); - GL.Uniform1(variableHandle, value ? 1 : 0); + var variableHandle = this.GL.GetUniformLocation(this.NativeShaderProgramID, uniformName); + this.GL.Uniform1(variableHandle, value ? 1 : 0); } /// @@ -115,8 +119,11 @@ protected void SetMatrix(Matrix4x4 matrix, string uniformName, bool shouldTransp { Enable(); - var variableHandle = GL.GetUniformLocation(this.NativeShaderProgramID, uniformName); - GL.UniformMatrix4x4(variableHandle, shouldTranspose, ref matrix); + var variableHandle = this.GL.GetUniformLocation(this.NativeShaderProgramID, uniformName); + unsafe + { + this.GL.UniformMatrix4(variableHandle, 4 * 4, shouldTranspose, &matrix.M11); + } } /// @@ -128,8 +135,8 @@ protected void SetInteger(int value, string uniformName) { Enable(); - var variableHandle = GL.GetUniformLocation(this.NativeShaderProgramID, uniformName); - GL.Uniform1(variableHandle, value); + var variableHandle = this.GL.GetUniformLocation(this.NativeShaderProgramID, uniformName); + this.GL.Uniform1(variableHandle, value); } /// @@ -141,21 +148,8 @@ protected void SetVector4(Vector4 value, string uniformName) { Enable(); - var variableHandle = GL.GetUniformLocation(this.NativeShaderProgramID, uniformName); - GL.Uniform4(variableHandle, value); - } - - /// - /// Sets the uniform named by to . - /// - /// The value. - /// The name of the uniform variable. - protected void SetColor4(Color4 value, string uniformName) - { - Enable(); - - var variableHandle = GL.GetUniformLocation(this.NativeShaderProgramID, uniformName); - GL.Uniform4(variableHandle, value); + var variableHandle = this.GL.GetUniformLocation(this.NativeShaderProgramID, uniformName); + this.GL.Uniform4(variableHandle, value); } /// @@ -167,8 +161,8 @@ protected void SetFloat(float value, string uniformName) { Enable(); - var variableHandle = GL.GetUniformLocation(this.NativeShaderProgramID, uniformName); - GL.Uniform1(variableHandle, value); + var variableHandle = this.GL.GetUniformLocation(this.NativeShaderProgramID, uniformName); + this.GL.Uniform1(variableHandle, value); } /// @@ -187,10 +181,10 @@ public void BindTexture2D(TextureUnit textureUnit, TextureUniform uniform, Textu Enable(); - var textureVariableHandle = GL.GetUniformLocation(this.NativeShaderProgramID, uniform.ToString()); - GL.Uniform1(textureVariableHandle, (int)uniform); + var textureVariableHandle = this.GL.GetUniformLocation(this.NativeShaderProgramID, uniform.ToString()); + this.GL.Uniform1(textureVariableHandle, (int)uniform); - GL.ActiveTexture(textureUnit); + this.GL.ActiveTexture(textureUnit); texture.Bind(); } @@ -231,33 +225,33 @@ public void BindTexture2D(TextureUnit textureUnit, TextureUniform uniform, Textu /// /// A native handle to a shader program. /// Thrown if the linking fails. - private static int LinkShader(int vertexShaderID, int fragmentShaderID, int geometryShaderID = -1) + private uint LinkShader(uint vertexShaderID, uint fragmentShaderID, uint geometryShaderID = 0) { Log.Info("Linking shader program..."); - var program = GL.CreateProgram(); + var program = this.GL.CreateProgram(); - GL.AttachShader(program, vertexShaderID); - GL.AttachShader(program, fragmentShaderID); + this.GL.AttachShader(program, vertexShaderID); + this.GL.AttachShader(program, fragmentShaderID); - if (geometryShaderID > -1) + if (geometryShaderID > 0) { - GL.AttachShader(program, geometryShaderID); + this.GL.AttachShader(program, geometryShaderID); } - GL.LinkProgram(program); + this.GL.LinkProgram(program); - GL.GetProgram(program, ProgramPropertyARB.LinkStatus, out var result); + this.GL.GetProgram(program, ProgramPropertyARB.LinkStatus, out var result); var linkingSucceeded = result > 0; - GL.GetProgram(program, ProgramPropertyARB.InfoLogLength, out var linkingLogLength); - GL.GetProgramInfoLog(program, out var linkingLog); + this.GL.GetProgram(program, ProgramPropertyARB.InfoLogLength, out var linkingLogLength); + this.GL.GetProgramInfoLog(program, out var linkingLog); // Clean up the shader source code and unlinked object files from graphics memory - GL.DetachShader(program, vertexShaderID); - GL.DetachShader(program, fragmentShaderID); + this.GL.DetachShader(program, vertexShaderID); + this.GL.DetachShader(program, fragmentShaderID); - GL.DeleteShader(vertexShaderID); - GL.DeleteShader(fragmentShaderID); + this.GL.DeleteShader(vertexShaderID); + this.GL.DeleteShader(fragmentShaderID); if (!linkingSucceeded) { @@ -280,7 +274,7 @@ private static int LinkShader(int vertexShaderID, int fragmentShaderID, int geom /// The source code of the shader. /// A native handle to the shader object code. /// Thrown if the compilation fails. - private static int CompileShader(ShaderType shaderType, string shaderSource) + private uint CompileShader(ShaderType shaderType, string shaderSource) { if (string.IsNullOrEmpty(shaderSource)) { @@ -291,21 +285,21 @@ private static int CompileShader(ShaderType shaderType, string shaderSource) ); } - var shader = GL.CreateShader(shaderType); + var shader = this.GL.CreateShader(shaderType); Log.Info("Compiling shader..."); - GL.ShaderSource(shader, shaderSource); - GL.CompileShader(shader); + this.GL.ShaderSource(shader, shaderSource); + this.GL.CompileShader(shader); - GL.GetShader(shader, ShaderParameterName.CompileStatus, out var result); + this.GL.GetShader(shader, ShaderParameterName.CompileStatus, out var result); var compilationSucceeded = result > 0; - GL.GetShader(shader, ShaderParameterName.InfoLogLength, out var compilationLogLength); - GL.GetShaderInfoLog(shader, out var compilationLog); + this.GL.GetShader(shader, ShaderParameterName.InfoLogLength, out var compilationLogLength); + this.GL.GetShaderInfoLog(shader, out var compilationLog); if (!compilationSucceeded) { - GL.DeleteShader(shader); + this.GL.DeleteShader(shader); throw new ShaderCompilationException(ShaderType.VertexShader, compilationLog); } @@ -344,14 +338,14 @@ private static int CompileShader(ShaderType shaderType, string shaderSource) /// public void Enable() { - GL.UseProgram(this.NativeShaderProgramID); + this.GL.UseProgram(this.NativeShaderProgramID); } /// public void Dispose() { - GL.DeleteProgram(this.NativeShaderProgramID); - this.NativeShaderProgramID = -1; + this.GL.DeleteProgram(this.NativeShaderProgramID); + this.NativeShaderProgramID = 0; } } } diff --git a/Everlook/Viewport/Rendering/Core/Texture2D.cs b/Everlook/Viewport/Rendering/Core/Texture2D.cs index 9c91edf..d88ecbc 100644 --- a/Everlook/Viewport/Rendering/Core/Texture2D.cs +++ b/Everlook/Viewport/Rendering/Core/Texture2D.cs @@ -40,7 +40,7 @@ namespace Everlook.Viewport.Rendering.Core /// /// Wraps functionality around an OpenGL texture. /// - public sealed class Texture2D : IDisposable + public sealed class Texture2D : GraphicsObject, IDisposable { /// /// Logger instance for this class. @@ -48,7 +48,7 @@ public sealed class Texture2D : IDisposable private static readonly ILog Log = LogManager.GetLogger(typeof(Texture2D)); private readonly object _textureLock = new object(); - private int _nativeTextureID; + private uint _nativeTextureID; /// /// Gets or sets the filter used when magnifying the texture. @@ -60,7 +60,7 @@ public TextureMagFilter MagnificationFilter } /// - /// Gets or sets the filter used when miniturizing the texture. + /// Gets or sets the filter used when miniaturizing the texture. /// public TextureMinFilter MiniaturizationFilter { @@ -97,9 +97,11 @@ public TextureWrapMode WrappingModeT /// /// Initializes a new instance of the class. /// - private Texture2D() + /// The OpenGL API. + private Texture2D(GL gl) + : base(gl) { - _nativeTextureID = GL.GenTexture(); + _nativeTextureID = this.GL.GenTexture(); } /// @@ -107,10 +109,11 @@ private Texture2D() /// mipmaps for the bitmap. /// /// The image data to create the texture from. + /// The OpenGL API. /// Optional. The wrapping mode to use for the texture. /// Thrown if the image data is null. - public Texture2D(Bitmap imageData, TextureWrapMode wrapMode = TextureWrapMode.Repeat) - : this() + public Texture2D(GL gl, Bitmap imageData, TextureWrapMode wrapMode = TextureWrapMode.Repeat) + : this(gl) { if (imageData == null) { @@ -129,11 +132,12 @@ public Texture2D(Bitmap imageData, TextureWrapMode wrapMode = TextureWrapMode.Re /// Mipmaps are loaded from the compressed texture. /// /// The image data to create the texture from. + /// The OpenGL API. /// Optional. The magnification filter to use for the texture. /// Optional. The miniaturization filter to use for the texture. /// Thrown if the image data is null. - public Texture2D(BLP imageData, TextureMagFilter magFilter, TextureMinFilter minFilter) - : this(imageData, TextureWrapMode.Repeat, TextureWrapMode.Repeat, magFilter, minFilter) + public Texture2D(GL gl, BLP imageData, TextureMagFilter magFilter, TextureMinFilter minFilter) + : this(gl, imageData, TextureWrapMode.Repeat, TextureWrapMode.Repeat, magFilter, minFilter) { } @@ -143,10 +147,11 @@ public Texture2D(BLP imageData, TextureMagFilter magFilter, TextureMinFilter min /// /// The image data to create the texture from. /// The magnification filter to use for the texture. + /// The OpenGL API. /// The miniaturization filter to use for the texture. /// Thrown if the image data is null. - public Texture2D(BLP imageData, TextureMinFilter minFilter, TextureMagFilter magFilter) - : this(imageData, magFilter, minFilter) + public Texture2D(GL gl, BLP imageData, TextureMinFilter minFilter, TextureMagFilter magFilter) + : this(gl, imageData, magFilter, minFilter) { } @@ -155,18 +160,22 @@ public Texture2D(BLP imageData, TextureMinFilter minFilter, TextureMagFilter mag /// Mipmaps are loaded from the compressed texture. /// /// The image data to create the texture from. + /// The OpenGL API. /// The wrapping mode to use for the texture on the S axis. /// The wrapping mode to use for the texture on the T axis. /// The magnification filter to use for the texture. /// The miniaturization filter to use for the texture. /// Thrown if the image data is null. - public Texture2D( + public Texture2D + ( + GL gl, BLP imageData, TextureWrapMode wrapModeS = TextureWrapMode.Repeat, TextureWrapMode wrapModeT = TextureWrapMode.Repeat, TextureMagFilter magFilter = TextureMagFilter.Linear, - TextureMinFilter minFilter = TextureMinFilter.LinearMipmapLinear) - : this() + TextureMinFilter minFilter = TextureMinFilter.LinearMipmapLinear + ) + : this(gl) { if (imageData == null) { @@ -179,11 +188,11 @@ public Texture2D( { CreateFromDXT(imageData); } - catch (GraphicsErrorException gex) + catch (Exception ex) { Log.Warn ( - $"GraphicsErrorException in CreateFromDXT (failed to create DXT texture): {gex.Message}\n" + + $"GraphicsErrorException in CreateFromDXT (failed to create DXT texture): {ex.Message}\n" + "The texture will be loaded as a bitmap instead." ); } @@ -226,7 +235,7 @@ private void SetMagnificationFilter(TextureMagFilter magFilter) lock (_textureLock) { Bind(); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)magFilter); + this.GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)magFilter); } } @@ -238,7 +247,7 @@ private void SetMiniaturizationFilter(TextureMinFilter minFilter) lock (_textureLock) { Bind(); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)minFilter); + this.GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)minFilter); } } @@ -251,7 +260,7 @@ private TextureMagFilter GetMagnificationFilter() lock (_textureLock) { Bind(); - GL.GetTexParameter(TextureTarget.Texture2D, GetTextureParameter.TextureMagFilter, out int magFilter); + this.GL.GetTexParameter(TextureTarget.Texture2D, GetTextureParameter.TextureMagFilter, out int magFilter); return (TextureMagFilter)magFilter; } } @@ -265,7 +274,7 @@ private TextureMinFilter GetMiniaturizationFilter() lock (_textureLock) { Bind(); - GL.GetTexParameter(TextureTarget.Texture2D, GetTextureParameter.TextureMinFilter, out int minFilter); + this.GL.GetTexParameter(TextureTarget.Texture2D, GetTextureParameter.TextureMinFilter, out int minFilter); return (TextureMinFilter)minFilter; } } @@ -294,7 +303,7 @@ private void SetWrappingModeS(TextureWrapMode wrapModeS) lock (_textureLock) { Bind(); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)wrapModeS); + this.GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)wrapModeS); } } @@ -307,7 +316,7 @@ private void SetWrappingModeT(TextureWrapMode wrapModeT) lock (_textureLock) { Bind(); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)wrapModeT); + this.GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)wrapModeT); } } @@ -320,7 +329,7 @@ private TextureWrapMode GetWrappingModeS() lock (_textureLock) { Bind(); - GL.GetTexParameter(TextureTarget.Texture2D, GetTextureParameter.TextureWrapS, out int wrapModeS); + this.GL.GetTexParameter(TextureTarget.Texture2D, GetTextureParameter.TextureWrapS, out int wrapModeS); return (TextureWrapMode)wrapModeS; } } @@ -334,7 +343,7 @@ private TextureWrapMode GetWrappingModeT() lock (_textureLock) { Bind(); - GL.GetTexParameter(TextureTarget.Texture2D, GetTextureParameter.TextureWrapT, out int wrapModeT); + this.GL.GetTexParameter(TextureTarget.Texture2D, GetTextureParameter.TextureWrapT, out int wrapModeT); return (TextureWrapMode)wrapModeT; } } @@ -384,17 +393,23 @@ private void CreateFromDXT(BLP inTextureData) } // Load the mipmap into the texture - GL.CompressedTexImage2D - ( - TextureTarget.Texture2D, - (int)i, - compressionFormat, - (int)mipResolution.X, - (int)mipResolution.Y, - 0, - compressedMipMap.Length, - compressedMipMap - ); + unsafe + { + fixed (void* ptr = compressedMipMap) + { + this.GL.CompressedTexImage2D + ( + TextureTarget.Texture2D, + (int)i, + compressionFormat, + mipResolution.X, + mipResolution.Y, + 0, + (uint)compressedMipMap.Length, + ptr + ); + } + } } } } @@ -417,20 +432,23 @@ private void CreateFromBitmap(Bitmap inTextureData) SysPixelFormat.Format32bppArgb ); - GL.TexImage2D - ( - TextureTarget.Texture2D, - 0, // level - PixelInternalFormat.Rgba, - pixels.Width, - pixels.Height, - 0, // border - GLPixelFormat.Bgra, - PixelType.UnsignedByte, - pixels.Scan0 - ); + unsafe + { + this.GL.TexImage2D + ( + TextureTarget.Texture2D, + 0, // level + (int)InternalFormat.Rgba, + (uint)pixels.Width, + (uint)pixels.Height, + 0, // border + PixelFormat.Bgra, + PixelType.UnsignedByte, + pixels.Scan0.ToPointer() + ); + } - GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); + this.GL.GenerateMipmap(TextureTarget.Texture2D); inTextureData.UnlockBits(pixels); } @@ -447,7 +465,7 @@ private void CreateFromImage(Image inTextureData) { fixed (void* ptr = &inTextureData.GetPixelSpan().GetPinnableReference()) { - GL.TexImage2D + this.GL.TexImage2D ( TextureTarget.Texture2D, 0, // level @@ -462,7 +480,7 @@ private void CreateFromImage(Image inTextureData) } } - GL.GenerateMipmap(TextureTarget.Texture2D); + this.GL.GenerateMipmap(TextureTarget.Texture2D); } } @@ -474,7 +492,7 @@ public void Bind() { lock (_textureLock) { - GL.BindTexture(TextureTarget.Texture2D, _nativeTextureID); + this.GL.BindTexture(TextureTarget.Texture2D, _nativeTextureID); } } @@ -485,8 +503,8 @@ public void Dispose() { GC.SuppressFinalize(this); - GL.DeleteTexture(_nativeTextureID); - _nativeTextureID = -1; + this.GL.DeleteTexture(_nativeTextureID); + _nativeTextureID = 0; } } } diff --git a/Everlook/Viewport/Rendering/Core/Timeline.cs b/Everlook/Viewport/Rendering/Core/Timeline.cs index b8dd5d6..7fc9246 100644 --- a/Everlook/Viewport/Rendering/Core/Timeline.cs +++ b/Everlook/Viewport/Rendering/Core/Timeline.cs @@ -213,7 +213,7 @@ protected float NormalizeTime(float time) return time % this.Duration; } - return MathHelper.Clamp(time, 0, this.Duration); + return Math.Clamp(time, 0, this.Duration); } } } diff --git a/Everlook/Viewport/Rendering/Core/VertexAttributePointer.cs b/Everlook/Viewport/Rendering/Core/VertexAttributePointer.cs index f67e395..4653ca9 100644 --- a/Everlook/Viewport/Rendering/Core/VertexAttributePointer.cs +++ b/Everlook/Viewport/Rendering/Core/VertexAttributePointer.cs @@ -27,12 +27,12 @@ namespace Everlook.Viewport.Rendering.Core /// /// Represents a vertex attribute pointer. /// - public class VertexAttributePointer + public class VertexAttributePointer : GraphicsObject { /// /// Gets the attribute array index that the pointer modifies. /// - public int LayoutIndex { get; } + public uint LayoutIndex { get; } /// /// Gets the number of components per attribute. @@ -52,16 +52,17 @@ public class VertexAttributePointer /// /// Gets the byte offset between consecutive vertex attributes. /// - public int ByteStride { get; } + public uint ByteStride { get; } /// /// Gets the offset to the first component of the first attribute in the array. /// - public int FirstAttributeByteOffset { get; } + public uint FirstAttributeByteOffset { get; } /// /// Initializes a new instance of the class. /// + /// The OpenGL API. /// The attribute array layout index. /// The number of components in the attribute. /// The data type of each component in the attribute. @@ -70,13 +71,15 @@ public class VertexAttributePointer /// Whether or not the data should be normalized. public VertexAttributePointer ( - int layoutIndex, + GL gl, + uint layoutIndex, int componentCount, VertexAttribPointerType type, - int byteStride, - int firstAttributeByteOffset, + uint byteStride, + uint firstAttributeByteOffset, bool isNormalized = false ) + : base(gl) { this.LayoutIndex = layoutIndex; this.ComponentCount = componentCount; @@ -93,16 +96,19 @@ public VertexAttributePointer /// public void Enable() { - GL.EnableVertexAttribArray(this.LayoutIndex); - GL.VertexAttribPointer - ( - this.LayoutIndex, - this.ComponentCount, - this.Type, - this.IsNormalized, - this.ByteStride, - this.FirstAttributeByteOffset - ); + this.GL.EnableVertexAttribArray(this.LayoutIndex); + unsafe + { + this.GL.VertexAttribPointer + ( + this.LayoutIndex, + this.ComponentCount, + this.Type, + this.IsNormalized, + this.ByteStride, + (void*)this.FirstAttributeByteOffset + ); + } } /// @@ -110,7 +116,7 @@ public void Enable() /// public void Disable() { - GL.DisableVertexAttribArray(this.LayoutIndex); + this.GL.DisableVertexAttribArray(this.LayoutIndex); } } } diff --git a/Everlook/Viewport/Rendering/Interfaces/IBuffer.cs b/Everlook/Viewport/Rendering/Interfaces/IBuffer.cs index b67a14c..5684c17 100644 --- a/Everlook/Viewport/Rendering/Interfaces/IBuffer.cs +++ b/Everlook/Viewport/Rendering/Interfaces/IBuffer.cs @@ -45,7 +45,7 @@ public interface IBuffer /// /// Gets the byte count of the data in the buffer. /// - int Length { get; } + ulong Length { get; } /// /// Attaches the specified attribute pointer to the buffer. diff --git a/Everlook/Viewport/Rendering/RenderCache.cs b/Everlook/Viewport/Rendering/RenderCache.cs index 64b0a3a..bf02cc9 100644 --- a/Everlook/Viewport/Rendering/RenderCache.cs +++ b/Everlook/Viewport/Rendering/RenderCache.cs @@ -26,6 +26,7 @@ using Everlook.Utility; using Everlook.Viewport.Rendering.Core; using Everlook.Viewport.Rendering.Shaders; +using JetBrains.Annotations; using log4net; using Silk.NET.OpenGL; using Warcraft.BLP; @@ -42,7 +43,7 @@ namespace Everlook.Viewport.Rendering /// /// Currently, these are textures and shader programs. /// - public sealed class RenderCache : IDisposable + public sealed class RenderCache : GraphicsObject, IDisposable { /// /// Logger instance for this class. @@ -82,7 +83,7 @@ public Texture2D FallbackTexture throw new InvalidOperationException(); } - _fallbackTextureInternal = new Texture2D(fallbackImage); + _fallbackTextureInternal = new Texture2D(this.GL, fallbackImage); } return _fallbackTextureInternal; @@ -92,16 +93,12 @@ public Texture2D FallbackTexture private Texture2D? _fallbackTextureInternal; /// - /// A singleton instance of the rendering cache. + /// Initializes a new instance of the class. /// - public static readonly RenderCache Instance = new RenderCache(); - - /// - /// Finalizes an instance of the class. - /// - ~RenderCache() + /// The OpenGL API. + public RenderCache([NotNull] GL gl) + : base(gl) { - Dispose(); } /// @@ -297,14 +294,14 @@ public Texture2D CreateCachedTexture { ThrowIfDisposed(); - var texture = new Texture2D(imageData, wrappingModeS, wrappingModeT); + var texture = new Texture2D(this.GL, imageData, wrappingModeS, wrappingModeT); _textureCache.Add(texturePath.ConvertPathSeparatorsToCurrentNativeSeparator().ToUpperInvariant(), texture); return texture; } /// - /// Creates a cached texture for the specifed texture, using the specified path + /// Creates a cached texture for the specified texture, using the specified path /// as a lookup key. This method will create a new texture, and cache it. /// /// A bitmap containing the image data. @@ -316,7 +313,7 @@ public Texture2D CreateCachedTexture(Bitmap imageData, string texturePath) { ThrowIfDisposed(); - var texture = new Texture2D(imageData); + var texture = new Texture2D(this.GL, imageData); _textureCache.Add(texturePath.ConvertPathSeparatorsToCurrentNativeSeparator().ToUpperInvariant(), texture); return texture; @@ -340,27 +337,27 @@ private ShaderProgram CreateCachedShader(EverlookShader shader) { case EverlookShader.Plain2D: { - shaderProgram = new Plain2DShader(); + shaderProgram = new Plain2DShader(this.GL); break; } case EverlookShader.WorldModel: { - shaderProgram = new WorldModelShader(); + shaderProgram = new WorldModelShader(this.GL); break; } case EverlookShader.BoundingBox: { - shaderProgram = new BoundingBoxShader(); + shaderProgram = new BoundingBoxShader(this.GL); break; } case EverlookShader.GameModel: { - shaderProgram = new GameModelShader(); + shaderProgram = new GameModelShader(this.GL); break; } case EverlookShader.BaseGrid: { - shaderProgram = new BaseGridShader(); + shaderProgram = new BaseGridShader(this.GL); break; } default: @@ -385,7 +382,7 @@ private void ThrowIfDisposed() { if (this.IsDisposed) { - throw new ObjectDisposedException(ToString()); + throw new ObjectDisposedException(ToString() ?? nameof(RenderCache)); } } diff --git a/Everlook/Viewport/Rendering/RenderableBLP.cs b/Everlook/Viewport/Rendering/RenderableBLP.cs index 2fbaebc..fad6f46 100644 --- a/Everlook/Viewport/Rendering/RenderableBLP.cs +++ b/Everlook/Viewport/Rendering/RenderableBLP.cs @@ -22,6 +22,7 @@ using System; using Everlook.Viewport.Rendering.Core; +using Silk.NET.OpenGL; using Warcraft.BLP; using Warcraft.Core.Structures; @@ -40,9 +41,12 @@ public sealed class RenderableBLP : RenderableImage /// /// Initializes a new instance of the class. /// + /// The OpenGL API. + /// The rendering cache. /// An image object with populated data. /// The path under which this renderable texture is stored in the archives. - public RenderableBLP(BLP inImage, string inTexturePath) + public RenderableBLP(GL gl, RenderCache renderCache, BLP inImage, string inTexturePath) + : base(gl, renderCache) { _image = inImage; this.TexturePath = inTexturePath; @@ -58,12 +62,12 @@ protected override Texture2D LoadTexture() throw new InvalidOperationException(); } - if (Cache.HasCachedTextureForPath(this.TexturePath)) + if (this.RenderCache.HasCachedTextureForPath(this.TexturePath)) { - return Cache.GetCachedTexture(this.TexturePath); + return this.RenderCache.GetCachedTexture(this.TexturePath); } - return Cache.CreateCachedTexture(_image, this.TexturePath); + return this.RenderCache.CreateCachedTexture(_image, this.TexturePath); } /// @@ -73,10 +77,9 @@ protected override Resolution GetResolution() } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { - var otherImage = obj as RenderableBLP; - if (otherImage == null) + if (!(obj is RenderableBLP otherImage)) { return false; } diff --git a/Everlook/Viewport/Rendering/RenderableBitmap.cs b/Everlook/Viewport/Rendering/RenderableBitmap.cs index 75dcf60..7147374 100644 --- a/Everlook/Viewport/Rendering/RenderableBitmap.cs +++ b/Everlook/Viewport/Rendering/RenderableBitmap.cs @@ -23,6 +23,7 @@ using System; using System.Drawing; using Everlook.Viewport.Rendering.Core; +using Silk.NET.OpenGL; using Warcraft.Core.Structures; namespace Everlook.Viewport.Rendering @@ -44,9 +45,12 @@ private Bitmap Image /// /// Initializes a new instance of the class. /// + /// The OpenGL API. + /// The rendering cache. /// In image. /// The path under which this renderable texture is stored in the archives. - public RenderableBitmap(Bitmap inImage, string inTexturePath) + public RenderableBitmap(GL gl, RenderCache renderCache, Bitmap inImage, string inTexturePath) + : base(gl, renderCache) { this.Image = inImage; this.TexturePath = inTexturePath; @@ -62,12 +66,12 @@ protected override Texture2D LoadTexture() throw new InvalidOperationException(); } - if (Cache.HasCachedTextureForPath(this.TexturePath)) + if (this.RenderCache.HasCachedTextureForPath(this.TexturePath)) { - return Cache.GetCachedTexture(this.TexturePath); + return this.RenderCache.GetCachedTexture(this.TexturePath); } - return Cache.CreateCachedTexture(this.Image, this.TexturePath); + return this.RenderCache.CreateCachedTexture(this.Image, this.TexturePath); } /// @@ -85,10 +89,9 @@ public override void Dispose() } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { - var otherImage = obj as RenderableBitmap; - if (otherImage == null) + if (!(obj is RenderableBitmap otherImage)) { return false; } diff --git a/Everlook/Viewport/Rendering/RenderableBoundingBox.cs b/Everlook/Viewport/Rendering/RenderableBoundingBox.cs index 18d3c6b..54ef67e 100644 --- a/Everlook/Viewport/Rendering/RenderableBoundingBox.cs +++ b/Everlook/Viewport/Rendering/RenderableBoundingBox.cs @@ -29,9 +29,6 @@ using Everlook.Viewport.Rendering.Core; using Everlook.Viewport.Rendering.Interfaces; using Everlook.Viewport.Rendering.Shaders; -using OpenTK; -using OpenTK.Graphics; -using OpenTK.Graphics.OpenGL; using Silk.NET.OpenGL; using Warcraft.Core.Structures; @@ -40,7 +37,7 @@ namespace Everlook.Viewport.Rendering /// /// Wraps a as a renderable in-world actor. /// - public sealed class RenderableBoundingBox : IInstancedRenderable, IActor + public sealed class RenderableBoundingBox : GraphicsObject, IInstancedRenderable, IActor { private readonly BoundingBoxShader _boxShader; @@ -59,7 +56,7 @@ public sealed class RenderableBoundingBox : IInstancedRenderable, IActor /// /// Gets or sets the colour of the bounding box's lines. /// - public Color4 LineColour { get; set; } + public Vector4 LineColour { get; set; } /// /// Gets or sets a value indicating whether this object has been disposed. @@ -74,15 +71,18 @@ public sealed class RenderableBoundingBox : IInstancedRenderable, IActor /// Initializes a new instance of the class. The bounds data is taken from /// the given , and the world translation is set to . /// + /// The OpenGL API. + /// The rendering cache. /// The BoundingBox to get data from. /// The world transform of the box. - public RenderableBoundingBox(Box boundingBox, Transform transform) + public RenderableBoundingBox(GL gl, RenderCache renderCache, Box boundingBox, Transform transform) + : base(gl) { _boundingBoxData = boundingBox; - this.LineColour = Color4.LimeGreen; + this.LineColour = new Vector4(0.0f, 1.0f, 0.0f, 1.0f); this.ActorTransform = transform; - _boxShader = (BoundingBoxShader)RenderCache.Instance.GetShader(EverlookShader.BoundingBox); + _boxShader = (BoundingBoxShader)renderCache.GetShader(EverlookShader.BoundingBox); this.IsInitialized = false; } @@ -102,12 +102,23 @@ public void Initialize() throw new ShaderNullException(typeof(BoundingBoxShader)); } - _vertexBuffer = new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw) + _vertexBuffer = new Buffer(this.GL, BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw) { Data = _boundingBoxData.GetCorners().ToArray() }; - _vertexBuffer.AttachAttributePointer(new VertexAttributePointer(0, 3, VertexAttribPointerType.Float, 0, 0)); + _vertexBuffer.AttachAttributePointer + ( + new VertexAttributePointer + ( + this.GL, + 0, + 3, + VertexAttribPointerType.Float, + 0, + 0 + ) + ); byte[] boundingBoxIndexValues = { @@ -128,7 +139,12 @@ public void Initialize() 5, 3 }; - _vertexIndexesBuffer = new Buffer(BufferTargetARB.ElementArrayBuffer, BufferUsageARB.StaticDraw) + _vertexIndexesBuffer = new Buffer + ( + this.GL, + BufferTargetARB.ElementArrayBuffer, + BufferUsageARB.StaticDraw + ) { Data = boundingBoxIndexValues }; @@ -146,8 +162,8 @@ public void RenderInstances(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, Vi return; } - GL.Disable(EnableCap.CullFace); - GL.Disable(EnableCap.DepthTest); + this.GL.Disable(EnableCap.CullFace); + this.GL.Disable(EnableCap.DepthTest); // Send the vertices to the shader _vertexBuffer.Bind(); @@ -167,7 +183,7 @@ public void RenderInstances(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, Vi // Now draw the box unsafe { - GL.DrawElementsInstanced + this.GL.DrawElementsInstanced ( PrimitiveType.LineLoop, 24, @@ -190,8 +206,8 @@ public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCam return; } - GL.Disable(EnableCap.CullFace); - GL.Disable(EnableCap.DepthTest); + this.GL.Disable(EnableCap.CullFace); + this.GL.Disable(EnableCap.DepthTest); // Send the vertices to the shader _vertexBuffer.Bind(); @@ -208,7 +224,7 @@ public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCam // Now draw the box unsafe { - GL.DrawElements + this.GL.DrawElements ( PrimitiveType.LineLoop, 24, @@ -228,7 +244,7 @@ private void ThrowIfDisposed() { if (this.IsDisposed) { - throw new ObjectDisposedException(ToString()); + throw new ObjectDisposedException(ToString() ?? nameof(RenderableBoundingBox)); } } diff --git a/Everlook/Viewport/Rendering/RenderableGameModel.cs b/Everlook/Viewport/Rendering/RenderableGameModel.cs index d0ea905..e5b73a3 100644 --- a/Everlook/Viewport/Rendering/RenderableGameModel.cs +++ b/Everlook/Viewport/Rendering/RenderableGameModel.cs @@ -50,6 +50,7 @@ namespace Everlook.Viewport.Rendering /// Represents a renderable Game Object Model. /// public sealed class RenderableGameModel : + GraphicsObject, IInstancedRenderable, ITickingActor, IDefaultCameraPositionProvider, @@ -72,16 +73,17 @@ public Vector3 DefaultCameraPosition return Vector3.Zero; } - return + var vec4 = Vector4.Transform ( - this.ActorTransform.GetModelMatrix() * new Vector4 ( _model.BoundingBox.GetCenterCoordinates(), 1.0f - ) - ) - .Xyz; + ), + this.ActorTransform.GetModelMatrix() + ); + + return new Vector3(vec4.X, vec4.Y, vec4.Z); } } @@ -105,7 +107,7 @@ public Vector3 DefaultCameraPosition public int VertexCount => (int)_model.Vertices.Count; private readonly string? _modelPath; - private readonly RenderCache _cache = RenderCache.Instance; + private readonly RenderCache _renderCache; private readonly WarcraftGameContext _gameContext; /// @@ -141,11 +143,13 @@ public Vector3 DefaultCameraPosition /// /// Initializes a new instance of the class. /// + /// The OpenGL API. + /// The rendering cache. /// The model to render. /// The game context. /// The full path of the model in the package group. - public RenderableGameModel(MDX inModel, WarcraftGameContext gameContext, string modelPath) - : this(inModel, gameContext) + public RenderableGameModel(GL gl, RenderCache renderCache, MDX inModel, WarcraftGameContext gameContext, string modelPath) + : this(gl, renderCache, inModel, gameContext) { _modelPath = modelPath; } @@ -153,10 +157,14 @@ public RenderableGameModel(MDX inModel, WarcraftGameContext gameContext, string /// /// Initializes a new instance of the class. /// + /// The OpenGL API. + /// The rendering cache. /// The model to render. /// The game context. - public RenderableGameModel(MDX inModel, WarcraftGameContext gameContext) + public RenderableGameModel(GL gl, RenderCache renderCache, MDX inModel, WarcraftGameContext gameContext) + : base(gl) { + _renderCache = renderCache; _model = inModel; _gameContext = gameContext; @@ -182,14 +190,14 @@ public void Initialize() return; } - _shader = _cache.GetShader(EverlookShader.GameModel) as GameModelShader; + _shader = _renderCache.GetShader(EverlookShader.GameModel) as GameModelShader; if (_shader == null) { throw new ShaderNullException(typeof(GameModelShader)); } - _vertexBuffer = new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw) + _vertexBuffer = new Buffer(this.GL, BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw) { Data = _model.Vertices.Select(v => v.PackForOpenGL()).SelectMany(b => b).ToArray() }; @@ -197,22 +205,43 @@ public void Initialize() var attributePointers = new[] { // Position - new VertexAttributePointer(0, 3, VertexAttribPointerType.Float, MDXVertex.GetSize(), 0), + new VertexAttributePointer(this.GL, 0, 3, VertexAttribPointerType.Float, (uint)MDXVertex.GetSize(), 0), + // Bone weights - new VertexAttributePointer(1, 4, VertexAttribPointerType.UnsignedByte, MDXVertex.GetSize(), 12), + new VertexAttributePointer + ( + this.GL, + 1, + 4, + VertexAttribPointerType.UnsignedByte, + (uint)MDXVertex.GetSize(), + 12 + ), + // Bone indexes - new VertexAttributePointer(2, 4, VertexAttribPointerType.UnsignedByte, MDXVertex.GetSize(), 16), + new VertexAttributePointer + ( + this.GL, + 2, + 4, + VertexAttribPointerType.UnsignedByte, + (uint)MDXVertex.GetSize(), + 16 + ), + // Normal - new VertexAttributePointer(3, 3, VertexAttribPointerType.Float, MDXVertex.GetSize(), 20), + new VertexAttributePointer(this.GL, 3, 3, VertexAttribPointerType.Float, (uint)MDXVertex.GetSize(), 20), + // UV1 - new VertexAttributePointer(4, 2, VertexAttribPointerType.Float, MDXVertex.GetSize(), 32), + new VertexAttributePointer(this.GL, 4, 2, VertexAttribPointerType.Float, (uint)MDXVertex.GetSize(), 32), + // UV2 - new VertexAttributePointer(5, 2, VertexAttribPointerType.Float, MDXVertex.GetSize(), 40) + new VertexAttributePointer(this.GL, 5, 2, VertexAttribPointerType.Float, (uint)MDXVertex.GetSize(), 40) }; _vertexBuffer.AttachAttributePointers(attributePointers); - _boundingBox = new RenderableBoundingBox(_model.BoundingBox, this.ActorTransform); + _boundingBox = new RenderableBoundingBox(this.GL, _renderCache, _model.BoundingBox, this.ActorTransform); _boundingBox.Initialize(); foreach (var texture in _model.Textures) @@ -222,7 +251,7 @@ public void Initialize() _textureLookup.Add ( texture.Filename, - _cache.GetTexture(texture, _gameContext) + _renderCache.GetTexture(texture, _gameContext) ); } } @@ -234,7 +263,12 @@ public void Initialize() relativeIndex => skin.VertexIndices[relativeIndex] ).ToArray(); - var skinIndexBuffer = new Buffer(BufferTargetARB.ElementArrayBuffer, BufferUsageARB.StaticDraw) + var skinIndexBuffer = new Buffer + ( + this.GL, + BufferTargetARB.ElementArrayBuffer, + BufferUsageARB.StaticDraw + ) { Data = absoluteTriangleVertexIndexes }; @@ -459,7 +493,7 @@ private void PrepareBatchForRender(MDXRenderBatch renderBatch) _shader.SetFragmentShaderType(fragmentShader); _shader.SetMaterial(batchMaterial); - var baseColour = Color4.White; + var baseColour = Vector4.One; if (renderBatch.ColorIndex >= 0) { var colorAnimation = _model.ColourAnimations[renderBatch.ColorIndex]; @@ -471,20 +505,20 @@ private void PrepareBatchForRender(MDXRenderBatch renderBatch) if (colorAnimation.ColourTrack.IsComposite) { rgb = colorAnimation.ColourTrack.CompositeTimelineValues.First(); - alpha = colorAnimation.OpacityTrack.CompositeTimelineValues.First() / 0x7fff; + alpha = (float)colorAnimation.OpacityTrack.CompositeTimelineValues.First() / 0x7fff; } else { rgb = colorAnimation.ColourTrack.Values.First().First(); - alpha = colorAnimation.OpacityTrack.Values.First().First() / 0x7fff; + alpha = (float)colorAnimation.OpacityTrack.Values.First().First() / 0x7fff; } - baseColour = new Color4 + baseColour = new Vector4 ( - MathHelper.Clamp(rgb.R, 0.0f, 1.0f), - MathHelper.Clamp(rgb.G, 0.0f, 1.0f), - MathHelper.Clamp(rgb.B, 0.0f, 1.0f), - MathHelper.Clamp(alpha, 0.0f, 1.0f) + Math.Clamp(rgb.R, 0.0f, 1.0f), + Math.Clamp(rgb.G, 0.0f, 1.0f), + Math.Clamp(rgb.B, 0.0f, 1.0f), + Math.Clamp(alpha, 0.0f, 1.0f) ); } @@ -496,14 +530,14 @@ private void PrepareBatchForRender(MDXRenderBatch renderBatch) float alphaWeight; if (transparencyAnimation.Weight.IsComposite) { - alphaWeight = transparencyAnimation.Weight.CompositeTimelineValues.First() / 0x7fff; + alphaWeight = (float)transparencyAnimation.Weight.CompositeTimelineValues.First() / 0x7fff; } else { - alphaWeight = transparencyAnimation.Weight.Values.First().First() / 0x7fff; + alphaWeight = (float)transparencyAnimation.Weight.Values.First().First() / 0x7fff; } - baseColour.A *= alphaWeight; + baseColour.W *= alphaWeight; } _shader.SetBaseInputColour(baseColour); @@ -721,7 +755,7 @@ private void CacheDisplayInfo(CreatureDisplayInfoRecord displayInfoRecord) _textureLookup.Add ( texturePath, - _cache.GetTexture(texture, _gameContext, texturePath) + _renderCache.GetTexture(texture, _gameContext, texturePath) ); } } @@ -734,7 +768,7 @@ private void ThrowIfDisposed() { if (this.IsDisposed) { - throw new ObjectDisposedException(ToString()); + throw new ObjectDisposedException(ToString() ?? nameof(RenderableGameModel)); } } @@ -752,10 +786,9 @@ public void Dispose() } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { - var otherModel = obj as RenderableGameModel; - if (otherModel == null) + if (!(obj is RenderableGameModel otherModel)) { return false; } diff --git a/Everlook/Viewport/Rendering/RenderableImage.cs b/Everlook/Viewport/Rendering/RenderableImage.cs index ee35f3d..29aab3a 100644 --- a/Everlook/Viewport/Rendering/RenderableImage.cs +++ b/Everlook/Viewport/Rendering/RenderableImage.cs @@ -27,6 +27,7 @@ using Everlook.Viewport.Rendering.Core; using Everlook.Viewport.Rendering.Interfaces; using Everlook.Viewport.Rendering.Shaders; +using JetBrains.Annotations; using Silk.NET.OpenGL; using Warcraft.Core.Extensions; using Warcraft.Core.Structures; @@ -36,12 +37,12 @@ namespace Everlook.Viewport.Rendering /// /// Represents a renderable 2D image, and contains common functionality required to render one. /// - public abstract class RenderableImage : IRenderable, IActor, IDefaultCameraPositionProvider + public abstract class RenderableImage : GraphicsObject, IRenderable, IActor, IDefaultCameraPositionProvider { /// /// Gets a reference to the global shader cache. /// - protected static RenderCache Cache => RenderCache.Instance; + protected RenderCache RenderCache { get; } /// /// Gets or sets a value indicating whether this object has been disposed. @@ -132,6 +133,17 @@ public abstract class RenderableImage : IRenderable, IActor, IDefaultCameraPosit /// public uint MipCount => GetNumReasonableMipLevels(); + /// + /// Initializes a new instance of the class. + /// + /// The OpenGL API. + /// The rendering cache. + protected RenderableImage([NotNull] GL gl, RenderCache renderCache) + : base(gl) + { + this.RenderCache = renderCache; + } + /// /// TODO: Put this in Warcraft.Core instead. /// @@ -172,13 +184,13 @@ public void Initialize() this.Texture = LoadTexture(); // Use cached shaders whenever possible - this.Shader = Cache.GetShader(EverlookShader.Plain2D) as Plain2DShader; + this.Shader = RenderCache.GetShader(EverlookShader.Plain2D) as Plain2DShader; this.ActorTransform = new Transform(); - GL.Enable(EnableCap.Blend); - GL.BlendEquation(BlendEquationModeEXT.FuncAdd); - GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); + this.GL.Enable(EnableCap.Blend); + this.GL.BlendEquation(BlendEquationModeEXT.FuncAdd); + this.GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); this.IsInitialized = true; } @@ -216,12 +228,12 @@ this.Texture is null // Render the object // Send the vertices to the shader - GL.EnableVertexAttribArray(0); + this.GL.EnableVertexAttribArray(0); this.VertexBuffer.Bind(); unsafe { - GL.VertexAttribPointer + this.GL.VertexAttribPointer ( 0u, 2, @@ -233,11 +245,11 @@ this.Texture is null } // Send the UV coordinates to the shader - GL.EnableVertexAttribArray(1); + this.GL.EnableVertexAttribArray(1); this.UVBuffer.Bind(); unsafe { - GL.VertexAttribPointer + this.GL.VertexAttribPointer ( 1u, 2, @@ -254,7 +266,7 @@ this.Texture is null // Set the texture ID as a uniform sampler in unit 0 this.Shader.SetTexture(this.Texture); - GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); + this.GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); // Set the model view matrix var modelViewProjection = this.ActorTransform.GetModelMatrix() * viewMatrix * projectionMatrix; @@ -266,12 +278,12 @@ this.Texture is null this.VertexIndexBuffer.Bind(); unsafe { - GL.DrawElements(PrimitiveType.Triangles, 6u, DrawElementsType.UnsignedShort, (void*)0); + this.GL.DrawElements(PrimitiveType.Triangles, 6u, DrawElementsType.UnsignedShort, (void*)0); } // Release the attribute arrays - GL.DisableVertexAttribArray(0); - GL.DisableVertexAttribArray(1); + this.GL.DisableVertexAttribArray(0); + this.GL.DisableVertexAttribArray(1); } /// @@ -299,7 +311,7 @@ protected Buffer GenerateVertices() }; // Buffer the generated vertices in the GPU - return new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw) + return new Buffer(this.GL, BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw) { Data = vertexPositions.ToArray() }; @@ -309,12 +321,12 @@ protected Buffer GenerateVertices() /// Generates a vertex index buffer for the four corner vertices. /// /// The vertex index buffer. - protected static Buffer GenerateVertexIndexes() + protected Buffer GenerateVertexIndexes() { // Generate vertex indexes var vertexIndexes = new List { 1, 0, 2, 2, 3, 1 }; - return new Buffer(BufferTargetARB.ElementArrayBuffer, BufferUsageARB.StaticDraw) + return new Buffer(this.GL, BufferTargetARB.ElementArrayBuffer, BufferUsageARB.StaticDraw) { Data = vertexIndexes.ToArray() }; @@ -324,7 +336,7 @@ protected static Buffer GenerateVertexIndexes() /// Generates a UV coordinate buffer for the four corner vertices. /// /// The native OpenGL ID of the buffer. - protected static Buffer GenerateTextureCoordinates() + protected Buffer GenerateTextureCoordinates() { // Generate UV coordinates var textureCoordinates = new List @@ -336,7 +348,7 @@ protected static Buffer GenerateTextureCoordinates() }; // Buffer the generated UV coordinates in the GPU - return new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw) + return new Buffer(this.GL, BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw) { Data = textureCoordinates.ToArray() }; @@ -350,7 +362,7 @@ private void ThrowIfDisposed() { if (this.IsDisposed) { - throw new ObjectDisposedException(ToString()); + throw new ObjectDisposedException(ToString() ?? nameof(RenderableImage)); } } diff --git a/Everlook/Viewport/Rendering/RenderableWorldModel.cs b/Everlook/Viewport/Rendering/RenderableWorldModel.cs index 1c64181..f395a1a 100644 --- a/Everlook/Viewport/Rendering/RenderableWorldModel.cs +++ b/Everlook/Viewport/Rendering/RenderableWorldModel.cs @@ -43,6 +43,7 @@ namespace Everlook.Viewport.Rendering /// Represents a renderable World Model Object. /// public sealed class RenderableWorldModel : + GraphicsObject, IRenderable, ITickingActor, IDefaultCameraPositionProvider, @@ -53,6 +54,11 @@ public sealed class RenderableWorldModel : /// private static readonly ILog Log = LogManager.GetLogger(typeof(RenderableWorldModel)); + /// + /// Holds the render cache. + /// + private RenderCache _renderCache; + /// /// Gets or sets a value indicating whether this object has been disposed. /// @@ -79,19 +85,20 @@ public Vector3 DefaultCameraPosition return Vector3.Zero; } - return + var vec4 = Vector4.Transform ( - this.ActorTransform.GetModelMatrix() * new Vector4 ( _model.Groups - .First() - .GetBoundingBox() - .GetCenterCoordinates(), + .First() + .GetBoundingBox() + .GetCenterCoordinates(), 1.0f - ) - ) - .Xyz; + ), + this.ActorTransform.GetModelMatrix() + ); + + return new Vector3(vec4.X, vec4.Y, vec4.Z); } } @@ -104,7 +111,6 @@ public Vector3 DefaultCameraPosition /// public Transform ActorTransform { get; set; } - private readonly RenderCache _cache = RenderCache.Instance; private readonly WarcraftGameContext _gameContext; /// @@ -170,10 +176,14 @@ public Vector3 DefaultCameraPosition /// /// Initializes a new instance of the class. /// + /// The OpenGL API. + /// The rendering cache. /// The model to render. /// The game context. - public RenderableWorldModel(WMO inModel, WarcraftGameContext gameContext) + public RenderableWorldModel(GL gl, RenderCache renderCache, WMO inModel, WarcraftGameContext gameContext) + : base(gl) { + _renderCache = renderCache; _model = inModel; _gameContext = gameContext; @@ -194,7 +204,7 @@ public void Initialize() this.IsInitialized = true; - _shader = _cache.GetShader(EverlookShader.WorldModel) as WorldModelShader; + _shader = _renderCache.GetShader(EverlookShader.WorldModel) as WorldModelShader; if (_shader == null) { @@ -212,7 +222,7 @@ public void Initialize() { if (!_textureLookup.ContainsKey(texture)) { - _textureLookup.Add(texture, _cache.GetTexture(texture, _gameContext.Assets)); + _textureLookup.Add(texture, _renderCache.GetTexture(texture, _gameContext.Assets)); } } } @@ -292,7 +302,14 @@ public void LoadDoodads() } // Then create a new renderable game model - var renderableDoodad = new RenderableGameModel(doodadModel, _gameContext, firstInstance.Name); + var renderableDoodad = new RenderableGameModel + ( + this.GL, + _renderCache, + doodadModel, + _gameContext, + firstInstance.Name + ); // And cache it _doodadCache.Add(firstInstance.Name, renderableDoodad); @@ -312,7 +329,11 @@ public void LoadDoodads() ); } - var instanceSet = new ActorInstanceSet(_doodadCache[firstInstance.Name]); + var instanceSet = new ActorInstanceSet + ( + this.GL, _doodadCache[firstInstance.Name] + ); + instanceSet.SetInstances(instanceTransforms); doodadSetInstanceGroups.Add(instanceSet); @@ -332,22 +353,31 @@ private void InitializeModelGroup(ModelGroup modelGroup) Buffers */ - var vertexBuffer = new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw); - var normalBuffer = new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw); - var coordinateBuffer = new Buffer(BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw); - var vertexIndexes = new Buffer(BufferTargetARB.ElementArrayBuffer, BufferUsageARB.StaticDraw); + var vertexBuffer = new Buffer(this.GL, BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw); + var normalBuffer = new Buffer(this.GL, BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw); + var coordinateBuffer = new Buffer(this.GL, BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw); + var vertexIndexes = new Buffer + ( + this.GL, BufferTargetARB.ElementArrayBuffer, BufferUsageARB.StaticDraw + ); // Upload all of the vertices in this group vertexBuffer.Data = modelGroup.GetVertices().Select(v => v).ToArray(); _vertexBufferLookup.Add(modelGroup, vertexBuffer); - vertexBuffer.AttachAttributePointer(new VertexAttributePointer(0, 3, VertexAttribPointerType.Float, 0, 0)); + vertexBuffer.AttachAttributePointer + ( + new VertexAttributePointer(this.GL, 0, 3, VertexAttribPointerType.Float, 0, 0) + ); // Upload all of the normals in this group normalBuffer.Data = modelGroup.GetNormals().Select(v => v).ToArray(); _normalBufferLookup.Add(modelGroup, normalBuffer); - normalBuffer.AttachAttributePointer(new VertexAttributePointer(1, 3, VertexAttribPointerType.Float, 0, 0)); + normalBuffer.AttachAttributePointer + ( + new VertexAttributePointer(this.GL, 1, 3, VertexAttribPointerType.Float, 0, 0) + ); // Upload all of the UVs in this group coordinateBuffer.Data = modelGroup.GetTextureCoordinates().Select(v => v).ToArray(); @@ -355,7 +385,7 @@ private void InitializeModelGroup(ModelGroup modelGroup) coordinateBuffer.AttachAttributePointer ( - new VertexAttributePointer(2, 2, VertexAttribPointerType.Float, 0, 0) + new VertexAttributePointer(this.GL, 2, 2, VertexAttribPointerType.Float, 0, 0) ); // Upload vertex indices for this group @@ -364,6 +394,8 @@ private void InitializeModelGroup(ModelGroup modelGroup) var boundingBox = new RenderableBoundingBox ( + this.GL, + _renderCache, modelGroup.GetBoundingBox(), this.ActorTransform ); @@ -465,7 +497,7 @@ private void RenderGroup(ModelGroup modelGroup, Matrix4x4 modelViewProjection) } // Reenable depth test - GL.Enable(EnableCap.DepthTest); + this.GL.Enable(EnableCap.DepthTest); // Render the object // Send the vertices to the shader @@ -486,7 +518,7 @@ private void RenderGroup(ModelGroup modelGroup, Matrix4x4 modelViewProjection) _shader.Wireframe.SetWireframeColour(EverlookConfiguration.Instance.WireframeColour); // Override blend setting - GL.Enable(EnableCap.Blend); + this.GL.Enable(EnableCap.Blend); } // Render all the different materials (opaque first, transparent after) @@ -502,10 +534,10 @@ private void RenderGroup(ModelGroup modelGroup, Matrix4x4 modelViewProjection) _shader.SetMVPMatrix(modelViewProjection); // Set the texture as the first diffuse texture in unit 0 - var texture = _cache.GetCachedTexture(modelMaterial.DiffuseTexture); + var texture = _renderCache.GetCachedTexture(modelMaterial.DiffuseTexture); if (modelMaterial.Flags.HasFlag(MaterialFlags.TextureWrappingClampS)) { - texture.WrappingMode = TextureWrapMode.Clamp; + texture.WrappingMode = TextureWrapMode.ClampToBorder; } else { @@ -517,7 +549,7 @@ private void RenderGroup(ModelGroup modelGroup, Matrix4x4 modelViewProjection) // Finally, draw the model unsafe { - GL.DrawRangeElements + this.GL.DrawRangeElements ( PrimitiveType.Triangles, renderBatch.FirstPolygonIndex, @@ -552,7 +584,7 @@ private void ThrowIfDisposed() { if (this.IsDisposed) { - throw new ObjectDisposedException(ToString()); + throw new ObjectDisposedException(ToString() ?? nameof(RenderableWorldModel)); } } @@ -588,10 +620,9 @@ public void Dispose() } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { - var otherModel = obj as RenderableWorldModel; - if (otherModel == null) + if (!(obj is RenderableWorldModel otherModel)) { return false; } diff --git a/Everlook/Viewport/Rendering/Shaders/BaseGridShader.cs b/Everlook/Viewport/Rendering/Shaders/BaseGridShader.cs index 164d6a8..5c9243b 100644 --- a/Everlook/Viewport/Rendering/Shaders/BaseGridShader.cs +++ b/Everlook/Viewport/Rendering/Shaders/BaseGridShader.cs @@ -20,8 +20,10 @@ // along with this program. If not, see . // +using System.Numerics; using Everlook.Viewport.Rendering.Core; -using OpenTK.Graphics; +using JetBrains.Annotations; +using Silk.NET.OpenGL; namespace Everlook.Viewport.Rendering.Shaders { @@ -41,13 +43,22 @@ public class BaseGridShader : ShaderProgram private const string ColourIdentifier = "lineColour"; + /// + /// Initializes a new instance of the class. + /// + /// The OpenGL API. + public BaseGridShader([NotNull] GL gl) + : base(gl) + { + } + /// /// Sets the line colour of the bounding box. /// /// The colour to set the lines to. - public void SetLineColour(Color4 colour) + public void SetLineColour(Vector4 colour) { - SetColor4(colour, ColourIdentifier); + SetVector4(colour, ColourIdentifier); } } } diff --git a/Everlook/Viewport/Rendering/Shaders/BoundingBoxShader.cs b/Everlook/Viewport/Rendering/Shaders/BoundingBoxShader.cs index 761de84..833f90f 100644 --- a/Everlook/Viewport/Rendering/Shaders/BoundingBoxShader.cs +++ b/Everlook/Viewport/Rendering/Shaders/BoundingBoxShader.cs @@ -22,8 +22,8 @@ using System.Numerics; using Everlook.Viewport.Rendering.Core; -using OpenTK; -using OpenTK.Graphics; +using JetBrains.Annotations; +using Silk.NET.OpenGL; namespace Everlook.Viewport.Rendering.Shaders { @@ -48,6 +48,15 @@ public class BoundingBoxShader : ShaderProgram /// protected override string? GeometryShaderResourceName => null; + /// + /// Initializes a new instance of the class. + /// + /// The OpenGL API. + public BoundingBoxShader([NotNull] GL gl) + : base(gl) + { + } + /// /// Sets the instancing flag. /// @@ -79,9 +88,9 @@ public void SetProjectionMatrix(Matrix4x4 projectionMatrix) /// Sets the line colour of the bounding box. /// /// The colour to set the lines to. - public void SetLineColour(Color4 colour) + public void SetLineColour(Vector4 colour) { - SetColor4(colour, ColourIdentifier); + SetVector4(colour, ColourIdentifier); } } } diff --git a/Everlook/Viewport/Rendering/Shaders/Components/AmbientLighting.cs b/Everlook/Viewport/Rendering/Shaders/Components/AmbientLighting.cs index 36399de..e694517 100644 --- a/Everlook/Viewport/Rendering/Shaders/Components/AmbientLighting.cs +++ b/Everlook/Viewport/Rendering/Shaders/Components/AmbientLighting.cs @@ -20,8 +20,8 @@ // along with this program. If not, see . // -using OpenTK.Graphics; -using OpenTK.Graphics.OpenGL; +using System.Numerics; +using Everlook.Viewport.Rendering.Core; using Silk.NET.OpenGL; namespace Everlook.Viewport.Rendering.Shaders.Components @@ -29,19 +29,21 @@ namespace Everlook.Viewport.Rendering.Shaders.Components /// /// An ambient lighting shader component. /// - public class AmbientLighting + public class AmbientLighting : GraphicsObject { private const string AmbientColourIdentifier = "AmbientColour"; private const string AmbientIntensityIdentifier = "AmbientIntensity"; - private readonly int _parentShaderNativeID; + private readonly uint _parentShaderNativeID; /// /// Initializes a new instance of the class, and attaches it to the given parent /// shader. /// + /// The OpenGL API. /// The native ID of the parent shader. - public AmbientLighting(int parentShaderID) + public AmbientLighting(GL gl, uint parentShaderID) + : base(gl) { _parentShaderNativeID = parentShaderID; } @@ -50,10 +52,10 @@ public AmbientLighting(int parentShaderID) /// Sets the colour of the ambient light shader. /// /// The colour of the light. - public void SetAmbientColour(Color4 lightColour) + public void SetAmbientColour(Vector4 lightColour) { - var colourLoc = GL.GetUniformLocation(_parentShaderNativeID, AmbientColourIdentifier); - GL.Uniform4(colourLoc, lightColour); + var colourLoc = this.GL.GetUniformLocation(_parentShaderNativeID, AmbientColourIdentifier); + this.GL.Uniform4(colourLoc, lightColour); } /// @@ -62,8 +64,8 @@ public void SetAmbientColour(Color4 lightColour) /// The intensity, in lux. public void SetAmbientIntensity(float lightIntensity) { - var intensityLoc = GL.GetUniformLocation(_parentShaderNativeID, AmbientIntensityIdentifier); - GL.Uniform1(intensityLoc, lightIntensity); + var intensityLoc = this.GL.GetUniformLocation(_parentShaderNativeID, AmbientIntensityIdentifier); + this.GL.Uniform1(intensityLoc, lightIntensity); } } } diff --git a/Everlook/Viewport/Rendering/Shaders/Components/GlobalLighting.cs b/Everlook/Viewport/Rendering/Shaders/Components/GlobalLighting.cs index a778cc2..46ad5f5 100644 --- a/Everlook/Viewport/Rendering/Shaders/Components/GlobalLighting.cs +++ b/Everlook/Viewport/Rendering/Shaders/Components/GlobalLighting.cs @@ -21,9 +21,7 @@ // using System.Numerics; -using OpenTK; -using OpenTK.Graphics; -using OpenTK.Graphics.OpenGL; +using Everlook.Viewport.Rendering.Core; using Silk.NET.OpenGL; namespace Everlook.Viewport.Rendering.Shaders.Components @@ -31,39 +29,41 @@ namespace Everlook.Viewport.Rendering.Shaders.Components /// /// A global light shader component. /// - public class GlobalLighting + public class GlobalLighting : GraphicsObject { private const string LightVectorIdentifier = "LightVector"; private const string LightColourIdentifier = "LightColour"; private const string LightIntensityIdentifier = "LightIntensity"; - private readonly int _parentShaderNativeID; + private readonly uint _parentShaderNativeID; /// /// Initializes a new instance of the class, and attaches it to the given parent /// shader. /// + /// The OpenGL API. /// The native ID of the parent shader. - public GlobalLighting(int parentShaderID) + public GlobalLighting(GL gl, uint parentShaderID) + : base(gl) { _parentShaderNativeID = parentShaderID; } private void EnableParent() { - GL.UseProgram(_parentShaderNativeID); + this.GL.UseProgram(_parentShaderNativeID); } /// /// Sets the colour of the global lighting shader component. /// /// The colour of the light. - public void SetLightColour(Color4 lightColour) + public void SetLightColour(Vector4 lightColour) { EnableParent(); - var colourLoc = GL.GetUniformLocation(_parentShaderNativeID, LightColourIdentifier); - GL.Uniform4(colourLoc, lightColour); + var colourLoc = this.GL.GetUniformLocation(_parentShaderNativeID, LightColourIdentifier); + this.GL.Uniform4(colourLoc, lightColour); } /// @@ -74,8 +74,8 @@ public void SetLightDirection(Vector3 lightVector) { EnableParent(); - var vectorLoc = GL.GetUniformLocation(_parentShaderNativeID, LightVectorIdentifier); - GL.Uniform3(vectorLoc, lightVector); + var vectorLoc = this.GL.GetUniformLocation(_parentShaderNativeID, LightVectorIdentifier); + this.GL.Uniform3(vectorLoc, lightVector); } /// @@ -86,8 +86,8 @@ public void SetLightIntensity(float lightIntensity) { EnableParent(); - var intensityLoc = GL.GetUniformLocation(_parentShaderNativeID, LightIntensityIdentifier); - GL.Uniform1(intensityLoc, lightIntensity); + var intensityLoc = this.GL.GetUniformLocation(_parentShaderNativeID, LightIntensityIdentifier); + this.GL.Uniform1(intensityLoc, lightIntensity); } } } diff --git a/Everlook/Viewport/Rendering/Shaders/Components/SolidWireframe.cs b/Everlook/Viewport/Rendering/Shaders/Components/SolidWireframe.cs index d712ffd..f30351a 100644 --- a/Everlook/Viewport/Rendering/Shaders/Components/SolidWireframe.cs +++ b/Everlook/Viewport/Rendering/Shaders/Components/SolidWireframe.cs @@ -20,10 +20,9 @@ // along with this program. If not, see . // +using System.Numerics; +using Everlook.Viewport.Rendering.Core; using Gdk; -using OpenTK; -using OpenTK.Graphics; -using OpenTK.Graphics.OpenGL; using Silk.NET.OpenGL; namespace Everlook.Viewport.Rendering.Shaders.Components @@ -31,7 +30,7 @@ namespace Everlook.Viewport.Rendering.Shaders.Components /// /// This shader component controls an implementation of solid wireframe rendering. /// - public class SolidWireframe + public class SolidWireframe : GraphicsObject { private const string ViewportMatrix = nameof(ViewportMatrix); @@ -45,14 +44,14 @@ public class SolidWireframe /// /// The standard colour of the wireframe. /// - public static readonly Color4 StandardColour = new Color4(234, 161, 0, 255); + public static readonly Vector4 StandardColour = new Vector4(234, 161, 0, 255); /// /// The standard highlight colour of the wireframe. /// - public static readonly Color4 HighlightColour = new Color4(217, 129, 3, 255); + public static readonly Vector4 HighlightColour = new Vector4(217, 129, 3, 255); - private readonly int _parentShaderNativeID; + private readonly uint _parentShaderNativeID; private bool _enabledInternal; @@ -73,8 +72,10 @@ public bool Enabled /// Initializes a new instance of the class, and attaches it to the given parent /// shader. /// + /// The OpenGL API. /// The native ID of the parent shader. - public SolidWireframe(int parentShaderID) + public SolidWireframe(GL gl, uint parentShaderID) + : base(gl) { _parentShaderNativeID = parentShaderID; this.Enabled = false; @@ -86,15 +87,15 @@ public SolidWireframe(int parentShaderID) private void EnableParent() { - GL.UseProgram(_parentShaderNativeID); + this.GL.UseProgram(_parentShaderNativeID); } private void SetWireframeState(bool isEnabled) { EnableParent(); - var enabledLoc = GL.GetUniformLocation(_parentShaderNativeID, IsWireframeEnabled); - GL.Uniform1(enabledLoc, isEnabled ? 1 : 0); + var enabledLoc = this.GL.GetUniformLocation(_parentShaderNativeID, IsWireframeEnabled); + this.GL.Uniform1(enabledLoc, isEnabled ? 1 : 0); } /// @@ -106,8 +107,8 @@ public void SetWireframeLineWidth(int lineWidth) { EnableParent(); - var lineWidthLoc = GL.GetUniformLocation(_parentShaderNativeID, WireframeLineWidth); - GL.Uniform1(lineWidthLoc, lineWidth); + var lineWidthLoc = this.GL.GetUniformLocation(_parentShaderNativeID, WireframeLineWidth); + this.GL.Uniform1(lineWidthLoc, lineWidth); } /// @@ -116,7 +117,7 @@ public void SetWireframeLineWidth(int lineWidth) /// The wire colour. public void SetWireframeColour(RGBA wireframeColour) { - var colour = new Color4 + var colour = new Vector4 ( (float)wireframeColour.Red, (float)wireframeColour.Green, @@ -131,12 +132,12 @@ public void SetWireframeColour(RGBA wireframeColour) /// Sets the colour of the wireframe. /// /// The wire colour. - public void SetWireframeColour(Color4 wireframeColour) + public void SetWireframeColour(Vector4 wireframeColour) { EnableParent(); - var colourLoc = GL.GetUniformLocation(_parentShaderNativeID, WireframeColour); - GL.Uniform4(colourLoc, wireframeColour); + var colourLoc = this.GL.GetUniformLocation(_parentShaderNativeID, WireframeColour); + this.GL.Uniform4(colourLoc, wireframeColour); } /// @@ -147,20 +148,23 @@ public void SetWireframeFadeWidth(int fadeWidth) { EnableParent(); - var fadeWidthLoc = GL.GetUniformLocation(_parentShaderNativeID, WireframeFadeWidth); - GL.Uniform1(fadeWidthLoc, fadeWidth); + var fadeWidthLoc = this.GL.GetUniformLocation(_parentShaderNativeID, WireframeFadeWidth); + this.GL.Uniform1(fadeWidthLoc, fadeWidth); } /// /// Sets the viewport matrix that will transform NDC coordinates to screen space coordinates. /// /// The viewport matrix. - public void SetViewportMatrix(Matrix3 viewportMatrix) + public void SetViewportMatrix(Matrix4x4 viewportMatrix) { EnableParent(); - var viewportMatrixLoc = GL.GetUniformLocation(_parentShaderNativeID, ViewportMatrix); - GL.UniformMatrix3(viewportMatrixLoc, false, ref viewportMatrix); + var viewportMatrixLoc = this.GL.GetUniformLocation(_parentShaderNativeID, ViewportMatrix); + unsafe + { + this.GL.UniformMatrix4(viewportMatrixLoc, 4 * 4, false, &viewportMatrix.M11); + } } } } diff --git a/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs b/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs index 3769ec6..776d1c6 100644 --- a/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs +++ b/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs @@ -24,9 +24,6 @@ using System.Numerics; using Everlook.Viewport.Rendering.Core; using Everlook.Viewport.Rendering.Shaders.Components; -using OpenTK; -using OpenTK.Graphics; -using OpenTK.Graphics.OpenGL; using Silk.NET.OpenGL; using Warcraft.Core.Shading.Blending; using Warcraft.Core.Shading.MDX; @@ -66,11 +63,13 @@ public class GameModelShader : ShaderProgram /// /// Initializes a new instance of the class. /// - public GameModelShader() + /// The OpenGL API. + public GameModelShader(GL gl) + : base(gl) { - this.Wireframe = new SolidWireframe(this.NativeShaderProgramID); + this.Wireframe = new SolidWireframe(this.GL, this.NativeShaderProgramID); - SetBaseInputColour(Color4.White); + SetBaseInputColour(Vector4.One); SetFragmentShaderType(MDXFragmentShaderType.Combiners_Opaque); } @@ -114,9 +113,9 @@ public void SetProjectionMatrix(Matrix4x4 projectionMatrix) /// Sets the base input colour for the shader. /// /// The base colour. - public void SetBaseInputColour(Color4 colour) + public void SetBaseInputColour(Vector4 colour) { - SetColor4(colour, BaseColour); + SetVector4(colour, BaseColour); } /// @@ -189,20 +188,20 @@ public void SetMaterial(MDXMaterial modelMaterial) // Set two-sided rendering if (modelMaterial.Flags.HasFlag(MDXRenderFlag.TwoSided)) { - GL.Disable(EnableCap.CullFace); + this.GL.Disable(EnableCap.CullFace); } else { - GL.Enable(EnableCap.CullFace); + this.GL.Enable(EnableCap.CullFace); } if (BlendingState.EnableBlending[modelMaterial.BlendMode]) { - GL.Enable(EnableCap.Blend); + this.GL.Enable(EnableCap.Blend); } else { - GL.Disable(EnableCap.Blend); + this.GL.Disable(EnableCap.Blend); } var dstA = BlendingState.DestinationAlpha[modelMaterial.BlendMode]; @@ -211,7 +210,7 @@ public void SetMaterial(MDXMaterial modelMaterial) var dstC = BlendingState.DestinationColour[modelMaterial.BlendMode]; var srcC = BlendingState.SourceColour[modelMaterial.BlendMode]; - GL.BlendFuncSeparate + this.GL.BlendFuncSeparate ( (BlendingFactor)srcC, (BlendingFactor)dstC, diff --git a/Everlook/Viewport/Rendering/Shaders/Plain2DShader.cs b/Everlook/Viewport/Rendering/Shaders/Plain2DShader.cs index 54d9429..c5726c3 100644 --- a/Everlook/Viewport/Rendering/Shaders/Plain2DShader.cs +++ b/Everlook/Viewport/Rendering/Shaders/Plain2DShader.cs @@ -22,8 +22,7 @@ using System.Numerics; using Everlook.Viewport.Rendering.Core; -using OpenTK; -using OpenTK.Graphics.OpenGL; +using JetBrains.Annotations; using Silk.NET.OpenGL; namespace Everlook.Viewport.Rendering.Shaders @@ -44,6 +43,15 @@ public class Plain2DShader : ShaderProgram /// protected override string? GeometryShaderResourceName => null; + /// + /// Initializes a new instance of the class. + /// + /// The OpenGL API. + public Plain2DShader([NotNull] GL gl) + : base(gl) + { + } + /// /// Sets the channel mask of the shader. /// diff --git a/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs b/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs index 002fe66..131d717 100644 --- a/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs +++ b/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs @@ -23,7 +23,6 @@ using System; using Everlook.Viewport.Rendering.Core; using Everlook.Viewport.Rendering.Shaders.Components; -using OpenTK.Graphics.OpenGL; using Silk.NET.OpenGL; using Warcraft.Core.Shading.Blending; using Warcraft.WMO.RootFile.Chunks; @@ -54,9 +53,11 @@ public class WorldModelShader : ShaderProgram /// /// Initializes a new instance of the class. /// - public WorldModelShader() + /// The OpenGL API. + public WorldModelShader(GL gl) + : base(gl) { - this.Wireframe = new SolidWireframe(this.NativeShaderProgramID); + this.Wireframe = new SolidWireframe(this.GL, this.NativeShaderProgramID); } /// @@ -75,20 +76,20 @@ public void SetMaterial(ModelMaterial modelMaterial) // Set two-sided rendering if (modelMaterial.Flags.HasFlag(MaterialFlags.TwoSided)) { - GL.Disable(EnableCap.CullFace); + this.GL.Disable(EnableCap.CullFace); } else { - GL.Enable(EnableCap.CullFace); + this.GL.Enable(EnableCap.CullFace); } if (BlendingState.EnableBlending[modelMaterial.BlendMode]) { - GL.Enable(EnableCap.Blend); + this.GL.Enable(EnableCap.Blend); } else { - GL.Disable(EnableCap.Blend); + this.GL.Disable(EnableCap.Blend); } var dstA = BlendingState.DestinationAlpha[modelMaterial.BlendMode]; @@ -97,7 +98,7 @@ public void SetMaterial(ModelMaterial modelMaterial) var dstC = BlendingState.DestinationColour[modelMaterial.BlendMode]; var srcC = BlendingState.SourceColour[modelMaterial.BlendMode]; - GL.BlendFuncSeparate + this.GL.BlendFuncSeparate ( (BlendingFactor)srcC, (BlendingFactor)dstC, diff --git a/Everlook/Viewport/ViewportRenderer.cs b/Everlook/Viewport/ViewportRenderer.cs index c4c7569..2efc5d1 100644 --- a/Everlook/Viewport/ViewportRenderer.cs +++ b/Everlook/Viewport/ViewportRenderer.cs @@ -22,10 +22,12 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Runtime.InteropServices; using Everlook.Configuration; using Everlook.UI.Widgets; using Everlook.Viewport.Camera; +using Everlook.Viewport.Rendering; using Everlook.Viewport.Rendering.Core; using Everlook.Viewport.Rendering.Interfaces; using Gdk; @@ -38,7 +40,7 @@ namespace Everlook.Viewport /// Viewport renderer for the main Everlook UI. This class manages an OpenGL rendering thread, which /// uses rendering built into the different renderable objects. /// - public sealed class ViewportRenderer : IDisposable + public sealed class ViewportRenderer : GraphicsObject, IDisposable { /// /// Logger instance for this class. @@ -51,6 +53,11 @@ public sealed class ViewportRenderer : IDisposable /// private readonly ViewportArea _viewportWidget; + /// + /// Holds the rendering cache. + /// + private readonly RenderCache _renderCache; + /* RenderTarget and related control flow data. */ @@ -114,7 +121,7 @@ Runtime transitional OpenGL data. /// /// The OpenGL ID of the vertex array valid for the current context. /// - private int _vertexArrayID; + private uint _vertexArrayID; /// /// Gets a value indicating whether or not this instance has been initialized and is ready @@ -145,10 +152,12 @@ Everlook caching and static data accessors. /// /// The widget which the viewport should be rendered to. public ViewportRenderer(ViewportArea viewportWidget) + : base(viewportWidget.GetAPI()) { _viewportWidget = viewportWidget; _camera = new ViewportCamera(); _movement = new CameraMovement(_camera); + _renderCache = new RenderCache(this.GL); this.IsInitialized = false; } @@ -162,44 +171,55 @@ public void Initialize() Log.Info($"Initializing {nameof(ViewportRenderer)} and setting up default OpenGL state..."); - var numExtensions = GL.GetInteger(GetPName.NumExtensions); + var numExtensions = this.GL.GetInteger(GetPName.NumExtensions); var extensions = new List(); - for (var i = 0; i < numExtensions; ++i) + for (var i = 0u; i < numExtensions; ++i) { - extensions.Add(GL.GetString(StringName.Extensions, i)); + extensions.Add(this.GL.GetString(StringName.Extensions, i)); } if (extensions.Contains("GL_KHR_debug")) { - //GL.Enable(EnableCap.DebugOutput); - GL.Enable(EnableCap.DebugOutputSynchronous); - GL.DebugMessageCallback(OnGLDebugMessage, IntPtr.Zero); + this.GL.Enable(EnableCap.DebugOutputSynchronous); + + unsafe + { + this.GL.DebugMessageCallback(OnGLDebugMessage, (void*)0); + } } // Generate the vertex array - GL.GenVertexArrays(1, out _vertexArrayID); - GL.BindVertexArray(_vertexArrayID); + unsafe + { + fixed (uint* ptr = &_vertexArrayID) + { + this.GL.GenVertexArrays(1, ptr); + } + } + + this.GL.BindVertexArray(_vertexArrayID); // GL.Disable(EnableCap.AlphaTest); // Make sure we use the depth buffer when drawing - GL.Enable(EnableCap.DepthTest); - GL.DepthFunc(DepthFunction.Lequal); - GL.DepthMask(true); + this.GL.Enable(EnableCap.DepthTest); + this.GL.DepthFunc(DepthFunction.Lequal); + this.GL.DepthMask(true); // Enable backface culling for performance reasons - GL.Enable(EnableCap.CullFace); + this.GL.Enable(EnableCap.CullFace); // Set a simple default blending function - GL.Enable(EnableCap.Blend); - GL.BlendEquation(BlendEquationModeEXT.FuncAdd); - GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); + this.GL.Enable(EnableCap.Blend); + this.GL.BlendEquation(BlendEquationModeEXT.FuncAdd); + this.GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); // Initialize the viewport - var widgetWidth = _viewportWidget.AllocatedWidth; - var widgetHeight = _viewportWidget.AllocatedHeight; - GL.Viewport(0, 0, widgetWidth, widgetHeight); - GL.ClearColor + var widgetWidth = (uint)_viewportWidget.AllocatedWidth; + var widgetHeight = (uint)_viewportWidget.AllocatedHeight; + + this.GL.Viewport(0, 0, widgetWidth, widgetHeight); + this.GL.ClearColor ( (float)_configuration.ViewportBackgroundColour.Red, (float)_configuration.ViewportBackgroundColour.Green, @@ -207,9 +227,9 @@ public void Initialize() (float)_configuration.ViewportBackgroundColour.Alpha ); - GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); + this.GL.Clear((uint)(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit)); - _grid = new BaseGrid(); + _grid = new BaseGrid(this.GL, _renderCache); _grid.Initialize(); this.IsInitialized = true; @@ -221,7 +241,7 @@ public void Initialize() /// The new colour to use. public void SetClearColour(RGBA colour) { - GL.ClearColor + this.GL.ClearColor ( (float)colour.Red, (float)colour.Green, @@ -232,10 +252,10 @@ public void SetClearColour(RGBA colour) private static void OnGLDebugMessage ( - DebugSource source, - DebugType type, + GLEnum source, + GLEnum type, int id, - DebugSeverity severity, + GLEnum severity, int length, IntPtr message, IntPtr userparam @@ -259,10 +279,11 @@ public void RenderFrame() lock (_renderTargetLock) { // Make sure the viewport is accurate for the current widget size on screen - var widgetWidth = _viewportWidget.AllocatedWidth; - var widgetHeight = _viewportWidget.AllocatedHeight; - GL.Viewport(0, 0, widgetWidth, widgetHeight); - GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); + var widgetWidth = (uint)_viewportWidget.AllocatedWidth; + var widgetHeight = (uint)_viewportWidget.AllocatedHeight; + + this.GL.Viewport(0, 0, widgetWidth, widgetHeight); + this.GL.Clear((uint)(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit)); if (!this.HasRenderTarget || this.RenderTarget is null) { @@ -314,11 +335,16 @@ public void RenderFrame() /// private void Calculate2DMovement() { - var mouseX = Mouse.GetCursorState().X; - var mouseY = Mouse.GetCursorState().Y; + var mouse = Display.Default.ListDevices().FirstOrDefault(d => d.HasCursor); + if (mouse is null) + { + return; + } - float deltaMouseX = this.InitialMouseX - mouseX; - float deltaMouseY = this.InitialMouseY - mouseY; + mouse.GetPosition(Screen.Default, out var mouseX, out var mouseY); + + var deltaMouseX = this.InitialMouseX - mouseX; + var deltaMouseY = this.InitialMouseY - mouseY; _movement.Calculate2DMovement(deltaMouseX, deltaMouseY, this.DeltaTime); @@ -332,16 +358,21 @@ private void Calculate2DMovement() /// private void Calculate3DMovement() { - var mouseX = Mouse.GetCursorState().X; - var mouseY = Mouse.GetCursorState().Y; + var mouse = Display.Default.ListDevices().FirstOrDefault(d => d.HasCursor); + if (mouse is null) + { + return; + } - float deltaMouseX = this.InitialMouseX - mouseX; - float deltaMouseY = this.InitialMouseY - mouseY; + mouse.GetPosition(Screen.Default, out var mouseX, out var mouseY); + + var deltaMouseX = this.InitialMouseX - mouseX; + var deltaMouseY = this.InitialMouseY - mouseY; _movement.Calculate3DMovement(deltaMouseX, deltaMouseY, this.DeltaTime); // Return the mouse to its original position - Mouse.SetPosition(this.InitialMouseX, this.InitialMouseY); + mouse.Warp(Screen.Default, (int)this.InitialMouseX, (int)this.InitialMouseY); } /// @@ -374,8 +405,8 @@ public void SetRenderTarget(IRenderable? inRenderable) { return; } - _camera.ViewportWidth = _viewportWidget.AllocatedWidth; - _camera.ViewportHeight = _viewportWidget.AllocatedHeight; + _camera.ViewportWidth = (uint)_viewportWidget.AllocatedWidth; + _camera.ViewportHeight = (uint)_viewportWidget.AllocatedHeight; if (this.RenderTarget is IDefaultCameraPositionProvider cameraPositionProvider) { @@ -396,7 +427,7 @@ private void ThrowIfDisposed() { if (this.IsDisposed) { - throw new ObjectDisposedException(ToString()); + throw new ObjectDisposedException(ToString() ?? nameof(ViewportRenderer)); } } @@ -407,7 +438,13 @@ public void Dispose() this.RenderTarget?.Dispose(); - GL.DeleteVertexArrays(1, ref _vertexArrayID); + unsafe + { + fixed (uint* ptr = &_vertexArrayID) + { + this.GL.DeleteVertexArrays(1u, ptr); + } + } } } } From 6718666dbf7550f684befa3074322ea5f16493b3 Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sat, 4 Apr 2020 20:23:37 +0200 Subject: [PATCH 06/18] Fix some nullability warnings. --- Everlook/Audio/AudioSource.cs | 2 +- Everlook/Configuration/EverlookConfiguration.cs | 8 ++++++++ Everlook/Database/ClientDatabaseProvider.cs | 6 +++++- Everlook/Explorer/FileReference.cs | 9 ++++----- Everlook/Package/PackageGroup.cs | 5 ++--- Everlook/Utility/DataLoadingRoutines.cs | 5 +++++ 6 files changed, 25 insertions(+), 10 deletions(-) diff --git a/Everlook/Audio/AudioSource.cs b/Everlook/Audio/AudioSource.cs index 7ed5759..9557a5f 100644 --- a/Everlook/Audio/AudioSource.cs +++ b/Everlook/Audio/AudioSource.cs @@ -446,7 +446,7 @@ public bool Equals(AudioSource other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (!(obj is AudioSource)) { diff --git a/Everlook/Configuration/EverlookConfiguration.cs b/Everlook/Configuration/EverlookConfiguration.cs index 03055ff..f83ea48 100644 --- a/Everlook/Configuration/EverlookConfiguration.cs +++ b/Everlook/Configuration/EverlookConfiguration.cs @@ -479,6 +479,14 @@ private void SetOption(string section, string keyName, T optionValue, bool st where T : notnull { var value = optionValue.ToString(); + if (value is null) + { + throw new InvalidOperationException + ( + "The value was null when transformed into its string representation." + ); + } + if (storeAsLowerCase) { value = value.ToLowerInvariant(); diff --git a/Everlook/Database/ClientDatabaseProvider.cs b/Everlook/Database/ClientDatabaseProvider.cs index 6906d74..0a0cf25 100644 --- a/Everlook/Database/ClientDatabaseProvider.cs +++ b/Everlook/Database/ClientDatabaseProvider.cs @@ -143,7 +143,11 @@ private void LoadDatabase(DatabaseName databaseName) var databasePath = GetDatabasePackagePath(databaseName); var databaseData = _contentSource.ExtractFile(databasePath); - var database = (IDBC)Activator.CreateInstance(specificDBCType, _version, databaseData); + if (!(Activator.CreateInstance(specificDBCType, _version, databaseData) is IDBC database)) + { + throw new InvalidOperationException("Something caused the database instantiation to fail."); + } + _databases.Add(databaseName, database); } diff --git a/Everlook/Explorer/FileReference.cs b/Everlook/Explorer/FileReference.cs index d3e10cc..5a54abb 100644 --- a/Everlook/Explorer/FileReference.cs +++ b/Everlook/Explorer/FileReference.cs @@ -52,14 +52,14 @@ public class FileReference : GLib.Object, IEquatable /// Gets the name of the package where the file is stored. /// /// The name of the package. - public string PackageName { get; } = string.Empty; + public string PackageName { get; } /// /// Gets the file path of the file inside the package. This string uses the backslash character ('\') as its /// directory separator. /// /// The file path. - public string FilePath { get; } = string.Empty; + public string FilePath { get; } /// /// Gets the directory that the file resides in. @@ -162,10 +162,9 @@ public WarcraftFileType GetReferencedFileType() } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { - var other = obj as FileReference; - return other != null && Equals(other); + return obj is FileReference other && Equals(other); } /// diff --git a/Everlook/Package/PackageGroup.cs b/Everlook/Package/PackageGroup.cs index ae65c73..4c20b21 100644 --- a/Everlook/Package/PackageGroup.cs +++ b/Everlook/Package/PackageGroup.cs @@ -407,10 +407,9 @@ public MPQFileInfo GetFileInfo(string filePath) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { - var other = obj as PackageGroup; - if (other != null) + if (obj is PackageGroup other) { return this.GroupName.Equals(other.GroupName) && _packages.Equals(other._packages); diff --git a/Everlook/Utility/DataLoadingRoutines.cs b/Everlook/Utility/DataLoadingRoutines.cs index 3fdc8c8..b10a767 100644 --- a/Everlook/Utility/DataLoadingRoutines.cs +++ b/Everlook/Utility/DataLoadingRoutines.cs @@ -239,6 +239,11 @@ public static Bitmap LoadBitmapImage(FileReference fileReference) try { var fileData = fileReference.Extract(); + if (fileData is null) + { + throw new FileNotFoundException(); + } + using (var ms = new MemoryStream(fileData)) { image = new Bitmap(ms); From a757a96439664be63e951cc01da2d70d6b7d4eaa Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sat, 4 Apr 2020 21:58:06 +0200 Subject: [PATCH 07/18] Transition to using a hosted application model. --- .idea/.idea.Everlook/.idea/contentModel.xml | 15 +- Everlook.sln | 12 +- Everlook.sln.DotSettings | 1 + Everlook/Audio/AudioSource.cs | 52 ++-- Everlook/Database/TypeTranslatorHelpers.cs | 8 +- Everlook/Everlook.csproj | 24 +- Everlook/Explorer/FileReference.cs | 33 ++- Everlook/Explorer/GamePage.cs | 12 +- Everlook/OpenTK.dll.config | 39 --- Everlook/Package/PackageInteractionHandler.cs | 14 +- Everlook/Program.cs | 143 ++++------ Everlook/Startup.cs | 64 +++++ Everlook/UI/EverlookDirectoryExportDialog.cs | 10 +- Everlook/UI/EverlookImageExportDialog.cs | 10 +- Everlook/UI/EverlookPreferences.cs | 10 +- Everlook/UI/MainWindow.cs | 251 ++++++++++++------ Everlook/Utility/DataLoadingDelegates.cs | 12 +- Everlook/Utility/DataLoadingRoutines.cs | 95 +++++-- Everlook/Utility/DirectoryHelpers.cs | 8 +- Everlook/Viewport/Camera/CameraMovement.cs | 49 +++- Everlook/Viewport/ViewportRenderer.cs | 92 ++++++- Everlook/app.config | 33 --- Everlook/config/appsettings.json | 9 + Everlook/log4net.config | 25 ++ 24 files changed, 644 insertions(+), 377 deletions(-) delete mode 100644 Everlook/OpenTK.dll.config create mode 100644 Everlook/Startup.cs delete mode 100644 Everlook/app.config create mode 100644 Everlook/config/appsettings.json create mode 100644 Everlook/log4net.config diff --git a/.idea/.idea.Everlook/.idea/contentModel.xml b/.idea/.idea.Everlook/.idea/contentModel.xml index 1a3117d..26062e2 100644 --- a/.idea/.idea.Everlook/.idea/contentModel.xml +++ b/.idea/.idea.Everlook/.idea/contentModel.xml @@ -216,7 +216,6 @@ - @@ -225,6 +224,7 @@ + @@ -321,8 +321,10 @@ - + + + @@ -330,12 +332,11 @@ + - - - - - + + + diff --git a/Everlook.sln b/Everlook.sln index c610d0c..f8ccdbb 100644 --- a/Everlook.sln +++ b/Everlook.sln @@ -5,13 +5,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Everlook", "Everlook\Everlo EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x86 = Debug|x86 - Release|x86 = Release|x86 + Release|Any CPU = Release|Any CPU + Debug|Any CPU = Debug|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {64BD763C-024D-477A-B05C-57152FD612DF}.Debug|x86.ActiveCfg = Debug|x86 - {64BD763C-024D-477A-B05C-57152FD612DF}.Debug|x86.Build.0 = Debug|x86 - {64BD763C-024D-477A-B05C-57152FD612DF}.Release|x86.ActiveCfg = Release|x86 - {64BD763C-024D-477A-B05C-57152FD612DF}.Release|x86.Build.0 = Release|x86 + {64BD763C-024D-477A-B05C-57152FD612DF}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {64BD763C-024D-477A-B05C-57152FD612DF}.Release|Any CPU.Build.0 = Debug|Any CPU + {64BD763C-024D-477A-B05C-57152FD612DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {64BD763C-024D-477A-B05C-57152FD612DF}.Debug|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection EndGlobal diff --git a/Everlook.sln.DotSettings b/Everlook.sln.DotSettings index 22d1aeb..cadf93f 100644 --- a/Everlook.sln.DotSettings +++ b/Everlook.sln.DotSettings @@ -84,6 +84,7 @@ True True True + True True True True diff --git a/Everlook/Audio/AudioSource.cs b/Everlook/Audio/AudioSource.cs index 9557a5f..e55ee31 100644 --- a/Everlook/Audio/AudioSource.cs +++ b/Everlook/Audio/AudioSource.cs @@ -37,7 +37,7 @@ namespace Everlook.Audio /// Represents a single audio source in 3D space. /// [PublicAPI] - public sealed class AudioSource : IDisposable, IEquatable + public sealed class AudioSource : IDisposable { private AL _al = AL.GetApi(); private IAudioAsset? _audioAsset; @@ -86,8 +86,13 @@ public bool Looping { get { - _al.GetSourceProperty(_soundSourceID, SourceBoolean.Looping, out var temp); - return temp > 0; + // TODO: Restore + /* + * al.GetSourceProperty(_soundSourceID, SourceBoolean.Looping, out var temp); + * return temp > 0; + */ + + return false; } set => _al.SetSourceProperty(_soundSourceID, SourceBoolean.Looping, value ? 1 : 0); } @@ -138,8 +143,13 @@ public bool RelativePositioning { get { - _al.GetSourceProperty(_soundSourceID, SourceBoolean.SourceRelative, out var value); - return value > 0; + // TODO: Restore + /* + * _al.GetSourceProperty(_soundSourceID, SourceBoolean.SourceRelative, out var value); + * return value > 0; + */ + + return false; } set => _al.SetSourceProperty(_soundSourceID, SourceBoolean.SourceRelative, value ? 1 : 0); } @@ -425,37 +435,5 @@ public void Dispose() Stop(); ClearAudio(); } - - /// - public override int GetHashCode() - { - unchecked - { - long hash = 17; - hash *= 23 + _soundBufferID; - hash *= 23 + _soundSourceID; - - return (int)hash; - } - } - - /// - public bool Equals(AudioSource other) - { - return Equals((object)other); - } - - /// - public override bool Equals(object? obj) - { - if (!(obj is AudioSource)) - { - return false; - } - - var other = (AudioSource)obj; - return other._soundSourceID == _soundSourceID && - other._soundBufferID == _soundBufferID; - } } } diff --git a/Everlook/Database/TypeTranslatorHelpers.cs b/Everlook/Database/TypeTranslatorHelpers.cs index c1edc03..042b81b 100644 --- a/Everlook/Database/TypeTranslatorHelpers.cs +++ b/Everlook/Database/TypeTranslatorHelpers.cs @@ -37,7 +37,13 @@ public static class TypeTranslatorHelpers /// The type mapping to the database name. public static Type GetRecordTypeFromDatabaseName(DatabaseName databaseName) { - return Type.GetType($"Warcraft.DBC.Definitions.{databaseName}Record, libwarcraft"); + var type = Type.GetType($"Warcraft.DBC.Definitions.{databaseName}Record, libwarcraft"); + if (type is null) + { + throw new InvalidOperationException(); + } + + return type; } /// diff --git a/Everlook/Everlook.csproj b/Everlook/Everlook.csproj index d0b7523..2fa5312 100644 --- a/Everlook/Everlook.csproj +++ b/Everlook/Everlook.csproj @@ -6,8 +6,6 @@ false true $(DefineConstants);GTK3; - true - ..\stylecop.ruleset true @@ -18,6 +16,14 @@ 2.0.0 An open-source World of Warcraft model viewer. + + + + + PreserveNewest + + + false @@ -43,9 +49,6 @@ - - PreserveNewest - PreserveNewest @@ -60,19 +63,16 @@ + + + - - - - - - @@ -82,7 +82,9 @@ + + diff --git a/Everlook/Explorer/FileReference.cs b/Everlook/Explorer/FileReference.cs index 5a54abb..8fdbee9 100644 --- a/Everlook/Explorer/FileReference.cs +++ b/Everlook/Explorer/FileReference.cs @@ -64,7 +64,19 @@ public class FileReference : GLib.Object, IEquatable /// /// Gets the directory that the file resides in. /// - public string FileDirectory => Path.GetDirectoryName(this.FilePath.Replace('\\', Path.DirectorySeparatorChar)); + public string FileDirectory + { + get + { + var directory = Path.GetDirectoryName(this.FilePath.Replace('\\', Path.DirectorySeparatorChar)); + if (directory is null) + { + throw new InvalidOperationException(); + } + + return directory; + } + } /// /// Gets the file info of this reference. @@ -115,9 +127,22 @@ public MPQFileInfo? ReferenceInfo /// /// Gets the name of the file or directory. /// - public string Filename => this.IsDirectory ? - Path.GetDirectoryName(this.FilePath.Replace('\\', Path.DirectorySeparatorChar)) : - Path.GetFileName(this.FilePath.Replace('\\', Path.DirectorySeparatorChar)); + public string Filename + { + get + { + var filename = this.IsDirectory + ? Path.GetDirectoryName(this.FilePath.Replace('\\', Path.DirectorySeparatorChar)) + : Path.GetFileName(this.FilePath.Replace('\\', Path.DirectorySeparatorChar)); + + if (filename is null) + { + throw new InvalidOperationException(); + } + + return filename; + } + } /// /// Initializes a new instance of the class. diff --git a/Everlook/Explorer/GamePage.cs b/Everlook/Explorer/GamePage.cs index d38c974..1aa5d87 100644 --- a/Everlook/Explorer/GamePage.cs +++ b/Everlook/Explorer/GamePage.cs @@ -405,7 +405,7 @@ private void RenderNodeName(TreeViewColumn column, CellRenderer cell, ITreeModel /// /// The sending object. /// Arguments describing the row that was activated. - private void OnQueueForExportRequested(object sender, EventArgs eventArgs) + private void OnQueueForExportRequested(object? sender, EventArgs eventArgs) { var fileReference = GetSelectedReference(); if (fileReference == null) @@ -421,7 +421,7 @@ private void OnQueueForExportRequested(object sender, EventArgs eventArgs) /// /// The sending object. /// Arguments describing the row that was activated. - private void OnExportItemRequested(object sender, EventArgs eventArgs) + private void OnExportItemRequested(object? sender, EventArgs eventArgs) { var fileReference = GetSelectedReference(); if (fileReference == null) @@ -439,7 +439,7 @@ private void OnExportItemRequested(object sender, EventArgs eventArgs) /// /// The sending object. /// Arguments describing the row that was activated. - private void OnOpenItem(object sender, EventArgs eventArgs) + private void OnOpenItem(object? sender, EventArgs eventArgs) { var fileReference = GetSelectedReference(); if (fileReference == null) @@ -465,7 +465,7 @@ private void OnOpenItem(object sender, EventArgs eventArgs) /// /// The sending object. /// Arguments describing the row that was activated. - private void OnCopyPath(object sender, EventArgs eventArgs) + private void OnCopyPath(object? sender, EventArgs eventArgs) { var fileReference = GetSelectedReference(); if (fileReference == null) @@ -483,7 +483,7 @@ private void OnCopyPath(object sender, EventArgs eventArgs) /// /// The sending object. /// Arguments describing the row that was activated. - private void OnSaveItem(object sender, EventArgs eventArgs) + private void OnSaveItem(object? sender, EventArgs eventArgs) { var fileReference = GetSelectedReference(); if (fileReference == null) @@ -565,7 +565,7 @@ private void OnButtonPressed(object o, ButtonPressEventArgs args) /// /// The sending object. /// Arguments describing the row that was activated. - private void OnSelectionChanged(object sender, EventArgs eventArgs) + private void OnSelectionChanged(object? sender, EventArgs eventArgs) { var fileReference = GetSelectedReference(); if (fileReference == null) diff --git a/Everlook/OpenTK.dll.config b/Everlook/OpenTK.dll.config deleted file mode 100644 index 873737e..0000000 --- a/Everlook/OpenTK.dll.config +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Everlook/Package/PackageInteractionHandler.cs b/Everlook/Package/PackageInteractionHandler.cs index 3db4bdb..7e09886 100644 --- a/Everlook/Package/PackageInteractionHandler.cs +++ b/Everlook/Package/PackageInteractionHandler.cs @@ -58,7 +58,19 @@ public string? PackagePath /// Gets the name of the package. /// /// The name of the package. - public string PackageName => Path.GetFileNameWithoutExtension(this.PackagePath); + public string PackageName + { + get + { + var filename = Path.GetFileNameWithoutExtension(this.PackagePath); + if (filename is null) + { + throw new InvalidOperationException(); + } + + return filename; + } + } private MPQ? _package; diff --git a/Everlook/Program.cs b/Everlook/Program.cs index a432bdf..7eec282 100644 --- a/Everlook/Program.cs +++ b/Everlook/Program.cs @@ -21,9 +21,10 @@ // using System; -using System.Globalization; using System.IO; +using System.Reflection; using System.Runtime.InteropServices; +using System.Xml; using Everlook.Explorer; using Everlook.Silk; using Everlook.UI; @@ -31,130 +32,88 @@ using FileTree.Tree.Serialized; using GLib; using log4net; +using log4net.Config; +using log4net.Repository.Hierarchy; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Silk.NET.Core.Loader; using Silk.NET.Core.Platform; + using Application = Gtk.Application; +using Task = System.Threading.Tasks.Task; namespace Everlook { /// /// The main entry class, containing the entry point and some top-level diagnostics. /// - internal static class Program + internal class Program { - /// - /// Logger instance for this class. - /// - private static readonly ILog Log = LogManager.GetLogger(typeof(Program)); - /// /// The entry point. /// - public static void Main() + /// The command-line arguments. + /// A representing the asynchronous operation. + [STAThread] + public static async Task Main(string[] args) { - // Bind any unhandled exceptions in the main thread so that they are logged. - AppDomain.CurrentDomain.UnhandledException += OnUnhandledException; - - // Set correct working directory for compatibility with double-clicking - Directory.SetCurrentDirectory(DirectoryHelpers.GetLocalDir()); - + IconManager.LoadEmbeddedIcons(); + Application.Init(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Environment.SetEnvironmentVariable("GSETTINGS_SCHEMA_DIR", "share\\glib-2.0\\schemas\\"); } - log4net.Config.XmlConfigurator.Configure(); - - Log.Info("----------------"); - Log.Info("Initializing Everlook..."); + const string configurationName = "Everlook.log4net.config"; + var logConfig = new XmlDocument(); + await using (var configStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(configurationName)) + { + if (configStream is null) + { + throw new InvalidOperationException("The log4net configuration stream could not be found."); + } - Log.Info("Initializing Silk..."); - SilkManager.Register(new GDKGLSymbolLoader()); + logConfig.Load(configStream); + } - Log.Info("Initializing GTK..."); + var repo = LogManager.CreateRepository(Assembly.GetEntryAssembly(), typeof(Hierarchy)); + XmlConfigurator.Configure(repo, logConfig["log4net"]); - // Bind any unhandled exceptions in the GTK UI so that they are logged. - ExceptionManager.UnhandledException += OnGLibUnhandledException; + SilkManager.Register(new GDKGLSymbolLoader()); - Log.Info("Registering treeview types with the native backend..."); var nodeType = (GType)typeof(SerializedNode); GType.Register(nodeType, typeof(SerializedNode)); var referenceType = (GType)typeof(FileReference); GType.Register(referenceType, typeof(FileReference)); - // GTK - IconManager.LoadEmbeddedIcons(); - Application.Init(); - var win = MainWindow.Create(); - win.Show(); - Application.Run(); - } + var host = CreateHostBuilder(args).Build(); - /// - /// Passes any unhandled exceptions from the GTK UI to the generic handler. - /// - /// The event object containing the information about the exception. - private static void OnGLibUnhandledException(UnhandledExceptionArgs args) - { - OnUnhandledException(null, args); - } + var app = host.Services.GetRequiredService(); + app.Start(); - /// - /// Event handler for all unhandled exceptions that may be encountered during runtime. While there should never - /// be any unhandled exceptions in an ideal program, unexpected issues can and will arise. This handler logs - /// the exception and all relevant information to a logfile and prints it to the console for debugging purposes. - /// - /// The sending object. - /// - /// The event object containing the information about the exception. - /// - private static void OnUnhandledException(object? sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs) - { - // Force english exception output - System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; - System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture; - - Log.Fatal("----------------"); - Log.Fatal("FATAL UNHANDLED EXCEPTION!"); - Log.Fatal("Something has gone terribly, terribly wrong during runtime."); - Log.Fatal("The following is what information could be gathered by the program before crashing."); - Log.Fatal("Please report this to or via GitHub. Include the full log and a " + - "description of what you were doing when it happened."); + Application.Run(); + } - var unhandledException = (Exception)unhandledExceptionEventArgs.ExceptionObject; - switch (unhandledException) + private static IHostBuilder CreateHostBuilder(string[] args) => new HostBuilder() + .ConfigureAppConfiguration((hostingContext, config) => { - case null: - { - return; - } - case DllNotFoundException _: - { - Log.Fatal - ( - "This exception is typical of instances where the GTK runtime has not been properly copied " + - "to the working directory or is not available on your system.\n" + - "If you're on Windows, make sure that the bundled GTK libraries are present.\n" + - "If you're on macOS, try installing GTK through Homebrew.\n" + - "If you're on Linux, check with your package maintainer that all dependencies are properly " + - "listed." - ); - break; - } - } - - Log.Fatal($"Exception type: {unhandledException!.GetType().FullName}"); - Log.Fatal($"Exception Message: {unhandledException.Message}"); - Log.Fatal($"Exception Stacktrace: {unhandledException.StackTrace}"); - - if (unhandledException.InnerException == null) + config.SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "config")); + config.AddJsonFile("appsettings.json"); + }) + .ConfigureServices((hostingContext, services) => { - return; - } + services.AddSingleton(new Application("net.Everlook.Everlook", ApplicationFlags.None)); - Log.Fatal($"Inner exception type: {unhandledException.InnerException.GetType().FullName}"); - Log.Fatal($"Inner exception Message: {unhandledException.InnerException.Message}"); - Log.Fatal($"Inner exception Stacktrace: {unhandledException.InnerException.StackTrace}"); - } + services.AddTransient(MainWindow.Create); + services.AddSingleton(); + }) + .ConfigureLogging(l => + { + l.ClearProviders(); + l.AddLog4Net(); + }); } } diff --git a/Everlook/Startup.cs b/Everlook/Startup.cs new file mode 100644 index 0000000..0d83acf --- /dev/null +++ b/Everlook/Startup.cs @@ -0,0 +1,64 @@ +// +// Startup.cs +// +// Author: +// Jarl Gullberg +// +// Copyright (c) 2017 Jarl Gullberg +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +using Everlook.UI; +using Gtk; + +namespace Everlook +{ + /// + /// Represents startup procedures for the application. + /// + public class Startup + { + private readonly Application _app; + private readonly MainWindow _mainWindow; + + /// + /// Initializes a new instance of the class. + /// + /// The application information. + /// The main application window. + public Startup(Application app, MainWindow mainWindow) + { + _app = app; + _mainWindow = mainWindow; + } + + /// + /// Starts the application. + /// + public void Start() + { + _app.Register(GLib.Cancellable.Current); + _app.AddWindow(_mainWindow); + + _mainWindow.Show(); + _mainWindow.DeleteEvent += DeletedEvent; + } + + private void DeletedEvent(object o, DeleteEventArgs args) + { + Application.Quit(); + } + } +} diff --git a/Everlook/UI/EverlookDirectoryExportDialog.cs b/Everlook/UI/EverlookDirectoryExportDialog.cs index 373df6f..f30e575 100644 --- a/Everlook/UI/EverlookDirectoryExportDialog.cs +++ b/Everlook/UI/EverlookDirectoryExportDialog.cs @@ -155,7 +155,7 @@ public void RunExport() /// Sender. /// E. [GLib.ConnectBefore] - private void OnItemListingButtonPressed(object sender, ButtonPressEventArgs e) + private void OnItemListingButtonPressed(object? sender, ButtonPressEventArgs e) { if (e.Event.Type == EventType.ButtonPress && e.Event.Button == 3) { @@ -171,7 +171,7 @@ private void OnItemListingButtonPressed(object sender, ButtonPressEventArgs e) /// /// Sender. /// E. - private void OnSelectAllItemActivated(object sender, EventArgs e) + private void OnSelectAllItemActivated(object? sender, EventArgs e) { _itemExportListStore.Foreach ( @@ -188,7 +188,7 @@ private void OnSelectAllItemActivated(object sender, EventArgs e) /// /// Sender. /// E. - private void OnSelectNoneItemActivated(object sender, EventArgs e) + private void OnSelectNoneItemActivated(object? sender, EventArgs e) { _itemExportListStore.Foreach ( @@ -205,7 +205,7 @@ private void OnSelectNoneItemActivated(object sender, EventArgs e) /// /// Sender. /// E. - private void OnExportItemToggleClicked(object sender, ToggledArgs e) + private void OnExportItemToggleClicked(object? sender, ToggledArgs e) { TreeIter iter; _itemExportListStore.GetIterFromString(out iter, e.Path); @@ -220,7 +220,7 @@ private void OnExportItemToggleClicked(object sender, ToggledArgs e) /// /// Sender. /// E. - private void OnOkButtonClicked(object sender, EventArgs e) + private void OnOkButtonClicked(object? sender, EventArgs e) { RunExport(); } diff --git a/Everlook/UI/EverlookImageExportDialog.cs b/Everlook/UI/EverlookImageExportDialog.cs index 9b97e0a..7574beb 100644 --- a/Everlook/UI/EverlookImageExportDialog.cs +++ b/Everlook/UI/EverlookImageExportDialog.cs @@ -234,7 +234,7 @@ private static string GetFileExtensionFromImageFormat(ImageFormat format) /// Sender. /// E. [GLib.ConnectBefore] - protected void OnMipListingButtonPressed(object sender, ButtonPressEventArgs e) + protected void OnMipListingButtonPressed(object? sender, ButtonPressEventArgs e) { if (e.Event.Type == EventType.ButtonPress && e.Event.Button == 3) { @@ -250,7 +250,7 @@ protected void OnMipListingButtonPressed(object sender, ButtonPressEventArgs e) /// /// Sender. /// E. - protected void OnSelectAllItemActivated(object sender, EventArgs e) + protected void OnSelectAllItemActivated(object? sender, EventArgs e) { _mipLevelListStore.Foreach ( @@ -267,7 +267,7 @@ protected void OnSelectAllItemActivated(object sender, EventArgs e) /// /// Sender. /// E. - protected void OnSelectNoneItemActivated(object sender, EventArgs e) + protected void OnSelectNoneItemActivated(object? sender, EventArgs e) { _mipLevelListStore.Foreach ( @@ -284,7 +284,7 @@ protected void OnSelectNoneItemActivated(object sender, EventArgs e) /// /// Sender. /// E. - protected void OnExportMipToggleClicked(object sender, ToggledArgs e) + protected void OnExportMipToggleClicked(object? sender, ToggledArgs e) { TreeIter iter; _mipLevelListStore.GetIterFromString(out iter, e.Path); @@ -299,7 +299,7 @@ protected void OnExportMipToggleClicked(object sender, ToggledArgs e) /// /// Sender. /// E. - protected void OnOkButtonClicked(object sender, EventArgs e) + protected void OnOkButtonClicked(object? sender, EventArgs e) { RunExport(); } diff --git a/Everlook/UI/EverlookPreferences.cs b/Everlook/UI/EverlookPreferences.cs index 27a723a..ca621cc 100644 --- a/Everlook/UI/EverlookPreferences.cs +++ b/Everlook/UI/EverlookPreferences.cs @@ -99,7 +99,7 @@ private EverlookPreferences(Builder builder, IntPtr handle) /// The sending object. /// The event arguments. [ConnectBefore] - private void OnShowUnknownFilesToggled(object sender, EventArgs e) + private void OnShowUnknownFilesToggled(object? sender, EventArgs e) { // Refilter if the option has changed if (_showUnknownFilesCheckButton.Active != _config.ShowUnknownFilesWhenFiltering) @@ -117,7 +117,7 @@ private void OnShowUnknownFilesToggled(object sender, EventArgs e) /// The sending object. /// The event arguments. [ConnectBefore] - private void OnAllowStatsToggled(object sender, EventArgs e) + private void OnAllowStatsToggled(object? sender, EventArgs e) { var suboptionSensitivity = _allowStatsCheckButton.Active; @@ -165,7 +165,7 @@ private void OnKeyPressedGamePathTreeView(object o, KeyPressEventArgs args) /// /// The sending object. /// The event arguments. - private void OnAliasEntryChanged(object sender, EventArgs eventArgs) + private void OnAliasEntryChanged(object? sender, EventArgs eventArgs) { _newGamePathDialog.SetResponseSensitive(ResponseType.Ok, !string.IsNullOrEmpty(_aliasEntry.Text)); } @@ -175,7 +175,7 @@ private void OnAliasEntryChanged(object sender, EventArgs eventArgs) /// /// The sending object. /// The event arguments. - private void OnAddPathButtonClicked(object sender, EventArgs eventArgs) + private void OnAddPathButtonClicked(object? sender, EventArgs eventArgs) { var defaultLocation = new Uri(Environment.GetFolderPath(Environment.SpecialFolder.Desktop)); _pathChooser.SetCurrentFolderUri(defaultLocation.ToString()); @@ -217,7 +217,7 @@ private void OnAddPathButtonClicked(object sender, EventArgs eventArgs) /// /// Sender. /// E. - private void OnRemovePathButtonClicked(object sender, EventArgs e) + private void OnRemovePathButtonClicked(object? sender, EventArgs e) { TreeIter selectedIter; _gamePathSelectionTreeView.Selection.GetSelected(out selectedIter); diff --git a/Everlook/UI/MainWindow.cs b/Everlook/UI/MainWindow.cs index db46f9c..fb092b8 100644 --- a/Everlook/UI/MainWindow.cs +++ b/Everlook/UI/MainWindow.cs @@ -22,11 +22,11 @@ using System; using System.Collections.Generic; +using System.ComponentModel.Design; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; -using System.Threading.Tasks; using Everlook.Audio; using Everlook.Configuration; using Everlook.Explorer; @@ -42,12 +42,14 @@ using Gdk; using GLib; using Gtk; -using log4net; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Silk.NET.OpenGL; using Warcraft.Core; using static Everlook.Utility.DataLoadingDelegates; -using Application = Gtk.Application; using EventArgs = System.EventArgs; using IOPath = System.IO.Path; using Task = System.Threading.Tasks.Task; @@ -62,9 +64,9 @@ namespace Everlook.UI public sealed partial class MainWindow : Gtk.Window { /// - /// Logger instance for this class. + /// Holds the logging instance for this class. /// - private static readonly ILog Log = LogManager.GetLogger(typeof(MainWindow)); + private readonly ILogger _log; /// /// Static reference to the configuration handler. @@ -74,12 +76,12 @@ public sealed partial class MainWindow : Gtk.Window /// /// Background viewport renderer. Handles all rendering in the viewport. /// - private readonly ViewportRenderer _renderingEngine; + private ViewportRenderer? _renderingEngine; /// - /// Task scheduler for the UI thread. This allows task-based code to have very simple UI callbacks. + /// Holds the available services. /// - private readonly TaskScheduler _uiTaskScheduler; + private IServiceProvider? _services; /// /// Whether or not the program is shutting down. This is used to remove callbacks and events. @@ -99,13 +101,17 @@ public sealed partial class MainWindow : Gtk.Window /// /// Creates an instance of the class, loading the glade XML UI as needed. /// + /// The application services. /// An initialized instance of the MainWindow class. - public static MainWindow Create() + public static MainWindow Create(IServiceProvider provider) { - using (var builder = new Builder(null, "Everlook.interfaces.Everlook.glade", null)) - { - return new MainWindow(builder, builder.GetObject("_mainWindow").Handle); - } + using var builder = new Builder(null, "Everlook.interfaces.Everlook.glade", null); + return ActivatorUtilities.CreateInstance + ( + provider, + builder, + builder.GetObject("_mainWindow").Handle + ); } /// @@ -113,15 +119,25 @@ public static MainWindow Create() /// /// Builder. /// Handle. - private MainWindow(Builder builder, IntPtr handle) + /// The application services. + /// The logging instance. + public MainWindow + ( + Builder builder, + IntPtr handle, + IServiceProvider services, + ILogger log + ) : base(handle) { + _log = log; + builder.Autoconnect(this); + this.DeleteEvent += OnDeleteEvent; this.Shown += OnMainWindowShown; this.WindowStateEvent += OnWindowStateChanged; - _uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); _fileLoadingCancellationSource = new CancellationTokenSource(); _viewportWidget = new ViewportArea(3, 3) @@ -140,6 +156,17 @@ private MainWindow(Builder builder, IntPtr handle) _viewportWidget.Initialized += (sender, args) => { + var wrappedServices = new ServiceContainer(services); + wrappedServices.AddService(typeof(GL), _viewportWidget.GetAPI()); + wrappedServices.AddService + ( + typeof(RenderCache), + new RenderCache(wrappedServices.GetRequiredService()) + ); + + _services = wrappedServices; + + _renderingEngine = ActivatorUtilities.CreateInstance(_services, _viewportWidget); _renderingEngine.Initialize(); }; @@ -150,6 +177,11 @@ private MainWindow(Builder builder, IntPtr handle) return; } + if (_renderingEngine is null) + { + return; + } + if (!_renderingEngine.IsInitialized) { return; @@ -165,7 +197,6 @@ private MainWindow(Builder builder, IntPtr handle) _viewportWidget.EnterNotifyEvent += OnViewportMouseEnter; _viewportWidget.LeaveNotifyEvent += OnViewportMouseLeave; - _renderingEngine = new ViewportRenderer(_viewportWidget); _viewportAlignment.Add(_viewportWidget); _viewportAlignment.ShowAll(); @@ -225,6 +256,11 @@ private void BindModelControlEvents() { _renderBoundsCheckButton.Toggled += (sender, args) => { + if (_renderingEngine is null) + { + return; + } + switch (_renderingEngine.RenderTarget) { case RenderableWorldModel wmo: @@ -242,6 +278,11 @@ private void BindModelControlEvents() _renderWireframeCheckButton.Toggled += (sender, args) => { + if (_renderingEngine is null) + { + return; + } + switch (_renderingEngine.RenderTarget) { case RenderableWorldModel wmo: @@ -259,6 +300,11 @@ private void BindModelControlEvents() _renderDoodadsCheckButton.Toggled += (sender, args) => { + if (_renderingEngine is null) + { + return; + } + switch (_renderingEngine.RenderTarget) { case RenderableWorldModel wmo: @@ -273,6 +319,11 @@ private void BindModelControlEvents() _modelVariationComboBox.Changed += (sender, args) => { + if (_renderingEngine is null) + { + return; + } + switch (_renderingEngine.RenderTarget) { case RenderableWorldModel wmo: @@ -307,8 +358,7 @@ private void BindImageControlEvents() { _renderAlphaCheckButton.Toggled += (sender, args) => { - var image = _renderingEngine.RenderTarget as RenderableImage; - if (image == null) + if (!(_renderingEngine?.RenderTarget is RenderableImage image)) { return; } @@ -318,8 +368,7 @@ private void BindImageControlEvents() _renderRedCheckButton.Toggled += (sender, args) => { - var image = _renderingEngine.RenderTarget as RenderableImage; - if (image == null) + if (!(_renderingEngine?.RenderTarget is RenderableImage image)) { return; } @@ -329,8 +378,7 @@ private void BindImageControlEvents() _renderGreenCheckButton.Toggled += (sender, args) => { - var image = _renderingEngine.RenderTarget as RenderableImage; - if (image == null) + if (!(_renderingEngine?.RenderTarget is RenderableImage image)) { return; } @@ -340,8 +388,7 @@ private void BindImageControlEvents() _renderBlueCheckButton.Toggled += (sender, args) => { - var image = _renderingEngine.RenderTarget as RenderableImage; - if (image == null) + if (!(_renderingEngine?.RenderTarget is RenderableImage image)) { return; } @@ -356,7 +403,7 @@ private void BindImageControlEvents() /// The sending object. /// The event arguments. [ConnectBefore] - private void OnRunExportQueueButtonClicked(object sender, EventArgs e) + private void OnRunExportQueueButtonClicked(object? sender, EventArgs e) { throw new NotImplementedException(); } @@ -367,7 +414,7 @@ private void OnRunExportQueueButtonClicked(object sender, EventArgs e) /// The sending object. /// The event arguments. [ConnectBefore] - private void OnClearExportQueueButtonClicked(object sender, EventArgs e) + private void OnClearExportQueueButtonClicked(object? sender, EventArgs e) { _exportQueueListStore.Clear(); } @@ -378,7 +425,7 @@ private void OnClearExportQueueButtonClicked(object sender, EventArgs e) /// The sending object. /// The event arguments. [ConnectBefore] - private void OnCancelCurrentActionClicked(object sender, EventArgs e) + private void OnCancelCurrentActionClicked(object? sender, EventArgs e) { _fileLoadingCancellationSource.Cancel(); } @@ -420,6 +467,11 @@ private void OnViewportMouseLeave(object o, LeaveNotifyEventArgs args) [ConnectBefore] private void OnViewportMouseEnter(object o, EnterNotifyEventArgs args) { + if (_renderingEngine is null) + { + return; + } + if (_renderingEngine.RenderTarget?.Projection == ProjectionType.Orthographic) { this.Window.Cursor = new Cursor(CursorType.Hand2); @@ -431,7 +483,7 @@ private void OnViewportMouseEnter(object o, EnterNotifyEventArgs args) /// /// The sending object. /// The event arguments. - private async void OnFilterChanged(object sender, EventArgs e) + private async void OnFilterChanged(object? sender, EventArgs e) { await RefilterTrees(); } @@ -492,10 +544,9 @@ private async Task RefilterTrees() /// /// The sending object. /// The event arguments. - private async void OnMainWindowShown(object sender, EventArgs eventArgs) + private async void OnMainWindowShown(object? sender, EventArgs eventArgs) { await LoadGames(); - //OnDeleteEvent(sender, null); // DEBUG } /// @@ -522,7 +573,7 @@ private async Task LoadGames() if (!Directory.Exists(gameTarget.Path)) { - Log.Warn($"Could not find game folder for {gameTarget.Alias}. Has the directory moved?"); + _log.LogWarning($"Could not find game folder for {gameTarget.Alias}. Has the directory moved?"); continue; } @@ -545,7 +596,7 @@ private async Task LoadGames() } catch (OperationCanceledException) { - Log.Info("Cancelled game loading operation."); + _log.LogInformation("Cancelled game loading operation."); break; } } @@ -554,7 +605,7 @@ private async Task LoadGames() dialog.Destroy(); sw.Stop(); - Log.Debug($"Game loading took {sw.Elapsed.TotalMilliseconds}ms ({sw.Elapsed.TotalSeconds}s)"); + _log.LogDebug($"Game loading took {sw.Elapsed.TotalMilliseconds}ms ({sw.Elapsed.TotalSeconds}s)"); } private void AddGamePage(string alias, WarcraftVersion version, PackageGroup group, SerializedTree nodeTree) @@ -608,8 +659,7 @@ private void EnableControlPage(ControlPage pageToEnable) { case ControlPage.Image: { - var image = _renderingEngine.RenderTarget as RenderableImage; - if (image == null) + if (!(_renderingEngine?.RenderTarget is RenderableImage image)) { return; } @@ -635,44 +685,53 @@ private void EnableControlPage(ControlPage pageToEnable) _modelVariationComboBox.Sensitive = true; - if (_renderingEngine.RenderTarget is RenderableWorldModel wmo) + if (_renderingEngine is null) { - wmo.ShouldRenderBounds = _renderBoundsCheckButton.Active; - wmo.ShouldRenderWireframe = _renderWireframeCheckButton.Active; - wmo.ShouldRenderDoodads = _renderDoodadsCheckButton.Active; - - var doodadSetNames = wmo.GetDoodadSetNames().ToList(); - _modelVariationListStore.Clear(); - for (var i = 0; i < doodadSetNames.Count; ++i) - { - _modelVariationListStore.AppendValues(doodadSetNames[i], i); - } - - _modelVariationComboBox.Active = 0; - _modelVariationComboBox.Sensitive = _renderDoodadsCheckButton.Active && - doodadSetNames.Count > 1; - _renderDoodadsCheckButton.Sensitive = true; + return; } - if (_renderingEngine.RenderTarget is RenderableGameModel mdx) + switch (_renderingEngine.RenderTarget) { - mdx.ShouldRenderBounds = _renderBoundsCheckButton.Active; - mdx.ShouldRenderWireframe = _renderWireframeCheckButton.Active; - - var skinVariations = mdx.GetSkinVariations().ToList(); - _modelVariationListStore.Clear(); - foreach (var variation in skinVariations) + case RenderableWorldModel wmo: { - var firstTextureName = variation.TextureVariation1.Value; - if (!string.IsNullOrEmpty(firstTextureName)) + wmo.ShouldRenderBounds = _renderBoundsCheckButton.Active; + wmo.ShouldRenderWireframe = _renderWireframeCheckButton.Active; + wmo.ShouldRenderDoodads = _renderDoodadsCheckButton.Active; + + var doodadSetNames = wmo.GetDoodadSetNames().ToList(); + _modelVariationListStore.Clear(); + for (var i = 0; i < doodadSetNames.Count; ++i) { - _modelVariationListStore.AppendValues(variation.TextureVariation1.Value, variation.ID); + _modelVariationListStore.AppendValues(doodadSetNames[i], i); } + + _modelVariationComboBox.Active = 0; + _modelVariationComboBox.Sensitive = _renderDoodadsCheckButton.Active && + doodadSetNames.Count > 1; + _renderDoodadsCheckButton.Sensitive = true; + break; } + case RenderableGameModel mdx: + { + mdx.ShouldRenderBounds = _renderBoundsCheckButton.Active; + mdx.ShouldRenderWireframe = _renderWireframeCheckButton.Active; - _modelVariationComboBox.Active = 0; - _modelVariationComboBox.Sensitive = skinVariations.Count > 1; - _renderDoodadsCheckButton.Sensitive = false; + var skinVariations = mdx.GetSkinVariations().ToList(); + _modelVariationListStore.Clear(); + foreach (var variation in skinVariations) + { + var firstTextureName = variation.TextureVariation1.Value; + if (!string.IsNullOrEmpty(firstTextureName)) + { + _modelVariationListStore.AppendValues(variation.TextureVariation1.Value, variation.ID); + } + } + + _modelVariationComboBox.Active = 0; + _modelVariationComboBox.Sensitive = skinVariations.Count > 1; + _renderDoodadsCheckButton.Sensitive = false; + break; + } } break; @@ -757,6 +816,11 @@ private Task ReloadGames() /// private void ReloadViewportBackground() { + if (_renderingEngine is null) + { + return; + } + _viewportWidget.MakeCurrent(); _renderingEngine.SetClearColour(_config.ViewportBackgroundColour); @@ -789,7 +853,12 @@ CancellationToken ct throw new ArgumentNullException(nameof(fileReference)); } - Log.Info($"Loading \"{fileReference.FilePath}\"."); + if (_renderingEngine is null) + { + return; + } + + _log.LogInformation($"Loading \"{fileReference.FilePath}\"."); _statusSpinner.Active = true; @@ -811,7 +880,13 @@ CancellationToken ct var renderable = await Task.Run ( - () => createRenderable(item, fileReference), + () => createRenderable + ( + _services.GetRequiredService(), + _services.GetRequiredService(), + item, + fileReference + ), ct ); @@ -836,7 +911,7 @@ CancellationToken ct } catch (OperationCanceledException) { - Log.Info($"Cancelled loading of {fileReference.Filename}"); + _log.LogInformation($"Cancelled loading of {fileReference.Filename}"); } finally { @@ -853,6 +928,11 @@ CancellationToken ct [ConnectBefore] private void OnViewportButtonPressed(object o, ButtonPressEventArgs args) { + if (_renderingEngine is null) + { + return; + } + if (_renderingEngine.IsMovementDisabled()) { return; @@ -905,6 +985,11 @@ private void OnViewportButtonPressed(object o, ButtonPressEventArgs args) [ConnectBefore] private void OnViewportButtonReleased(object o, ButtonReleaseEventArgs args) { + if (_renderingEngine is null) + { + return; + } + if (args.Event.Type != EventType.ButtonRelease) { return; @@ -972,7 +1057,8 @@ private static Task OnExportItemRequested(GamePage page, FileReference fileRefer { exportDialog.RunExport(); } - exportDialog.Destroy(); + + exportDialog.Hide(); } break; } @@ -999,7 +1085,7 @@ private Task OnEnqueueItemRequested(GamePage page, FileReference fileReference) /// /// Sender. /// E. - private void OnAboutButtonClicked(object sender, EventArgs e) + private void OnAboutButtonClicked(object? sender, EventArgs e) { _aboutDialog.Run(); _aboutDialog.Hide(); @@ -1010,7 +1096,7 @@ private void OnAboutButtonClicked(object sender, EventArgs e) /// /// Sender. /// E. - private async void OnPreferencesButtonClicked(object sender, EventArgs e) + private async void OnPreferencesButtonClicked(object? sender, EventArgs e) { using (var preferencesDialog = EverlookPreferences.Create()) { @@ -1020,7 +1106,7 @@ private async void OnPreferencesButtonClicked(object sender, EventArgs e) preferencesDialog.SavePreferences(); } - preferencesDialog.Destroy(); + preferencesDialog.Hide(); // Commit the changes ReloadViewportBackground(); @@ -1091,16 +1177,16 @@ private async Task OnSaveRequested(GamePage page, IEnumerable fil } catch (UnauthorizedAccessException unex) { - Log.Warn($"Failed to save \"{fileReference.Filename}\": {unex}"); + _log.LogWarning($"Failed to save \"{fileReference.Filename}\": {unex}"); } catch (IOException iex) { - Log.Warn($"Failed to save \"{fileReference.Filename}\": {iex}"); + _log.LogWarning($"Failed to save \"{fileReference.Filename}\": {iex}"); } } else { - Log.Warn + _log.LogWarning ( $"Failed to save \"{fileReference.Filename}\": Could not extract any data from the archives." ); @@ -1237,7 +1323,7 @@ await DisplayRenderableFile /// Sender. /// E. [ConnectBefore] - private void OnExportQueueButtonPressed(object sender, ButtonPressEventArgs e) + private void OnExportQueueButtonPressed(object? sender, ButtonPressEventArgs e) { if (e.Event.Type != EventType.ButtonPress || e.Event.Button != 3) { @@ -1266,8 +1352,7 @@ private void OnExportQueueButtonPressed(object sender, ButtonPressEventArgs e) } _queueContextMenu.ShowAll(); - _queueContextMenu.PopupForDevice(e.Event.Device, null, null, null, null, e.Event.Button, e.Event.Time); - //this.QueueContextMenu.Popup(); + _queueContextMenu.PopupAtPointer(e.Event); } /// @@ -1275,7 +1360,7 @@ private void OnExportQueueButtonPressed(object sender, ButtonPressEventArgs e) /// /// Sender. /// E. - private void OnQueueRemoveContextItemActivated(object sender, EventArgs e) + private void OnQueueRemoveContextItemActivated(object? sender, EventArgs e) { _exportQueueTreeView.Selection.GetSelected(out var selectedIter); _exportQueueListStore.Remove(ref selectedIter); @@ -1287,20 +1372,14 @@ private void OnQueueRemoveContextItemActivated(object sender, EventArgs e) /// /// Sender. /// The alpha component. - private void OnDeleteEvent(object sender, DeleteEventArgs a) + private void OnDeleteEvent(object? sender, DeleteEventArgs a) { _isShuttingDown = true; _fileLoadingCancellationSource?.Cancel(); - - _viewportWidget.MakeCurrent(); - - _renderingEngine.SetRenderTarget(null); - _renderingEngine.Dispose(); - + _renderingEngine?.Dispose(); _viewportWidget.Dispose(); - Application.Quit(); a.RetVal = true; } } diff --git a/Everlook/Utility/DataLoadingDelegates.cs b/Everlook/Utility/DataLoadingDelegates.cs index 2fe815f..bca3891 100644 --- a/Everlook/Utility/DataLoadingDelegates.cs +++ b/Everlook/Utility/DataLoadingDelegates.cs @@ -21,7 +21,9 @@ // using Everlook.Explorer; +using Everlook.Viewport.Rendering; using Everlook.Viewport.Rendering.Interfaces; +using Silk.NET.OpenGL; namespace Everlook.Utility { @@ -41,12 +43,20 @@ public static class DataLoadingDelegates /// /// A delegate which will create an from the specified item. /// + /// The OpenGL API. + /// The rendering cache. /// The item to encapsulate in a renderable version of it. /// The file reference associated with the object. /// /// A type which can be encapsulated in another type implementing . /// /// A renderable object. - public delegate IRenderable CreateRenderable(T renderableItem, FileReference fileReference); + public delegate IRenderable CreateRenderable + ( + GL gl, + RenderCache renderCache, + T renderableItem, + FileReference fileReference + ); } } diff --git a/Everlook/Utility/DataLoadingRoutines.cs b/Everlook/Utility/DataLoadingRoutines.cs index b10a767..57dc757 100644 --- a/Everlook/Utility/DataLoadingRoutines.cs +++ b/Everlook/Utility/DataLoadingRoutines.cs @@ -28,6 +28,7 @@ using Everlook.Viewport.Rendering; using Everlook.Viewport.Rendering.Interfaces; using log4net; +using Silk.NET.OpenGL; using Warcraft.BLP; using Warcraft.Core; using Warcraft.Core.Extensions; @@ -148,10 +149,18 @@ public static WMO LoadWorldModelGroup(FileReference fileReference) /// NOTE: This method *must* be called in the UI thread after the OpenGL context has been made current. /// The constructors commonly make extensive use of OpenGL methods. /// + /// The OpenGL API. + /// The rendering cache. /// The model object. /// The reference it was constructed from. /// An encapsulated renderable OpenGL object. - public static IRenderable CreateRenderableWorldModel(WMO worldModel, FileReference fileReference) + public static IRenderable CreateRenderableWorldModel + ( + GL gl, + RenderCache renderCache, + WMO worldModel, + FileReference fileReference + ) { var warcraftContext = fileReference.Context as WarcraftGameContext; if (warcraftContext == null) @@ -163,7 +172,7 @@ public static IRenderable CreateRenderableWorldModel(WMO worldModel, FileReferen ); } - var renderableWorldModel = new RenderableWorldModel(worldModel, warcraftContext); + var renderableWorldModel = new RenderableWorldModel(gl, renderCache, worldModel, warcraftContext); renderableWorldModel.LoadDoodads(); return renderableWorldModel; @@ -192,9 +201,12 @@ public static BLP LoadBinaryImage(FileReference fileReference) } catch (FileLoadException fex) { - Log.Warn( + Log.Warn + ( $"FileLoadException when loading BLP image: {fex.Message}\n" + - $"Please report this on GitHub or via email."); + $"Please report this on GitHub or via email." + ); + throw; } } @@ -213,12 +225,20 @@ public static BLP LoadBinaryImage(FileReference fileReference) /// NOTE: This method *must* be called in the UI thread after the OpenGL context has been made current. /// The constructors commonly make extensive use of OpenGL methods. /// + /// The OpenGL API. + /// The rendering cache. /// The image object. /// The reference it was constructed from. /// An encapsulated renderable OpenGL object. - public static IRenderable CreateRenderableBinaryImage(BLP binaryImage, FileReference fileReference) + public static IRenderable CreateRenderableBinaryImage + ( + GL gl, + RenderCache renderCache, + BLP binaryImage, + FileReference fileReference + ) { - var renderableImage = new RenderableBLP(binaryImage, fileReference.FilePath); + var renderableImage = new RenderableBLP(gl, renderCache, binaryImage, fileReference.FilePath); return renderableImage; } @@ -244,15 +264,16 @@ public static Bitmap LoadBitmapImage(FileReference fileReference) throw new FileNotFoundException(); } - using (var ms = new MemoryStream(fileData)) - { - image = new Bitmap(ms); - } + using var ms = new MemoryStream(fileData); + image = new Bitmap(ms); } catch (FileNotFoundException fex) { - Log.Warn( - $"Failed to load the image \"{fileReference.FilePath}\": {fex}"); + Log.Warn + ( + $"Failed to load the image \"{fileReference.FilePath}\": {fex}" + ); + throw; } @@ -265,12 +286,20 @@ public static Bitmap LoadBitmapImage(FileReference fileReference) /// NOTE: This method *must* be called in the UI thread after the OpenGL context has been made current. /// The constructors commonly make extensive use of OpenGL methods. /// + /// The OpenGL API. + /// The rendering cache. /// The image object. /// The reference it was constructed from. /// An encapsulated renderable OpenGL object. - public static IRenderable CreateRenderableBitmapImage(Bitmap bitmapImage, FileReference fileReference) + public static IRenderable CreateRenderableBitmapImage + ( + GL gl, + RenderCache renderCache, + Bitmap bitmapImage, + FileReference fileReference + ) { - var renderableImage = new RenderableBitmap(bitmapImage, fileReference.FilePath); + var renderableImage = new RenderableBitmap(gl, renderCache, bitmapImage, fileReference.FilePath); return renderableImage; } @@ -305,19 +334,16 @@ public static MDX LoadGameModel(FileReference fileReference) var modelSkinPath = $"{modelDirectory}\\{modelFilename}{i:D2}.skin"; var skinData = fileReference.Context.Assets.ExtractFile(modelSkinPath); - using (var ms = new MemoryStream(skinData)) + using var ms = new MemoryStream(skinData); + using var br = new BinaryReader(ms); + + var skinIdentifier = new string(br.ReadChars(4)); + if (skinIdentifier != "SKIN") { - using (var br = new BinaryReader(ms)) - { - var skinIdentifier = new string(br.ReadChars(4)); - if (skinIdentifier != "SKIN") - { - break; - } - - skins.Add(br.ReadMDXSkin(model.Version)); - } + break; } + + skins.Add(br.ReadMDXSkin(model.Version)); } model.SetSkins(skins); @@ -347,10 +373,18 @@ public static MDX LoadGameModel(FileReference fileReference) /// NOTE: This method *must* be called in the UI thread after the OpenGL context has been made current. /// The constructors commonly make extensive use of OpenGL methods. /// + /// The OpenGL API. + /// The rendering cache. /// The model object. /// The reference it was constructed from. /// An encapsulated renderable OpenGL object. - public static IRenderable CreateRenderableGameModel(MDX gameModel, FileReference fileReference) + public static IRenderable CreateRenderableGameModel + ( + GL gl, + RenderCache renderCache, + MDX gameModel, + FileReference fileReference + ) { var warcraftContext = fileReference.Context as WarcraftGameContext; if (warcraftContext == null) @@ -362,7 +396,14 @@ public static IRenderable CreateRenderableGameModel(MDX gameModel, FileReference ); } - var renderableModel = new RenderableGameModel(gameModel, warcraftContext, fileReference.FilePath); + var renderableModel = new RenderableGameModel + ( + gl, + renderCache, + gameModel, + warcraftContext, + fileReference.FilePath + ); return renderableModel; } diff --git a/Everlook/Utility/DirectoryHelpers.cs b/Everlook/Utility/DirectoryHelpers.cs index 93b4c87..faac1fe 100644 --- a/Everlook/Utility/DirectoryHelpers.cs +++ b/Everlook/Utility/DirectoryHelpers.cs @@ -39,7 +39,13 @@ public static string GetLocalDir() { var codeBaseURI = new UriBuilder(Assembly.GetExecutingAssembly().Location).Uri; - return Path.GetDirectoryName(Uri.UnescapeDataString(codeBaseURI.AbsolutePath)); + var directory = Path.GetDirectoryName(Uri.UnescapeDataString(codeBaseURI.AbsolutePath)); + if (directory is null) + { + throw new InvalidOperationException(); + } + + return directory; } } } diff --git a/Everlook/Viewport/Camera/CameraMovement.cs b/Everlook/Viewport/Camera/CameraMovement.cs index a7101bf..422d524 100644 --- a/Everlook/Viewport/Camera/CameraMovement.cs +++ b/Everlook/Viewport/Camera/CameraMovement.cs @@ -88,6 +88,41 @@ public bool ConstrainVerticalView set; } + /// + /// Gets or sets a value indicating whether the user wants to move left. + /// + public bool WantsToMoveLeft { get; set; } + + /// + /// Gets or sets a value indicating whether the user wants to move right. + /// + public bool WantsToMoveRight { get; set; } + + /// + /// Gets or sets a value indicating whether the user wants to move forward. + /// + public bool WantsToMoveForward { get; set; } + + /// + /// Gets or sets a value indicating whether the user wants to move backward. + /// + public bool WantsToMoveBackward { get; set; } + + /// + /// Gets or sets a value indicating whether the user wants to move up. + /// + public bool WantsToMoveUp { get; set; } + + /// + /// Gets or sets a value indicating whether the user wants to move down. + /// + public bool WantsToMoveDown { get; set; } + + /// + /// Gets or sets a value indicating whether the user wants to move faster. + /// + public bool WantsToSprint { get; set; } + /// /// Initializes a new instance of the class, bound to the input camera. /// @@ -162,7 +197,7 @@ public void Calculate3DMovement(double deltaMouseX, double deltaMouseY, float de var speedMultiplier = (float)(DefaultMovementSpeed * EverlookConfiguration.Instance.CameraSpeed); - if (Keyboard.GetState().IsKeyDown(Key.ShiftLeft)) + if (this.WantsToSprint) { speedMultiplier *= (float)EverlookConfiguration.Instance.SprintMultiplier; } @@ -170,32 +205,32 @@ public void Calculate3DMovement(double deltaMouseX, double deltaMouseY, float de var moveDistance = deltaTime * speedMultiplier; // Perform axial movement - if (Keyboard.GetState().IsKeyDown(Key.W)) + if (this.WantsToMoveForward) { MoveForward(moveDistance); } - if (Keyboard.GetState().IsKeyDown(Key.S)) + if (this.WantsToMoveBackward) { MoveBackward(moveDistance); } - if (Keyboard.GetState().IsKeyDown(Key.A)) + if (this.WantsToMoveLeft) { MoveLeft(moveDistance); } - if (Keyboard.GetState().IsKeyDown(Key.D)) + if (this.WantsToMoveRight) { MoveRight(moveDistance); } - if (Keyboard.GetState().IsKeyDown(Key.Q)) + if (this.WantsToMoveUp) { MoveUp(moveDistance); } - if (Keyboard.GetState().IsKeyDown(Key.E)) + if (this.WantsToMoveDown) { MoveDown(moveDistance); } diff --git a/Everlook/Viewport/ViewportRenderer.cs b/Everlook/Viewport/ViewportRenderer.cs index 2efc5d1..445ef73 100644 --- a/Everlook/Viewport/ViewportRenderer.cs +++ b/Everlook/Viewport/ViewportRenderer.cs @@ -150,14 +150,100 @@ Everlook caching and static data accessors. /// /// Initializes a new instance of the class. /// + /// The OpenGL API. + /// The rendering cache. /// The widget which the viewport should be rendered to. - public ViewportRenderer(ViewportArea viewportWidget) - : base(viewportWidget.GetAPI()) + public ViewportRenderer(GL gl, RenderCache renderCache, ViewportArea viewportWidget) + : base(gl) { _viewportWidget = viewportWidget; _camera = new ViewportCamera(); _movement = new CameraMovement(_camera); - _renderCache = new RenderCache(this.GL); + _renderCache = renderCache; + + _viewportWidget.KeyPressEvent += (o, args) => + { + switch (args.Event.Key) + { + case Key.Shift_L: + { + _movement.WantsToSprint = true; + break; + } + case Key.W: + { + _movement.WantsToMoveForward = true; + break; + } + case Key.S: + { + _movement.WantsToMoveBackward = true; + break; + } + case Key.A: + { + _movement.WantsToMoveLeft = true; + break; + } + case Key.D: + { + _movement.WantsToMoveRight = true; + break; + } + case Key.Q: + { + _movement.WantsToMoveUp = true; + break; + } + case Key.E: + { + _movement.WantsToMoveDown = true; + break; + } + } + }; + + _viewportWidget.KeyReleaseEvent += (o, args) => + { + switch (args.Event.Key) + { + case Key.Shift_L: + { + _movement.WantsToSprint = false; + break; + } + case Key.W: + { + _movement.WantsToMoveForward = false; + break; + } + case Key.S: + { + _movement.WantsToMoveBackward = false; + break; + } + case Key.A: + { + _movement.WantsToMoveLeft = false; + break; + } + case Key.D: + { + _movement.WantsToMoveRight = false; + break; + } + case Key.Q: + { + _movement.WantsToMoveUp = false; + break; + } + case Key.E: + { + _movement.WantsToMoveDown = false; + break; + } + } + }; this.IsInitialized = false; } diff --git a/Everlook/app.config b/Everlook/app.config deleted file mode 100644 index 6caee30..0000000 --- a/Everlook/app.config +++ /dev/null @@ -1,33 +0,0 @@ - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Everlook/config/appsettings.json b/Everlook/config/appsettings.json new file mode 100644 index 0000000..6ba02f3 --- /dev/null +++ b/Everlook/config/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/Everlook/log4net.config b/Everlook/log4net.config new file mode 100644 index 0000000..2ba500a --- /dev/null +++ b/Everlook/log4net.config @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + From df66a9ca8a3c82de70bcd5569acd2cc46c4466a3 Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sat, 4 Apr 2020 22:35:56 +0200 Subject: [PATCH 08/18] Replace a number of obsolete methods. --- Everlook.sln.DotSettings | 1 + Everlook/Audio/MP3/MP3AudioAsset.cs | 3 +- Everlook/Audio/Wave/WaveAudioAsset.cs | 3 +- Everlook/Explorer/FileReference.cs | 26 +++---- Everlook/Explorer/FileTreeModel.cs | 2 +- Everlook/Explorer/GameLoader.cs | 10 +-- Everlook/Explorer/GamePage.cs | 7 +- Everlook/Package/PackageGroup.cs | 67 ++++++++----------- Everlook/Package/PackageInteractionHandler.cs | 63 +++++++---------- Everlook/Program.cs | 13 ++++ Everlook/UI/EverlookDirectoryExportDialog.cs | 10 +-- Everlook/UI/EverlookGameLoadingDialog.cs | 6 +- Everlook/UI/EverlookImageExportDialog.cs | 9 ++- Everlook/UI/MainWindow.cs | 7 +- Everlook/UI/Widgets/ViewportArea.cs | 13 +--- Everlook/Utility/DataLoadingRoutines.cs | 45 ++++++++++--- Everlook/Utility/IconManager.cs | 5 +- Everlook/Viewport/Camera/CameraMovement.cs | 1 - .../Viewport/Rendering/RenderableGameModel.cs | 16 ++--- .../Viewport/Rendering/RenderableImage.cs | 2 +- .../Rendering/RenderableWorldModel.cs | 2 +- .../Shaders/GLSLExtended/GLSLPreprocessor.cs | 2 +- Everlook/log4net.config | 2 +- 23 files changed, 155 insertions(+), 160 deletions(-) diff --git a/Everlook.sln.DotSettings b/Everlook.sln.DotSettings index cadf93f..201d43b 100644 --- a/Everlook.sln.DotSettings +++ b/Everlook.sln.DotSettings @@ -94,5 +94,6 @@ True True True + True True True \ No newline at end of file diff --git a/Everlook/Audio/MP3/MP3AudioAsset.cs b/Everlook/Audio/MP3/MP3AudioAsset.cs index 221ec67..61d0ea0 100644 --- a/Everlook/Audio/MP3/MP3AudioAsset.cs +++ b/Everlook/Audio/MP3/MP3AudioAsset.cs @@ -124,8 +124,7 @@ public MP3AudioAsset(FileReference fileReference) ); } - var fileBytes = fileReference.Extract(); - if (fileBytes == null) + if (!fileReference.TryExtract(out var fileBytes)) { throw new ArgumentException("The file data could not be extracted.", nameof(fileReference)); } diff --git a/Everlook/Audio/Wave/WaveAudioAsset.cs b/Everlook/Audio/Wave/WaveAudioAsset.cs index 1c3eb54..6b8dbdf 100644 --- a/Everlook/Audio/Wave/WaveAudioAsset.cs +++ b/Everlook/Audio/Wave/WaveAudioAsset.cs @@ -125,8 +125,7 @@ public WaveAudioAsset(FileReference fileReference) ); } - var fileBytes = fileReference.Extract(); - if (fileBytes == null) + if (!fileReference.TryExtract(out var fileBytes)) { throw new ArgumentException("The file data could not be extracted.", nameof(fileReference)); } diff --git a/Everlook/Explorer/FileReference.cs b/Everlook/Explorer/FileReference.cs index 8fdbee9..f18feeb 100644 --- a/Everlook/Explorer/FileReference.cs +++ b/Everlook/Explorer/FileReference.cs @@ -21,8 +21,8 @@ // using System; +using System.Diagnostics.CodeAnalysis; using System.IO; -using System.Threading.Tasks; using Everlook.Utility; using FileTree.Tree.Nodes; using FileTree.Tree.Serialized; @@ -86,12 +86,12 @@ public MPQFileInfo? ReferenceInfo { get { - if (this.IsFile) + if (!this.IsFile) { - return this.Context.Assets.GetReferenceInfo(this); + return null; } - return null; + return this.Context.Assets.TryGetReferenceInfo(this, out var result) ? result : null; } } @@ -160,21 +160,13 @@ public FileReference(IGameContext gameContext, SerializedNode node, string packa } /// - /// Asynchronously extracts this instance from the package group it is associated with. + /// Attempts to extract this instance from the package group it is associated with. /// - /// A task wrapping the raw data of the file pointed to by the reference. - public Task ExtractAsync() + /// The extracted data. + /// true if the data was successfully extracted; otherwise, false. + public bool TryExtract([NotNullWhen(true)] out byte[]? data) { - return Task.Factory.StartNew(Extract); - } - - /// - /// Extracts this instance from the package group it is associated with. - /// - /// The raw data of the file pointed to by the reference. - public byte[]? Extract() - { - return this.Context.Assets.ExtractVersionedReference(this); + return this.Context.Assets.TryExtractVersionedReference(this, out data); } /// diff --git a/Everlook/Explorer/FileTreeModel.cs b/Everlook/Explorer/FileTreeModel.cs index 5a90056..585f524 100644 --- a/Everlook/Explorer/FileTreeModel.cs +++ b/Everlook/Explorer/FileTreeModel.cs @@ -36,7 +36,7 @@ namespace Everlook.Explorer { /// - /// GTK TreeModel which serves an . + /// GTK TreeModel which serves tree nodes. /// public class FileTreeModel : Object, ITreeModelImplementor { diff --git a/Everlook/Explorer/GameLoader.cs b/Everlook/Explorer/GameLoader.cs index d0c76e1..a1576b8 100644 --- a/Everlook/Explorer/GameLoader.cs +++ b/Everlook/Explorer/GameLoader.cs @@ -85,7 +85,7 @@ private static Task LoadDictionaryAsync(CancellationToken ct /// A cancellation token. /// An object for progress reporting. /// A tuple with a package group and a node tree for the requested game. - public async Task<(PackageGroup? packageGroup, SerializedTree? nodeTree)> LoadGameAsync + public async Task<(PackageGroup? PackageGroup, SerializedTree? NodeTree)> LoadGameAsync ( string gameAlias, string gamePath, @@ -156,7 +156,7 @@ private static Task LoadDictionaryAsync(CancellationToken ct double totalSteps = packagePaths.Count * 2; // Load packages - var packages = new List<(string packageName, IPackage package)>(); + var packages = new List<(string PackageName, IPackage Package)>(); foreach (var packagePath in packagePaths) { ct.ThrowIfCancellationRequested(); @@ -219,15 +219,15 @@ private static Task LoadDictionaryAsync(CancellationToken ct CompletionPercentage = steps / totalSteps, State = GameLoadingState.BuildingNodeTree, Alias = gameAlias, - CurrentPackage = packageInfo.packageName, + CurrentPackage = packageInfo.PackageName, NodesCreationProgress = p } ); } ); - await Task.Run(() => builder.AddPackage(packageInfo.packageName, packageInfo.package, createNodesProgress, ct), ct); - packageGroup.AddPackage((PackageInteractionHandler)packageInfo.package); + await Task.Run(() => builder.AddPackage(packageInfo.PackageName, packageInfo.Package, createNodesProgress, ct), ct); + packageGroup.AddPackage((PackageInteractionHandler)packageInfo.Package); ++completedSteps; } diff --git a/Everlook/Explorer/GamePage.cs b/Everlook/Explorer/GamePage.cs index 1aa5d87..056fcb9 100644 --- a/Everlook/Explorer/GamePage.cs +++ b/Everlook/Explorer/GamePage.cs @@ -554,9 +554,7 @@ private void OnButtonPressed(object o, ButtonPressEventArgs args) } _treeContextMenu.ShowAll(); - - //this.TreeContextMenu.Popup(); // only available in GTK >= 3.22 - _treeContextMenu.PopupForDevice(args.Event.Device, null, null, null, null, args.Event.Button, args.Event.Time); + _treeContextMenu.PopupAtPointer(args.Event); } /// @@ -655,8 +653,7 @@ private static void OpenReference(FileReference fileReference) case WarcraftFileType.Font: case WarcraftFileType.Script: { - var fileData = fileReference.Extract(); - if (fileData != null) + if (fileReference.TryExtract(out var fileData)) { // create a temporary file and write the data to it. var tempPath = Path.Combine(Path.GetTempPath(), fileReference.Filename); diff --git a/Everlook/Package/PackageGroup.cs b/Everlook/Package/PackageGroup.cs index 4c20b21..0a3d351 100644 --- a/Everlook/Package/PackageGroup.cs +++ b/Everlook/Package/PackageGroup.cs @@ -207,77 +207,67 @@ public void AddPackage(PackageInteractionHandler package) } /// - /// Gets the reference info for the specified reference. This method gets the most recent info for the file from - /// overriding packages. + /// Attempts to get the reference info for the specified reference. This method gets the most recent info for + /// the file from overriding packages. /// /// The reference info. /// Reference reference. - public MPQFileInfo GetReferenceInfo(FileReference fileReference) + /// The file information. + public bool TryGetReferenceInfo(FileReference fileReference, [NotNullWhen(true)] out MPQFileInfo? fileInfo) { - if (fileReference == null) - { - throw new ArgumentNullException(nameof(fileReference)); - } - - return GetFileInfo(fileReference.FilePath); + return TryGetFileInfo(fileReference.FilePath, out fileInfo); } /// - /// Gets the file info for the specified reference in its specific package. If the file does not exist in - /// the package referenced in , this method returned will return null. + /// Attempts to get the file info for the specified reference in its specific package. If the file does not + /// exist in the package referenced in , this method will return false. /// /// The reference info. /// Reference reference. - public MPQFileInfo? GetVersionedReferenceInfo(FileReference fileReference) + /// The file info. + public bool TryGetVersionedReferenceInfo + ( + FileReference fileReference, + [NotNullWhen(true)] out MPQFileInfo? fileInfo + ) { - if (fileReference == null) - { - throw new ArgumentNullException(nameof(fileReference)); - } - var package = GetPackageByName(fileReference.PackageName); - return package.GetReferenceInfo(fileReference); + return package.TryGetReferenceInfo(fileReference, out fileInfo); } /// - /// Extracts a file from a specific package in the package group. If the file does not exist in + /// Attempts to extract a file from a specific package in the package group. If the file does not exist in /// the package referenced in , this method returned will return null. /// /// The unversioned file or null. /// Reference reference. - public byte[]? ExtractVersionedReference(FileReference fileReference) + /// The data. + public bool TryExtractVersionedReference(FileReference fileReference, [NotNullWhen(true)] out byte[]? data) { - if (fileReference == null) - { - throw new ArgumentNullException(nameof(fileReference)); - } + data = null; if (fileReference.IsVirtual) { - return ExtractReference(fileReference); + return TryExtractReference(fileReference, out data); } var package = GetPackageByName(fileReference.PackageName); - return package?.ExtractReference(fileReference); + return !(package is null) && package.TryExtractReference(fileReference, out data); } /// - /// Extracts a file from the package group. This method returns the most recently overridden version + /// Attempts to extract a file from the package group. This method returns the most recently overridden version /// of the specified file with no regard for the origin package. The returned file may originate from the /// package referenced in the , or it may originate from a patch package. /// - /// If the file does not exist in any package, this method will return null. + /// If the file does not exist in any package, this method will return false. /// /// The file or null. /// Reference reference. - public byte[] ExtractReference(FileReference fileReference) + /// The data. + public bool TryExtractReference(FileReference fileReference, [NotNullWhen(true)] out byte[]? data) { - if (fileReference == null) - { - throw new ArgumentNullException(nameof(fileReference)); - } - - return ExtractFile(fileReference.FilePath); + return TryExtractFile(fileReference.FilePath, out data); } /// @@ -323,7 +313,7 @@ private PackageInteractionHandler GetPackageByName(string packageName) } /// - public bool TryExtractFile(string filePath, out byte[]? data) + public bool TryExtractFile(string filePath, [NotNullWhen(true)] out byte[]? data) { data = null; @@ -339,6 +329,7 @@ public bool TryExtractFile(string filePath, out byte[]? data) } /// + [Obsolete] public byte[] ExtractFile(string filePath) { for (var i = _packages.Count - 1; i >= 0; --i) @@ -387,8 +378,7 @@ public bool TryGetFileInfo(string filePath, [NotNullWhen(true)] out MPQFileInfo? { if (_packages[i].ContainsFile(filePath)) { - fileInfo = _packages[i].GetFileInfo(filePath); - return true; + return _packages[i].TryGetFileInfo(filePath, out fileInfo); } } @@ -396,6 +386,7 @@ public bool TryGetFileInfo(string filePath, [NotNullWhen(true)] out MPQFileInfo? } /// + [Obsolete] public MPQFileInfo GetFileInfo(string filePath) { if (!TryGetFileInfo(filePath, out var fileInfo)) diff --git a/Everlook/Package/PackageInteractionHandler.cs b/Everlook/Package/PackageInteractionHandler.cs index 7e09886..2ae7ae9 100644 --- a/Everlook/Package/PackageInteractionHandler.cs +++ b/Everlook/Package/PackageInteractionHandler.cs @@ -26,8 +26,6 @@ using System.IO; using System.Threading.Tasks; using Everlook.Explorer; -using log4net; -using Warcraft.Core; using Warcraft.MPQ; using Warcraft.MPQ.FileInfo; @@ -39,11 +37,6 @@ namespace Everlook.Package /// public sealed class PackageInteractionHandler : IDisposable, IPackage { - /// - /// Logger instance for this class. - /// - private static readonly ILog Log = LogManager.GetLogger(typeof(PackageInteractionHandler)); - /// /// Gets the package path. /// @@ -147,46 +140,30 @@ public bool ContainsFile(FileReference fileReference) } /// - /// Extracts the specified reference from its associated package. This method only operates on the file path. + /// Attempts to extract a file from the package group. This method returns the most recently overridden version + /// of the specified file with no regard for the origin package. The returned file may originate from the + /// package referenced in the , or it may originate from a patch package. + /// + /// If the file does not exist in any package, this method will return false. /// + /// The file or null. /// Reference reference. - /// The raw data of the file pointed to by the reference. - public byte[]? ExtractReference(FileReference fileReference) + /// The data. + public bool TryExtractReference(FileReference fileReference, [NotNullWhen(true)] out byte[]? data) { - if (!fileReference.IsFile) - { - throw new ArgumentException("The specified reference can't be extracted.", nameof(fileReference)); - } - - try - { - return ExtractFile(fileReference.FilePath); - } - catch (InvalidFileSectorTableException fex) - { - Log.Warn - ( - $"Failed to extract the file \"{fileReference.FilePath}\" due to an invalid sector table " + - $"(\"{fex.Message}\")." - ); - throw; - } + return TryExtractFile(fileReference.FilePath, out data); } /// - /// Gets a set of information about the specified package file, such as stored size, disk size - /// and storage flags. + /// Attempts to get the reference info for the specified reference. This method gets the most recent info for + /// the file from overriding packages. /// /// The reference info. /// Reference reference. - public MPQFileInfo? GetReferenceInfo(FileReference fileReference) + /// The file information. + public bool TryGetReferenceInfo(FileReference fileReference, [NotNullWhen(true)] out MPQFileInfo? fileInfo) { - if (!fileReference.IsFile) - { - throw new ArgumentException("The specified reference is not a file.", nameof(fileReference)); - } - - return GetFileInfo(fileReference.FilePath); + return TryGetFileInfo(fileReference.FilePath, out fileInfo); } /// @@ -203,6 +180,7 @@ public bool TryExtractFile(string filePath, [NotNullWhen(true)] out byte[]? data } /// + [Obsolete] public byte[]? ExtractFile(string filePath) { return _package?.ExtractFile(filePath); @@ -254,9 +232,18 @@ public bool TryGetFileInfo(string filePath, [NotNullWhen(true)] out MPQFileInfo? } /// + [Obsolete] public MPQFileInfo? GetFileInfo(string filePath) { - return _package?.GetFileInfo(filePath); + try + { + return _package?.GetFileInfo(filePath); + } + catch (FileNotFoundException) + { + // TODO: YUCK + return null; + } } /// diff --git a/Everlook/Program.cs b/Everlook/Program.cs index 7eec282..37a6c95 100644 --- a/Everlook/Program.cs +++ b/Everlook/Program.cs @@ -51,6 +51,11 @@ namespace Everlook /// internal class Program { + /// + /// Holds the logging instance for this class. + /// + private static ILogger? _log; + /// /// The entry point. /// @@ -59,6 +64,8 @@ internal class Program [STAThread] public static async Task Main(string[] args) { + ExceptionManager.UnhandledException += OnUnhandledGLibException; + IconManager.LoadEmbeddedIcons(); Application.Init(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -91,12 +98,18 @@ public static async Task Main(string[] args) var host = CreateHostBuilder(args).Build(); + _log = host.Services.GetRequiredService>(); var app = host.Services.GetRequiredService(); app.Start(); Application.Run(); } + private static void OnUnhandledGLibException(UnhandledExceptionArgs args) + { + _log.LogError((Exception)args.ExceptionObject, "Unhandled GLib exception."); + } + private static IHostBuilder CreateHostBuilder(string[] args) => new HostBuilder() .ConfigureAppConfiguration((hostingContext, config) => { diff --git a/Everlook/UI/EverlookDirectoryExportDialog.cs b/Everlook/UI/EverlookDirectoryExportDialog.cs index f30e575..ad4d146 100644 --- a/Everlook/UI/EverlookDirectoryExportDialog.cs +++ b/Everlook/UI/EverlookDirectoryExportDialog.cs @@ -157,13 +157,13 @@ public void RunExport() [GLib.ConnectBefore] private void OnItemListingButtonPressed(object? sender, ButtonPressEventArgs e) { - if (e.Event.Type == EventType.ButtonPress && e.Event.Button == 3) + if (e.Event.Type != EventType.ButtonPress || e.Event.Button != 3) { - _exportPopupMenu.ShowAll(); - - _exportPopupMenu.PopupForDevice(e.Event.Device, null, null, null, null, e.Event.Button, e.Event.Time); - //this.ExportPopupMenu.Popup(); + return; } + + _exportPopupMenu.ShowAll(); + _exportPopupMenu.PopupAtPointer(e.Event); } /// diff --git a/Everlook/UI/EverlookGameLoadingDialog.cs b/Everlook/UI/EverlookGameLoadingDialog.cs index efa8e6a..252c9ca 100644 --- a/Everlook/UI/EverlookGameLoadingDialog.cs +++ b/Everlook/UI/EverlookGameLoadingDialog.cs @@ -261,10 +261,10 @@ private void SetStatusMessage(string statusMessage) $"{_currentLoadingProgress.OperationCount}) {statusMessage}"; } - /// - public override void Destroy() + /// + protected override void Dispose(bool disposing) { - base.Destroy(); + base.Dispose(disposing); GLib.Timeout.Remove(_jokeTimeoutID); GLib.Timeout.Remove(_secondaryProgressPulserTimeoutID); diff --git a/Everlook/UI/EverlookImageExportDialog.cs b/Everlook/UI/EverlookImageExportDialog.cs index 7574beb..3bc3e45 100644 --- a/Everlook/UI/EverlookImageExportDialog.cs +++ b/Everlook/UI/EverlookImageExportDialog.cs @@ -110,7 +110,11 @@ private void LoadInformation() this.Title = $"Export Image | {imageFilename}"; - var file = _exportTarget.Extract(); + if (!_exportTarget.TryExtract(out var file)) + { + throw new ArgumentException("The file data could not be extracted.", nameof(_exportTarget)); + } + _image = new BLP(file); _exportFormatComboBox.Active = (int)_config.DefaultImageExportFormat; @@ -240,8 +244,7 @@ protected void OnMipListingButtonPressed(object? sender, ButtonPressEventArgs e) { _exportPopupMenu.ShowAll(); - _exportPopupMenu.PopupForDevice(e.Event.Device, null, null, null, null, e.Event.Button, e.Event.Time); - //this.ExportPopupMenu.Popup(); + _exportPopupMenu.PopupAtPointer(e.Event); } } diff --git a/Everlook/UI/MainWindow.cs b/Everlook/UI/MainWindow.cs index fb092b8..110b50c 100644 --- a/Everlook/UI/MainWindow.cs +++ b/Everlook/UI/MainWindow.cs @@ -43,7 +43,6 @@ using GLib; using Gtk; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Silk.NET.OpenGL; using Warcraft.Core; @@ -558,7 +557,7 @@ private async Task LoadGames() sw.Start(); var loader = new GameLoader(); - var dialog = EverlookGameLoadingDialog.Create(this); + using var dialog = EverlookGameLoadingDialog.Create(this); dialog.ShowAll(); var loadingProgress = default(OverallLoadingProgress); @@ -602,7 +601,6 @@ private async Task LoadGames() } dialog.Hide(); - dialog.Destroy(); sw.Stop(); _log.LogDebug($"Game loading took {sw.Elapsed.TotalMilliseconds}ms ({sw.Elapsed.TotalSeconds}s)"); @@ -1157,8 +1155,7 @@ private async Task OnSaveRequested(GamePage page, IEnumerable fil Directory.CreateDirectory(Directory.GetParent(exportpath).FullName); } - var file = await fileReference.ExtractAsync(); - if (file != null) + if (fileReference.TryExtract(out var file)) { try { diff --git a/Everlook/UI/Widgets/ViewportArea.cs b/Everlook/UI/Widgets/ViewportArea.cs index 7bd0c08..1477045 100644 --- a/Everlook/UI/Widgets/ViewportArea.cs +++ b/Everlook/UI/Widgets/ViewportArea.cs @@ -32,15 +32,11 @@ namespace Everlook.UI.Widgets /// The is a GTK widget for which an OpenGL context can be used to draw arbitrary /// graphics. /// - [CLSCompliant(false)] [ToolboxItem(true)] public class ViewportArea : GLArea { private readonly bool _isDebugEnabled; private readonly bool _isForwardCompatible; - private readonly bool _withDepthBuffer; - private readonly bool _withStencilBuffer; - private readonly bool _withAlpha; private bool _isInitialized; @@ -82,17 +78,14 @@ public ViewportArea { _isDebugEnabled = isDebugEnabled; _isForwardCompatible = isForwardCompatible; - _withDepthBuffer = withDepthBuffer; - _withStencilBuffer = withStencilBuffer; - _withAlpha = withAlpha; AddTickCallback(UpdateFrameTime); SetRequiredVersion(glVersionMajor, glVersionMinor); - this.HasDepthBuffer = _withDepthBuffer; - this.HasStencilBuffer = _withStencilBuffer; - this.HasAlpha = _withAlpha; + this.HasDepthBuffer = withDepthBuffer; + this.HasStencilBuffer = withStencilBuffer; + this.HasAlpha = withAlpha; } /// diff --git a/Everlook/Utility/DataLoadingRoutines.cs b/Everlook/Utility/DataLoadingRoutines.cs index 57dc757..19501ae 100644 --- a/Everlook/Utility/DataLoadingRoutines.cs +++ b/Everlook/Utility/DataLoadingRoutines.cs @@ -66,7 +66,11 @@ public static WMO LoadWorldModel(FileReference fileReference) WMO worldModel; try { - var fileData = fileReference.Extract(); + if (!fileReference.TryExtract(out var fileData)) + { + throw new FileNotFoundException(); + } + worldModel = new WMO(fileData); var modelPathWithoutExtension = $"{fileReference.FileDirectory.Replace('/', '\\')}\\" + @@ -78,7 +82,11 @@ public static WMO LoadWorldModel(FileReference fileReference) try { - var modelGroupData = fileReference.Context.Assets.ExtractFile(modelGroupPath); + if (!fileReference.Context.Assets.TryExtractFile(modelGroupPath, out var modelGroupData)) + { + throw new FileNotFoundException(); + } + worldModel.AddModelGroup(new ModelGroup(modelGroupData)); } catch (FileNotFoundException fex) @@ -116,14 +124,22 @@ public static WMO LoadWorldModelGroup(FileReference fileReference) // Get the file name of the root object var modelRootPath = fileReference.FilePath.Remove(fileReference.FilePath.Length - 8, 4); - WMO worldModel; // Extract it and load just this model group + WMO worldModel; try { - var rootData = fileReference.Context.Assets.ExtractFile(modelRootPath); + if (!fileReference.Context.Assets.TryExtractFile(modelRootPath, out var rootData)) + { + throw new FileNotFoundException(); + } + worldModel = new WMO(rootData); - var modelGroupData = fileReference.Extract(); + if (!fileReference.TryExtract(out var modelGroupData)) + { + throw new FileNotFoundException(); + } + worldModel.AddModelGroup(new ModelGroup(modelGroupData)); } catch (FileNotFoundException fex) @@ -193,7 +209,10 @@ public static BLP LoadBinaryImage(FileReference fileReference) BLP image; try { - var fileData = fileReference.Extract(); + if (!fileReference.TryExtract(out var fileData)) + { + throw new FileNotFoundException(); + } try { @@ -258,8 +277,7 @@ public static Bitmap LoadBitmapImage(FileReference fileReference) Bitmap image; try { - var fileData = fileReference.Extract(); - if (fileData is null) + if (!fileReference.TryExtract(out var fileData)) { throw new FileNotFoundException(); } @@ -319,7 +337,11 @@ public static MDX LoadGameModel(FileReference fileReference) MDX model; try { - var fileData = fileReference.Extract(); + if (!fileReference.TryExtract(out var fileData)) + { + throw new FileNotFoundException(); + } + model = new MDX(fileData); if (model.Version >= WarcraftVersion.Wrath) @@ -332,7 +354,10 @@ public static MDX LoadGameModel(FileReference fileReference) for (var i = 0; i < model.SkinCount; ++i) { var modelSkinPath = $"{modelDirectory}\\{modelFilename}{i:D2}.skin"; - var skinData = fileReference.Context.Assets.ExtractFile(modelSkinPath); + if (!fileReference.Context.Assets.TryExtractFile(modelSkinPath, out var skinData)) + { + continue; + } using var ms = new MemoryStream(skinData); using var br = new BinaryReader(ms); diff --git a/Everlook/Utility/IconManager.cs b/Everlook/Utility/IconManager.cs index ff665ed..57af111 100644 --- a/Everlook/Utility/IconManager.cs +++ b/Everlook/Utility/IconManager.cs @@ -43,8 +43,8 @@ public static class IconManager /// private static readonly ILog Log = LogManager.GetLogger(typeof(IconManager)); - private static readonly Dictionary<(string iconName, int iconSize), Pixbuf> IconCache = - new Dictionary<(string iconName, int iconSize), Pixbuf>(); + private static readonly Dictionary<(string IconName, int IconSize), Pixbuf> IconCache = + new Dictionary<(string IconName, int IconSize), Pixbuf>(); /// /// Loads all embedded builtin icons into the application's icon theme. @@ -289,7 +289,6 @@ public static Pixbuf GetIconForFiletype(WarcraftFileType fileType) { return GetIcon("text-xml"); } - case WarcraftFileType.Unknown: default: { return GetIcon(Stock.File); diff --git a/Everlook/Viewport/Camera/CameraMovement.cs b/Everlook/Viewport/Camera/CameraMovement.cs index 422d524..6672006 100644 --- a/Everlook/Viewport/Camera/CameraMovement.cs +++ b/Everlook/Viewport/Camera/CameraMovement.cs @@ -24,7 +24,6 @@ using System.Numerics; using Everlook.Configuration; using Everlook.Utility; -using Gdk; namespace Everlook.Viewport.Camera { diff --git a/Everlook/Viewport/Rendering/RenderableGameModel.cs b/Everlook/Viewport/Rendering/RenderableGameModel.cs index e5b73a3..b89db08 100644 --- a/Everlook/Viewport/Rendering/RenderableGameModel.cs +++ b/Everlook/Viewport/Rendering/RenderableGameModel.cs @@ -325,7 +325,7 @@ public void RenderInstances(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, Vi _vertexBuffer.Bind(); _vertexBuffer.EnableAttributes(); - GL.Enable(EnableCap.DepthTest); + this.GL.Enable(EnableCap.DepthTest); var modelViewMatrix = this.ActorTransform.GetModelMatrix() * viewMatrix; var modelViewProjection = modelViewMatrix * projectionMatrix; @@ -344,7 +344,7 @@ public void RenderInstances(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, Vi _shader.Wireframe.SetViewportMatrix(camera.GetViewportMatrix()); // Override blend setting - GL.Enable(EnableCap.Blend); + this.GL.Enable(EnableCap.Blend); } foreach (var skin in _model.Skins) @@ -353,7 +353,7 @@ public void RenderInstances(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, Vi if (this.ShouldRenderWireframe) { // Override blend setting - GL.Enable(EnableCap.Blend); + this.GL.Enable(EnableCap.Blend); } foreach (var renderBatch in skin.RenderBatches) @@ -369,7 +369,7 @@ public void RenderInstances(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, Vi unsafe { - GL.DrawElementsInstanced + this.GL.DrawElementsInstanced ( PrimitiveType.Triangles, skinSection.TriangleCount, @@ -409,7 +409,7 @@ public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCam _vertexBuffer.Bind(); _vertexBuffer.EnableAttributes(); - GL.Enable(EnableCap.DepthTest); + this.GL.Enable(EnableCap.DepthTest); var modelViewMatrix = this.ActorTransform.GetModelMatrix() * viewMatrix; var modelViewProjection = modelViewMatrix * projectionMatrix; @@ -428,7 +428,7 @@ public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCam _shader.Wireframe.SetViewportMatrix(camera.GetViewportMatrix()); // Override blend setting - GL.Enable(EnableCap.Blend); + this.GL.Enable(EnableCap.Blend); } foreach (var skin in _model.Skins) @@ -437,7 +437,7 @@ public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCam if (this.ShouldRenderWireframe) { // Override blend setting - GL.Enable(EnableCap.Blend); + this.GL.Enable(EnableCap.Blend); } foreach (var renderBatch in skin.RenderBatches) @@ -452,7 +452,7 @@ public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCam var skinSection = skin.Sections[renderBatch.SkinSectionIndex]; unsafe { - GL.DrawElements + this.GL.DrawElements ( PrimitiveType.Triangles, skinSection.TriangleCount, diff --git a/Everlook/Viewport/Rendering/RenderableImage.cs b/Everlook/Viewport/Rendering/RenderableImage.cs index 29aab3a..6bfd8af 100644 --- a/Everlook/Viewport/Rendering/RenderableImage.cs +++ b/Everlook/Viewport/Rendering/RenderableImage.cs @@ -184,7 +184,7 @@ public void Initialize() this.Texture = LoadTexture(); // Use cached shaders whenever possible - this.Shader = RenderCache.GetShader(EverlookShader.Plain2D) as Plain2DShader; + this.Shader = this.RenderCache.GetShader(EverlookShader.Plain2D) as Plain2DShader; this.ActorTransform = new Transform(); diff --git a/Everlook/Viewport/Rendering/RenderableWorldModel.cs b/Everlook/Viewport/Rendering/RenderableWorldModel.cs index f395a1a..832853b 100644 --- a/Everlook/Viewport/Rendering/RenderableWorldModel.cs +++ b/Everlook/Viewport/Rendering/RenderableWorldModel.cs @@ -466,7 +466,7 @@ public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCam { foreach (var doodadInstanceSet in _doodadSets[this.DoodadSet]) { - //doodadInstanceSet.ShouldRenderBounds = this.ShouldRenderBounds; + doodadInstanceSet.ShouldRenderBounds = this.ShouldRenderBounds; } foreach (var doodadInstanceSet in _doodadSets[this.DoodadSet]) diff --git a/Everlook/Viewport/Rendering/Shaders/GLSLExtended/GLSLPreprocessor.cs b/Everlook/Viewport/Rendering/Shaders/GLSLExtended/GLSLPreprocessor.cs index aa579d1..d9f5634 100644 --- a/Everlook/Viewport/Rendering/Shaders/GLSLExtended/GLSLPreprocessor.cs +++ b/Everlook/Viewport/Rendering/Shaders/GLSLExtended/GLSLPreprocessor.cs @@ -43,7 +43,7 @@ public static string ProcessIncludes(string source, string baseResourceDirectory { // Find a list of includes var includeRegex = new Regex("#include\\s+?\"(?.+)\"", RegexOptions.Multiline); - var matches = includeRegex.Matches(source).Cast().Reverse(); + var matches = includeRegex.Matches(source).Reverse(); // Remove any trailing dot separators from the resource directory. baseResourceDirectory = baseResourceDirectory.TrimEnd('.'); diff --git a/Everlook/log4net.config b/Everlook/log4net.config index 2ba500a..3598450 100644 --- a/Everlook/log4net.config +++ b/Everlook/log4net.config @@ -6,7 +6,7 @@ - + From cd8b609b01d24fbd9518b20a0317ac601a4d12fd Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sat, 4 Apr 2020 22:42:13 +0200 Subject: [PATCH 09/18] Convert mat4 into a mat3. --- .../SolidWireframe/SolidWireframeGeometry.glsl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Everlook/Content/Shaders/Components/SolidWireframe/SolidWireframeGeometry.glsl b/Everlook/Content/Shaders/Components/SolidWireframe/SolidWireframeGeometry.glsl index 1daa851..d08ee61 100644 --- a/Everlook/Content/Shaders/Components/SolidWireframe/SolidWireframeGeometry.glsl +++ b/Everlook/Content/Shaders/Components/SolidWireframe/SolidWireframeGeometry.glsl @@ -40,7 +40,7 @@ out GeometryOut flat vec2 ABDir; } gOut; -uniform mat3 ViewportMatrix; +uniform mat4 ViewportMatrix; uniform bool IsWireframeEnabled; void InitializeOutput() @@ -124,13 +124,13 @@ int DetermineCase(float P0z, float P1z, float P2z) vec2 ComputeLineDirection(int Q, int QPrim) { vec4 Qp = gl_in[Q].gl_Position; - vec3 Qv = ProjectToScreen(ViewportMatrix, Qp); + vec3 Qv = ProjectToScreen(mat3(ViewportMatrix), Qp); vec4 QPrimp = gl_in[QPrim].gl_Position; return normalize ( Qv - - ProjectToScreen(ViewportMatrix, Qp + (QPrimp - Qp)) + ProjectToScreen(mat3(ViewportMatrix), Qp + (QPrimp - Qp)) ).xy; } @@ -149,8 +149,8 @@ void SetComplexCasePoints(int complexCase) gOut.IsSimpleWireframeCase = false; TriangleProjectionIndexes projectionIndices = ProjectionLookup[complexCase]; - gOut.A = ProjectToScreen(ViewportMatrix, gl_in[projectionIndices.A].gl_Position).xy; - gOut.B = ProjectToScreen(ViewportMatrix, gl_in[projectionIndices.B].gl_Position).xy; + gOut.A = ProjectToScreen(mat3(ViewportMatrix), gl_in[projectionIndices.A].gl_Position).xy; + gOut.B = ProjectToScreen(mat3(ViewportMatrix), gl_in[projectionIndices.B].gl_Position).xy; gOut.ADir = ComputeLineDirection(projectionIndices.A, projectionIndices.APrim); gOut.BDir = ComputeLineDirection(projectionIndices.B, projectionIndices.BPrim); @@ -181,7 +181,7 @@ void ComputeEdgeDistanceData() vec2 P[3]; for (int i = 0; i < 3; ++i) { - P[i] = ProjectToScreen(ViewportMatrix, gl_in[i].gl_Position).xy; + P[i] = ProjectToScreen(mat3(ViewportMatrix), gl_in[i].gl_Position).xy; } EdgeDistances = ComputeVertexHeights(P); From 9a281fc378252e69f201463e2b5020312198b4f2 Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sun, 5 Apr 2020 00:07:46 +0200 Subject: [PATCH 10/18] Fix input. --- Everlook/UI/MainWindow.cs | 7 +- .../Viewport/Rendering/Core/ShaderProgram.cs | 2 +- .../Shaders/Components/SolidWireframe.cs | 2 +- Everlook/Viewport/ViewportRenderer.cs | 88 +++++++++++++------ 4 files changed, 68 insertions(+), 31 deletions(-) diff --git a/Everlook/UI/MainWindow.cs b/Everlook/UI/MainWindow.cs index 110b50c..8ae9e82 100644 --- a/Everlook/UI/MainWindow.cs +++ b/Everlook/UI/MainWindow.cs @@ -151,7 +151,8 @@ ILogger log EventMask.EnterNotifyMask | EventMask.LeaveNotifyMask | EventMask.KeyPressMask | - EventMask.KeyReleaseMask; + EventMask.KeyReleaseMask | + EventMask.PointerMotionMask; _viewportWidget.Initialized += (sender, args) => { @@ -969,8 +970,8 @@ private void OnViewportButtonPressed(object o, ButtonPressEventArgs args) _viewportWidget.GrabFocus(); - _renderingEngine.InitialMouseX = args.Event.XRoot; - _renderingEngine.InitialMouseY = args.Event.YRoot; + _renderingEngine.InitialMouseX = args.Event.X; + _renderingEngine.InitialMouseY = args.Event.Y; _renderingEngine.WantsToMove = true; } diff --git a/Everlook/Viewport/Rendering/Core/ShaderProgram.cs b/Everlook/Viewport/Rendering/Core/ShaderProgram.cs index 4bda9ea..a9f16e8 100644 --- a/Everlook/Viewport/Rendering/Core/ShaderProgram.cs +++ b/Everlook/Viewport/Rendering/Core/ShaderProgram.cs @@ -122,7 +122,7 @@ protected void SetMatrix(Matrix4x4 matrix, string uniformName, bool shouldTransp var variableHandle = this.GL.GetUniformLocation(this.NativeShaderProgramID, uniformName); unsafe { - this.GL.UniformMatrix4(variableHandle, 4 * 4, shouldTranspose, &matrix.M11); + this.GL.UniformMatrix4(variableHandle, 1, shouldTranspose, &matrix.M11); } } diff --git a/Everlook/Viewport/Rendering/Shaders/Components/SolidWireframe.cs b/Everlook/Viewport/Rendering/Shaders/Components/SolidWireframe.cs index f30351a..412fb43 100644 --- a/Everlook/Viewport/Rendering/Shaders/Components/SolidWireframe.cs +++ b/Everlook/Viewport/Rendering/Shaders/Components/SolidWireframe.cs @@ -163,7 +163,7 @@ public void SetViewportMatrix(Matrix4x4 viewportMatrix) var viewportMatrixLoc = this.GL.GetUniformLocation(_parentShaderNativeID, ViewportMatrix); unsafe { - this.GL.UniformMatrix4(viewportMatrixLoc, 4 * 4, false, &viewportMatrix.M11); + this.GL.UniformMatrix4(viewportMatrixLoc, 1, false, &viewportMatrix.M11); } } } diff --git a/Everlook/Viewport/ViewportRenderer.cs b/Everlook/Viewport/ViewportRenderer.cs index 445ef73..90f397d 100644 --- a/Everlook/Viewport/ViewportRenderer.cs +++ b/Everlook/Viewport/ViewportRenderer.cs @@ -105,15 +105,29 @@ RenderTarget and related control flow data. public bool WantsToMove { get; set; } /// - /// Gets or sets the X position of the mouse during the last frame, relative to the . + /// Gets or sets the X position of the mouse during the last frame, relative to the + /// . /// public double InitialMouseX { get; set; } /// - /// Gets or sets the Y position of the mouse during the last frame, relative to the . + /// Gets or sets the Y position of the mouse during the last frame, relative to the + /// . /// public double InitialMouseY { get; set; } + /// + /// Gets or sets the Y position of the mouse at the last event time, relative to the + /// . + /// + public double CurrentMouseX { get; set; } + + /// + /// Gets or sets the Y position of the mouse at the last event time, relative to the + /// . + /// + public double CurrentMouseY { get; set; } + /* Runtime transitional OpenGL data. */ @@ -161,6 +175,22 @@ public ViewportRenderer(GL gl, RenderCache renderCache, ViewportArea viewportWid _movement = new CameraMovement(_camera); _renderCache = renderCache; + _viewportWidget.MotionNotifyEvent += (o, args) => + { + if (!this.WantsToMove) + { + return; + } + + if (!this.HasRenderTarget || this.RenderTarget is null) + { + return; + } + + this.CurrentMouseX = args.Event.X; + this.CurrentMouseY = args.Event.Y; + }; + _viewportWidget.KeyPressEvent += (o, args) => { switch (args.Event.Key) @@ -171,31 +201,37 @@ public ViewportRenderer(GL gl, RenderCache renderCache, ViewportArea viewportWid break; } case Key.W: + case Key.w: { _movement.WantsToMoveForward = true; break; } case Key.S: + case Key.s: { _movement.WantsToMoveBackward = true; break; } case Key.A: + case Key.a: { _movement.WantsToMoveLeft = true; break; } case Key.D: + case Key.d: { _movement.WantsToMoveRight = true; break; } case Key.Q: + case Key.q: { _movement.WantsToMoveUp = true; break; } case Key.E: + case Key.e: { _movement.WantsToMoveDown = true; break; @@ -213,31 +249,37 @@ public ViewportRenderer(GL gl, RenderCache renderCache, ViewportArea viewportWid break; } case Key.W: + case Key.w: { _movement.WantsToMoveForward = false; break; } case Key.S: + case Key.s: { _movement.WantsToMoveBackward = false; break; } case Key.A: + case Key.a: { _movement.WantsToMoveLeft = false; break; } case Key.D: + case Key.d: { _movement.WantsToMoveRight = false; break; } case Key.Q: + case Key.q: { _movement.WantsToMoveUp = false; break; } case Key.E: + case Key.e: { _movement.WantsToMoveDown = false; break; @@ -376,7 +418,7 @@ public void RenderFrame() return; } - // Calculate the current relative movement of the camera + // Update camera orientation if (this.WantsToMove) { switch (this.RenderTarget.Projection) @@ -421,22 +463,14 @@ public void RenderFrame() /// private void Calculate2DMovement() { - var mouse = Display.Default.ListDevices().FirstOrDefault(d => d.HasCursor); - if (mouse is null) - { - return; - } - - mouse.GetPosition(Screen.Default, out var mouseX, out var mouseY); - - var deltaMouseX = this.InitialMouseX - mouseX; - var deltaMouseY = this.InitialMouseY - mouseY; + var deltaMouseX = this.InitialMouseX - this.CurrentMouseX; + var deltaMouseY = this.InitialMouseY - this.CurrentMouseY; _movement.Calculate2DMovement(deltaMouseX, deltaMouseY, this.DeltaTime); // Update the initial location for the next frame - this.InitialMouseX = mouseX; - this.InitialMouseY = mouseY; + this.InitialMouseX = this.CurrentMouseX; + this.InitialMouseY = this.CurrentMouseY; } /// @@ -444,21 +478,23 @@ private void Calculate2DMovement() /// private void Calculate3DMovement() { - var mouse = Display.Default.ListDevices().FirstOrDefault(d => d.HasCursor); - if (mouse is null) - { - return; - } - - mouse.GetPosition(Screen.Default, out var mouseX, out var mouseY); - - var deltaMouseX = this.InitialMouseX - mouseX; - var deltaMouseY = this.InitialMouseY - mouseY; + var deltaMouseX = this.InitialMouseX - this.CurrentMouseX; + var deltaMouseY = this.InitialMouseY - this.CurrentMouseY; _movement.Calculate3DMovement(deltaMouseX, deltaMouseY, this.DeltaTime); // Return the mouse to its original position - mouse.Warp(Screen.Default, (int)this.InitialMouseX, (int)this.InitialMouseY); + /*motionEvent.Device.Warp + ( + motionEvent.Window.Screen, + (int)(motionEvent.XRoot - deltaMouseX), + (int)(motionEvent.YRoot - deltaMouseY) + ); + */ + + // Update the initial location for the next frame + this.InitialMouseX = this.CurrentMouseX; + this.InitialMouseY = this.CurrentMouseY; } /// From 386ba50567b7d7b15544c0a325ffe0cb7eaa2fe1 Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sun, 5 Apr 2020 11:50:19 +0200 Subject: [PATCH 11/18] Move builtin icon bindings to a dictionary instead of a case statement. --- Everlook.sln.DotSettings | 1 + Everlook/Utility/IconManager.cs | 222 ++++++++------------------ Everlook/Viewport/ViewportRenderer.cs | 1 - 3 files changed, 70 insertions(+), 154 deletions(-) diff --git a/Everlook.sln.DotSettings b/Everlook.sln.DotSettings index 201d43b..b13cd2c 100644 --- a/Everlook.sln.DotSettings +++ b/Everlook.sln.DotSettings @@ -84,6 +84,7 @@ True True True + True True True True diff --git a/Everlook/Utility/IconManager.cs b/Everlook/Utility/IconManager.cs index 57af111..f7528b5 100644 --- a/Everlook/Utility/IconManager.cs +++ b/Everlook/Utility/IconManager.cs @@ -46,6 +46,51 @@ public static class IconManager private static readonly Dictionary<(string IconName, int IconSize), Pixbuf> IconCache = new Dictionary<(string IconName, int IconSize), Pixbuf>(); + private static readonly Dictionary KnownIconTypes = new Dictionary + { + { WarcraftFileType.Directory, Stock.Directory }, + { WarcraftFileType.MoPaQArchive, "package-x-generic" }, + { WarcraftFileType.TerrainTable, "x-office-spreadsheet" }, + { WarcraftFileType.DatabaseContainer, "x-office-spreadsheet" }, + { WarcraftFileType.Hashmap, "x-office-spreadsheet" }, + { WarcraftFileType.TerrainWater, "Blender-Wave-Icon" }, + { WarcraftFileType.TerrainLiquid, "Blender-Wave-Icon" }, + { WarcraftFileType.TerrainLevel, "text-x-generic-template" }, + { WarcraftFileType.TerrainData, "Blender-Planet-Icon" }, + { WarcraftFileType.GameObjectModel, "Blender-Armature-Icon" }, + { WarcraftFileType.WorldObjectModel, "Blender-Object-Icon" }, + { WarcraftFileType.WorldObjectModelGroup, "Blender-Object-Icon" }, + { WarcraftFileType.WaveAudio, "audio-x-generic" }, + { WarcraftFileType.MP3Audio, "audio-x-generic" }, + { WarcraftFileType.VorbisAudio, "audio-x-generic" }, + { WarcraftFileType.WMAAudio, "audio-x-generic" }, + { WarcraftFileType.Subtitles, "gnome-subtitles" }, + { WarcraftFileType.Text, "text-x-generic" }, + { WarcraftFileType.AddonManifest, "text-x-generic" }, + { WarcraftFileType.AddonManifestSignature, "text-x-generic" }, + { WarcraftFileType.GIFImage, "image-gif" }, + { WarcraftFileType.PNGImage, "image-png" }, + { WarcraftFileType.JPGImage, "image-jpeg" }, + { WarcraftFileType.IconImage, "image-x-ico" }, + { WarcraftFileType.BitmapImage, "image-bmp" }, + { WarcraftFileType.BinaryImage, "image-x-generic" }, + { WarcraftFileType.TargaImage, "image-x-generic" }, + { WarcraftFileType.PDF, "application-pdf" }, + { WarcraftFileType.Web, "text-html" }, + { WarcraftFileType.Assembly, "application-x-executable" }, + { WarcraftFileType.Font, "font-x-generic" }, + { WarcraftFileType.Animation, "Blender-JumpingToon-Icon" }, + { WarcraftFileType.Physics, "Blender-Deform-Icon" }, + { WarcraftFileType.Skeleton, "Blender-Skeleton-Icon" }, + { WarcraftFileType.DataCache, "text-x-sql" }, + { WarcraftFileType.INI, "utilities-terminal" }, + { WarcraftFileType.ConfigurationFile, "utilities-terminal" }, + { WarcraftFileType.Script, "utilities-terminal" }, + { WarcraftFileType.Lighting, "Blender-Sun-Icon" }, + { WarcraftFileType.Shader, "Blender-Shader-Icon" }, + { WarcraftFileType.XML, "text-xml" } + }; + /// /// Loads all embedded builtin icons into the application's icon theme. /// @@ -96,27 +141,23 @@ public static void LoadEmbeddedIcons() /// A pixel buffer containing the image. private static Pixbuf? LoadEmbeddedImage(string resourceName, int width = 16, int height = 16) { - using (var vectorStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) + using var vectorStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName); + if (vectorStream == null) { - if (vectorStream == null) - { - return null; - } + return null; + } - using (var ms = new MemoryStream()) - { - vectorStream.CopyTo(ms); + using var ms = new MemoryStream(); + vectorStream.CopyTo(ms); - try - { - return new Pixbuf(ms.ToArray(), width, height); - } - catch (GException gex) - { - Log.Error($"Failed to load resource \"{resourceName}\" due to a GException: {gex}"); - return null; - } - } + try + { + return new Pixbuf(ms.ToArray(), width, height); + } + catch (GException gex) + { + Log.Error($"Failed to load resource \"{resourceName}\" due to a GException: {gex}"); + return null; } } @@ -134,8 +175,12 @@ public static Pixbuf GetIcon(string iconName) } catch (GException gex) { - Log.Warn($"Loading of icon \"{iconName}\" failed. Exception message: {gex.Message}\n" + - $"A fallback icon will be used instead."); + Log.Warn + ( + $"Loading of icon \"{iconName}\" failed. Exception message: {gex.Message}\n" + + $"A fallback icon will be used instead." + ); + return LoadIconPixbuf("empty"); } } @@ -159,141 +204,12 @@ public static Pixbuf GetIconForFiletype(string file) /// The file type. public static Pixbuf GetIconForFiletype(WarcraftFileType fileType) { - switch (fileType) + if (KnownIconTypes.TryGetValue(fileType, out var result)) { - case WarcraftFileType.Directory: - { - return GetIcon(Stock.Directory); - } - case WarcraftFileType.MoPaQArchive: - { - return GetIcon("package-x-generic"); - } - case WarcraftFileType.TerrainTable: - case WarcraftFileType.DatabaseContainer: - case WarcraftFileType.Hashmap: - { - return GetIcon("x-office-spreadsheet"); - } - case WarcraftFileType.TerrainWater: - case WarcraftFileType.TerrainLiquid: - { - return GetIcon("Blender-Wave-Icon"); - } - case WarcraftFileType.TerrainLevel: - { - return GetIcon("text-x-generic-template"); - } - case WarcraftFileType.TerrainData: - { - return GetIcon("Blender-Planet-Icon"); - } - case WarcraftFileType.GameObjectModel: - { - return GetIcon("Blender-Armature-Icon"); - } - case WarcraftFileType.WorldObjectModel: - case WarcraftFileType.WorldObjectModelGroup: - { - return GetIcon("Blender-Object-Icon"); - } - case WarcraftFileType.WaveAudio: - case WarcraftFileType.MP3Audio: - case WarcraftFileType.VorbisAudio: - case WarcraftFileType.WMAAudio: - { - return GetIcon("audio-x-generic"); - } - case WarcraftFileType.Subtitles: - { - return GetIcon("gnome-subtitles"); - } - case WarcraftFileType.Text: - case WarcraftFileType.AddonManifest: - case WarcraftFileType.AddonManifestSignature: - { - return GetIcon("text-x-generic"); - } - case WarcraftFileType.GIFImage: - { - return GetIcon("image-gif"); - } - case WarcraftFileType.PNGImage: - { - return GetIcon("image-png"); - } - case WarcraftFileType.JPGImage: - { - return GetIcon("image-jpeg"); - } - case WarcraftFileType.IconImage: - { - return GetIcon("image-x-ico"); - } - case WarcraftFileType.BitmapImage: - { - return GetIcon("image-bmp"); - } - case WarcraftFileType.BinaryImage: - case WarcraftFileType.TargaImage: - { - return GetIcon("image-x-generic"); - } - case WarcraftFileType.PDF: - { - return GetIcon("application-pdf"); - } - case WarcraftFileType.Web: - { - return GetIcon("text-html"); - } - case WarcraftFileType.Assembly: - { - return GetIcon("application-x-executable"); - } - case WarcraftFileType.Font: - { - return GetIcon("font-x-generic"); - } - case WarcraftFileType.Animation: - { - return GetIcon("Blender-JumpingToon-Icon"); - } - case WarcraftFileType.Physics: - { - return GetIcon("Blender-Deform-Icon"); - } - case WarcraftFileType.Skeleton: - { - return GetIcon("Blender-Skeleton-Icon"); - } - case WarcraftFileType.DataCache: - { - return GetIcon("text-x-sql"); - } - case WarcraftFileType.INI: - case WarcraftFileType.ConfigurationFile: - case WarcraftFileType.Script: - { - return GetIcon("utilities-terminal"); - } - case WarcraftFileType.Lighting: - { - return GetIcon("Blender-Sun-Icon"); - } - case WarcraftFileType.Shader: - { - return GetIcon("Blender-Shader-Icon"); - } - case WarcraftFileType.XML: - { - return GetIcon("text-xml"); - } - default: - { - return GetIcon(Stock.File); - } + return GetIcon(result); } + + return GetIcon(Stock.File); } /// diff --git a/Everlook/Viewport/ViewportRenderer.cs b/Everlook/Viewport/ViewportRenderer.cs index 90f397d..ad0ddb6 100644 --- a/Everlook/Viewport/ViewportRenderer.cs +++ b/Everlook/Viewport/ViewportRenderer.cs @@ -22,7 +22,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Runtime.InteropServices; using Everlook.Configuration; using Everlook.UI.Widgets; From 418a4ad2601cf744d4f239eebaa33e45778e6fa5 Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sun, 5 Apr 2020 11:52:19 +0200 Subject: [PATCH 12/18] Use "is null" instead of == null. --- Everlook/Audio/AudioManager.cs | 2 +- Everlook/Audio/AudioSource.cs | 4 ++-- Everlook/Audio/MP3/MP3AudioAsset.cs | 2 +- Everlook/Audio/Wave/WaveAudioAsset.cs | 2 +- Everlook/Explorer/FileTreeModel.cs | 20 +++++++++---------- Everlook/Explorer/GameLoader.cs | 2 +- Everlook/Explorer/GamePage.cs | 20 +++++++++---------- Everlook/Package/PackageGroup.cs | 4 ++-- Everlook/UI/EverlookGameLoadingDialog.cs | 2 +- Everlook/UI/Helpers/CellRenderers.cs | 6 +++--- Everlook/UI/MainWindow.cs | 4 ++-- Everlook/Utility/DataLoadingRoutines.cs | 14 ++++++------- Everlook/Utility/ExtensionMethods.cs | 4 ++-- Everlook/Utility/IconManager.cs | 2 +- Everlook/Utility/ResourceManager.cs | 4 ++-- .../Utility/StringReferenceListComparer.cs | 4 ++-- Everlook/Utility/WarcraftGameContext.cs | 8 ++++---- Everlook/Viewport/Rendering/Core/Buffer.cs | 4 ++-- .../Core/RenderableActorReference.cs | 4 ++-- .../Viewport/Rendering/Core/ShaderProgram.cs | 2 +- Everlook/Viewport/Rendering/Core/Texture2D.cs | 4 ++-- Everlook/Viewport/Rendering/RenderCache.cs | 2 +- .../Rendering/RenderableBoundingBox.cs | 2 +- .../Viewport/Rendering/RenderableGameModel.cs | 4 ++-- .../Rendering/RenderableWorldModel.cs | 4 ++-- .../Shaders/GLSLExtended/GLSLPreprocessor.cs | 2 +- .../Rendering/Shaders/GameModelShader.cs | 2 +- .../Rendering/Shaders/WorldModelShader.cs | 2 +- Everlook/Viewport/ViewportRenderer.cs | 2 +- 29 files changed, 69 insertions(+), 69 deletions(-) diff --git a/Everlook/Audio/AudioManager.cs b/Everlook/Audio/AudioManager.cs index e8715fa..146b171 100644 --- a/Everlook/Audio/AudioManager.cs +++ b/Everlook/Audio/AudioManager.cs @@ -79,7 +79,7 @@ public static void RegisterSource(AudioSource audioSource) /// The audio source to unregister. public static void UnregisterSource(AudioSource audioSource) { - if (audioSource == null) + if (audioSource is null) { return; } diff --git a/Everlook/Audio/AudioSource.cs b/Everlook/Audio/AudioSource.cs index e55ee31..3d9bb6c 100644 --- a/Everlook/Audio/AudioSource.cs +++ b/Everlook/Audio/AudioSource.cs @@ -314,7 +314,7 @@ public static AudioSource CreateNew() /// An AudioSource. public static AudioSource CreateFromSoundEntry(SoundEntriesRecord soundEntry) { - if (soundEntry == null) + if (soundEntry is null) { throw new ArgumentNullException(nameof(soundEntry)); } @@ -369,7 +369,7 @@ public void Stop() /// An asynchronous task. public async Task SetAudioAsync(FileReference fileReference) { - if (fileReference == null) + if (fileReference is null) { throw new ArgumentNullException(nameof(fileReference)); } diff --git a/Everlook/Audio/MP3/MP3AudioAsset.cs b/Everlook/Audio/MP3/MP3AudioAsset.cs index 61d0ea0..3412506 100644 --- a/Everlook/Audio/MP3/MP3AudioAsset.cs +++ b/Everlook/Audio/MP3/MP3AudioAsset.cs @@ -111,7 +111,7 @@ public byte[] PCMData /// Thrown if the file data can't be extracted. public MP3AudioAsset(FileReference fileReference) { - if (fileReference == null) + if (fileReference is null) { throw new ArgumentNullException(nameof(fileReference)); } diff --git a/Everlook/Audio/Wave/WaveAudioAsset.cs b/Everlook/Audio/Wave/WaveAudioAsset.cs index 6b8dbdf..bcec2af 100644 --- a/Everlook/Audio/Wave/WaveAudioAsset.cs +++ b/Everlook/Audio/Wave/WaveAudioAsset.cs @@ -111,7 +111,7 @@ public byte[] PCMData /// Thrown if the file data can't be extracted. public WaveAudioAsset(FileReference fileReference) { - if (fileReference == null) + if (fileReference is null) { throw new ArgumentNullException(nameof(fileReference)); } diff --git a/Everlook/Explorer/FileTreeModel.cs b/Everlook/Explorer/FileTreeModel.cs index 585f524..f6af209 100644 --- a/Everlook/Explorer/FileTreeModel.cs +++ b/Everlook/Explorer/FileTreeModel.cs @@ -127,7 +127,7 @@ public string GetNodeFilePath(SerializedNode node) /// A set of all the child references of the given reference. public IEnumerable EnumerateFilesOfReference(FileReference fileReference) { - if (fileReference == null) + if (fileReference is null) { yield break; } @@ -184,7 +184,7 @@ public FileReference GetReferenceByIter(IGameContext gameContext, TreeIter iter) } var node = _tree.GetNode((ulong)iter.UserData); - if (node == null) + if (node is null) { throw new InvalidDataException("The iter did not contain a valid node offset."); } @@ -312,7 +312,7 @@ public TreePath GetPath(TreeIter iter) var result = new TreePath(); var node = _tree.GetNode((ulong)iter.UserData); - if (node == null) + if (node is null) { return result; } @@ -345,7 +345,7 @@ public void GetValue(TreeIter iter, int column, ref Value value) } var node = iter.Equals(TreeIter.Zero) ? _tree.Root : _tree.GetNode((ulong)iter.UserData); - if (node == null) + if (node is null) { return; } @@ -431,7 +431,7 @@ public bool IterChildren(out TreeIter iter, TreeIter parent) iter = TreeIter.Zero; var node = parent.Equals(TreeIter.Zero) ? _tree.Root : _tree.GetNode((ulong)parent.UserData); - if (node == null) + if (node is null) { throw new ArgumentException("The given iter was not valid.", nameof(parent)); } @@ -461,7 +461,7 @@ public bool IterHasChild(TreeIter iter) } var node = iter.Equals(TreeIter.Zero) ? _tree.Root : _tree.GetNode((ulong)iter.UserData); - if (node == null) + if (node is null) { throw new ArgumentException("The given iter was not valid.", nameof(iter)); } @@ -489,7 +489,7 @@ public int IterNChildren(TreeIter iter) } var node = _tree.GetNode((ulong)iter.UserData); - if (node == null) + if (node is null) { throw new ArgumentException("The given iter was not valid.", nameof(iter)); } @@ -522,7 +522,7 @@ public bool IterNthChild(out TreeIter iter, TreeIter parent, int n) var node = iter.Equals(TreeIter.Zero) ? _tree.Root : _tree.GetNode((ulong)iter.UserData); - if (node == null) + if (node is null) { throw new ArgumentException("The given iter was not valid.", nameof(parent)); } @@ -555,13 +555,13 @@ public bool IterParent(out TreeIter iter, TreeIter child) iter = TreeIter.Zero; var childNode = _tree.GetNode((ulong)child.UserData); - if (childNode == null) + if (childNode is null) { throw new ArgumentException("The given iter was not valid.", nameof(child)); } var parentNode = _tree.GetNode((ulong)childNode.ParentOffset); - if (parentNode == null) + if (parentNode is null) { return false; } diff --git a/Everlook/Explorer/GameLoader.cs b/Everlook/Explorer/GameLoader.cs index a1576b8..26da41e 100644 --- a/Everlook/Explorer/GameLoader.cs +++ b/Everlook/Explorer/GameLoader.cs @@ -182,7 +182,7 @@ private static Task LoadDictionaryAsync(CancellationToken ct } // Load dictionary if neccesary - if (_dictionary == null) + if (_dictionary is null) { progress?.Report(new GameLoadingProgress { diff --git a/Everlook/Explorer/GamePage.cs b/Everlook/Explorer/GamePage.cs index 056fcb9..debc7da 100644 --- a/Everlook/Explorer/GamePage.cs +++ b/Everlook/Explorer/GamePage.cs @@ -337,7 +337,7 @@ private void RenderNodeIcon(TreeViewColumn column, CellRenderer cell, ITreeModel var cellIcon = cell as CellRendererPixbuf; var node = (SerializedNode)model.GetValue(iter, 0); - if (node == null || cellIcon == null) + if (node is null || cellIcon is null) { return; } @@ -381,7 +381,7 @@ private void RenderNodeName(TreeViewColumn column, CellRenderer cell, ITreeModel var cellText = cell as CellRendererText; var node = (SerializedNode)model.GetValue(iter, 0); - if (node == null || cellText == null) + if (node is null || cellText is null) { return; } @@ -408,7 +408,7 @@ private void RenderNodeName(TreeViewColumn column, CellRenderer cell, ITreeModel private void OnQueueForExportRequested(object? sender, EventArgs eventArgs) { var fileReference = GetSelectedReference(); - if (fileReference == null) + if (fileReference is null) { return; } @@ -424,7 +424,7 @@ private void OnQueueForExportRequested(object? sender, EventArgs eventArgs) private void OnExportItemRequested(object? sender, EventArgs eventArgs) { var fileReference = GetSelectedReference(); - if (fileReference == null) + if (fileReference is null) { return; } @@ -442,7 +442,7 @@ private void OnExportItemRequested(object? sender, EventArgs eventArgs) private void OnOpenItem(object? sender, EventArgs eventArgs) { var fileReference = GetSelectedReference(); - if (fileReference == null) + if (fileReference is null) { return; } @@ -468,7 +468,7 @@ private void OnOpenItem(object? sender, EventArgs eventArgs) private void OnCopyPath(object? sender, EventArgs eventArgs) { var fileReference = GetSelectedReference(); - if (fileReference == null) + if (fileReference is null) { return; } @@ -486,7 +486,7 @@ private void OnCopyPath(object? sender, EventArgs eventArgs) private void OnSaveItem(object? sender, EventArgs eventArgs) { var fileReference = GetSelectedReference(); - if (fileReference == null) + if (fileReference is null) { return; } @@ -525,7 +525,7 @@ private void OnButtonPressed(object o, ButtonPressEventArgs args) var filterPath = _treeSorter.ConvertPathToChildPath(sorterPath); var modelPath = _treeFilter.ConvertPathToChildPath(filterPath); - if (modelPath == null) + if (modelPath is null) { _saveItem.Sensitive = false; _exportItem.Sensitive = false; @@ -566,7 +566,7 @@ private void OnButtonPressed(object o, ButtonPressEventArgs args) private void OnSelectionChanged(object? sender, EventArgs eventArgs) { var fileReference = GetSelectedReference(); - if (fileReference == null) + if (fileReference is null) { return; } @@ -585,7 +585,7 @@ private void OnSelectionChanged(object? sender, EventArgs eventArgs) private void OnRowActivated(object o, RowActivatedArgs args) { var fileReference = GetSelectedReference(); - if (fileReference == null) + if (fileReference is null) { return; } diff --git a/Everlook/Package/PackageGroup.cs b/Everlook/Package/PackageGroup.cs index 0a3d351..cf72bf3 100644 --- a/Everlook/Package/PackageGroup.cs +++ b/Everlook/Package/PackageGroup.cs @@ -193,7 +193,7 @@ public void LoadPackagesFromPath(string path) /// Thrown if the package is null. public void AddPackage(PackageInteractionHandler package) { - if (package == null) + if (package is null) { throw new ArgumentNullException(nameof(package)); } @@ -277,7 +277,7 @@ public bool TryExtractReference(FileReference fileReference, [NotNullWhen(true)] /// Reference reference. public bool ContainsReference(FileReference fileReference) { - if (fileReference == null) + if (fileReference is null) { throw new ArgumentNullException(nameof(fileReference)); } diff --git a/Everlook/UI/EverlookGameLoadingDialog.cs b/Everlook/UI/EverlookGameLoadingDialog.cs index 252c9ca..a8bfd6f 100644 --- a/Everlook/UI/EverlookGameLoadingDialog.cs +++ b/Everlook/UI/EverlookGameLoadingDialog.cs @@ -161,7 +161,7 @@ private EverlookGameLoadingDialog(Builder builder, IntPtr handle, Window parent) using (var shaderStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Everlook.Content.jokes.txt")) { - if (shaderStream == null) + if (shaderStream is null) { return; } diff --git a/Everlook/UI/Helpers/CellRenderers.cs b/Everlook/UI/Helpers/CellRenderers.cs index 4f350bc..657eac6 100644 --- a/Everlook/UI/Helpers/CellRenderers.cs +++ b/Everlook/UI/Helpers/CellRenderers.cs @@ -52,7 +52,7 @@ TreeIter iter ) { var cellText = cell as CellRendererText; - if (cellText == null) + if (cellText is null) { return; } @@ -97,7 +97,7 @@ TreeIter iter var cellText = cell as CellRendererText; var reference = (FileReference)model.GetValue(iter, 0); - if (reference == null || cellText == null) + if (reference is null || cellText is null) { return; } @@ -123,7 +123,7 @@ TreeIter iter var cellIcon = cell as CellRendererPixbuf; var reference = (FileReference)model.GetValue(iter, 0); - if (reference == null || cellIcon == null) + if (reference is null || cellIcon is null) { return; } diff --git a/Everlook/UI/MainWindow.cs b/Everlook/UI/MainWindow.cs index 8ae9e82..555ea5e 100644 --- a/Everlook/UI/MainWindow.cs +++ b/Everlook/UI/MainWindow.cs @@ -847,7 +847,7 @@ private async Task DisplayRenderableFile CancellationToken ct ) { - if (fileReference == null) + if (fileReference is null) { throw new ArgumentNullException(nameof(fileReference)); } @@ -1331,7 +1331,7 @@ private void OnExportQueueButtonPressed(object? sender, ButtonPressEventArgs e) _exportQueueTreeView.GetPathAtPos((int)e.Event.X, (int)e.Event.Y, out var path); - if (path == null) + if (path is null) { return; } diff --git a/Everlook/Utility/DataLoadingRoutines.cs b/Everlook/Utility/DataLoadingRoutines.cs index 19501ae..a6fe76c 100644 --- a/Everlook/Utility/DataLoadingRoutines.cs +++ b/Everlook/Utility/DataLoadingRoutines.cs @@ -58,7 +58,7 @@ public static class DataLoadingRoutines /// A WMO object. public static WMO LoadWorldModel(FileReference fileReference) { - if (fileReference == null) + if (fileReference is null) { throw new ArgumentNullException(nameof(fileReference)); } @@ -116,7 +116,7 @@ public static WMO LoadWorldModel(FileReference fileReference) /// A WMO object, containing just the specified model group. public static WMO LoadWorldModelGroup(FileReference fileReference) { - if (fileReference == null) + if (fileReference is null) { throw new ArgumentNullException(nameof(fileReference)); } @@ -179,7 +179,7 @@ FileReference fileReference ) { var warcraftContext = fileReference.Context as WarcraftGameContext; - if (warcraftContext == null) + if (warcraftContext is null) { // TODO: This is bad practice. Refactor throw new ArgumentException @@ -201,7 +201,7 @@ FileReference fileReference /// A BLP object containing the image data pointed to by the reference. public static BLP LoadBinaryImage(FileReference fileReference) { - if (fileReference == null) + if (fileReference is null) { throw new ArgumentNullException(nameof(fileReference)); } @@ -269,7 +269,7 @@ FileReference fileReference /// A bitmap containing the image data pointed to by the reference. public static Bitmap LoadBitmapImage(FileReference fileReference) { - if (fileReference == null) + if (fileReference is null) { throw new ArgumentNullException(nameof(fileReference)); } @@ -329,7 +329,7 @@ FileReference fileReference /// An object containing the model data pointed to by the reference. public static MDX LoadGameModel(FileReference fileReference) { - if (fileReference == null) + if (fileReference is null) { throw new ArgumentNullException(nameof(fileReference)); } @@ -412,7 +412,7 @@ FileReference fileReference ) { var warcraftContext = fileReference.Context as WarcraftGameContext; - if (warcraftContext == null) + if (warcraftContext is null) { // TODO: This is bad practice. Refactor throw new ArgumentException diff --git a/Everlook/Utility/ExtensionMethods.cs b/Everlook/Utility/ExtensionMethods.cs index 8c28941..c4f2bcb 100644 --- a/Everlook/Utility/ExtensionMethods.cs +++ b/Everlook/Utility/ExtensionMethods.cs @@ -40,7 +40,7 @@ public static class ExtensionMethods /// The notebook to clear the pages from. public static void ClearPages(this Gtk.Notebook notebook) { - if (notebook == null) + if (notebook is null) { throw new ArgumentNullException(nameof(notebook)); } @@ -89,7 +89,7 @@ public static bool IsRunningOnUnix() /// A pixel buffer containg the icon. public static Pixbuf GetIcon(this FileReference fileReference) { - if (fileReference == null) + if (fileReference is null) { throw new ArgumentNullException(nameof(fileReference)); } diff --git a/Everlook/Utility/IconManager.cs b/Everlook/Utility/IconManager.cs index f7528b5..5a9fc6d 100644 --- a/Everlook/Utility/IconManager.cs +++ b/Everlook/Utility/IconManager.cs @@ -142,7 +142,7 @@ public static void LoadEmbeddedIcons() private static Pixbuf? LoadEmbeddedImage(string resourceName, int width = 16, int height = 16) { using var vectorStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName); - if (vectorStream == null) + if (vectorStream is null) { return null; } diff --git a/Everlook/Utility/ResourceManager.cs b/Everlook/Utility/ResourceManager.cs index 7026572..bad0607 100644 --- a/Everlook/Utility/ResourceManager.cs +++ b/Everlook/Utility/ResourceManager.cs @@ -41,7 +41,7 @@ public static class ResourceManager string resourceString; using (var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourcePath)) { - if (resourceStream == null) + if (resourceStream is null) { return null; } @@ -67,7 +67,7 @@ public static class ResourceManager using (var imageStream = executingAssembly.GetManifestResourceStream(fallbackTextureName)) { - if (imageStream == null) + if (imageStream is null) { return null; } diff --git a/Everlook/Utility/StringReferenceListComparer.cs b/Everlook/Utility/StringReferenceListComparer.cs index 74d8283..26fc5d2 100644 --- a/Everlook/Utility/StringReferenceListComparer.cs +++ b/Everlook/Utility/StringReferenceListComparer.cs @@ -34,12 +34,12 @@ public class StringReferenceListComparer : IEqualityComparer public bool Equals(IReadOnlyList x, IReadOnlyList y) { - if (x == null && y == null) + if (x is null && y is null) { return true; } - if (x == null || y == null) + if (x is null || y is null) { return false; } diff --git a/Everlook/Utility/WarcraftGameContext.cs b/Everlook/Utility/WarcraftGameContext.cs index d2ec31d..d475d6f 100644 --- a/Everlook/Utility/WarcraftGameContext.cs +++ b/Everlook/Utility/WarcraftGameContext.cs @@ -56,12 +56,12 @@ public sealed class WarcraftGameContext : IGameContext /// Thrown if the assets or the file tree are null. public WarcraftGameContext(WarcraftVersion version, PackageGroup assets, FileTreeModel fileTree) { - if (assets == null) + if (assets is null) { throw new ArgumentNullException(nameof(assets)); } - if (fileTree == null) + if (fileTree is null) { throw new ArgumentNullException(nameof(fileTree)); } @@ -88,7 +88,7 @@ public FileReference GetReferenceForDoodad(DoodadInstance doodadInstance) // Doodads may have the *.mdx extension instead of *.m2. Try with that as well. doodadReference = GetReferenceForPath(Path.ChangeExtension(doodadInstance.Name, "m2")); - if (doodadReference == null) + if (doodadReference is null) { throw new ArgumentException ( @@ -109,7 +109,7 @@ public FileReference GetReferenceForDoodad(DoodadInstance doodadInstance) } var treePath = this.FileTree.GetPath(path); - if (treePath == null) + if (treePath is null) { return null; } diff --git a/Everlook/Viewport/Rendering/Core/Buffer.cs b/Everlook/Viewport/Rendering/Core/Buffer.cs index ba33905..c92a174 100644 --- a/Everlook/Viewport/Rendering/Core/Buffer.cs +++ b/Everlook/Viewport/Rendering/Core/Buffer.cs @@ -112,7 +112,7 @@ public Buffer(GL gl, BufferTargetARB target, BufferUsageARB usage) /// public void AttachAttributePointer(VertexAttributePointer attributePointer) { - if (attributePointer == null) + if (attributePointer is null) { throw new ArgumentNullException(nameof(attributePointer)); } @@ -124,7 +124,7 @@ public void AttachAttributePointer(VertexAttributePointer attributePointer) /// public void AttachAttributePointers(IEnumerable attributePointers) { - if (attributePointers == null) + if (attributePointers is null) { throw new ArgumentNullException(nameof(attributePointers)); } diff --git a/Everlook/Viewport/Rendering/Core/RenderableActorReference.cs b/Everlook/Viewport/Rendering/Core/RenderableActorReference.cs index 920dfc1..cc8b4f6 100644 --- a/Everlook/Viewport/Rendering/Core/RenderableActorReference.cs +++ b/Everlook/Viewport/Rendering/Core/RenderableActorReference.cs @@ -65,12 +65,12 @@ public RenderableActorReference(T target) /// The transform of the instance. public RenderableActorReference(T target, Transform transform) { - if (target == null) + if (target is null) { throw new ArgumentNullException(nameof(target)); } - if (transform == null) + if (transform is null) { throw new ArgumentNullException(nameof(transform)); } diff --git a/Everlook/Viewport/Rendering/Core/ShaderProgram.cs b/Everlook/Viewport/Rendering/Core/ShaderProgram.cs index a9f16e8..13ef11e 100644 --- a/Everlook/Viewport/Rendering/Core/ShaderProgram.cs +++ b/Everlook/Viewport/Rendering/Core/ShaderProgram.cs @@ -174,7 +174,7 @@ protected void SetFloat(float value, string uniformName) /// The texture to bind. public void BindTexture2D(TextureUnit textureUnit, TextureUniform uniform, Texture2D texture) { - if (texture == null) + if (texture is null) { throw new ArgumentNullException(nameof(texture)); } diff --git a/Everlook/Viewport/Rendering/Core/Texture2D.cs b/Everlook/Viewport/Rendering/Core/Texture2D.cs index d88ecbc..fea59f0 100644 --- a/Everlook/Viewport/Rendering/Core/Texture2D.cs +++ b/Everlook/Viewport/Rendering/Core/Texture2D.cs @@ -115,7 +115,7 @@ private Texture2D(GL gl) public Texture2D(GL gl, Bitmap imageData, TextureWrapMode wrapMode = TextureWrapMode.Repeat) : this(gl) { - if (imageData == null) + if (imageData is null) { throw new ArgumentNullException(nameof(imageData)); } @@ -177,7 +177,7 @@ public Texture2D ) : this(gl) { - if (imageData == null) + if (imageData is null) { throw new ArgumentNullException(nameof(imageData)); } diff --git a/Everlook/Viewport/Rendering/RenderCache.cs b/Everlook/Viewport/Rendering/RenderCache.cs index bf02cc9..d6d06d5 100644 --- a/Everlook/Viewport/Rendering/RenderCache.cs +++ b/Everlook/Viewport/Rendering/RenderCache.cs @@ -75,7 +75,7 @@ public Texture2D FallbackTexture { ThrowIfDisposed(); - if (_fallbackTextureInternal == null) + if (_fallbackTextureInternal is null) { var fallbackImage = ResourceManager.GetFallbackImage(); if (fallbackImage is null) diff --git a/Everlook/Viewport/Rendering/RenderableBoundingBox.cs b/Everlook/Viewport/Rendering/RenderableBoundingBox.cs index 54ef67e..85c0dfe 100644 --- a/Everlook/Viewport/Rendering/RenderableBoundingBox.cs +++ b/Everlook/Viewport/Rendering/RenderableBoundingBox.cs @@ -97,7 +97,7 @@ public void Initialize() return; } - if (_boxShader == null) + if (_boxShader is null) { throw new ShaderNullException(typeof(BoundingBoxShader)); } diff --git a/Everlook/Viewport/Rendering/RenderableGameModel.cs b/Everlook/Viewport/Rendering/RenderableGameModel.cs index b89db08..93eb8ad 100644 --- a/Everlook/Viewport/Rendering/RenderableGameModel.cs +++ b/Everlook/Viewport/Rendering/RenderableGameModel.cs @@ -192,7 +192,7 @@ public void Initialize() _shader = _renderCache.GetShader(EverlookShader.GameModel) as GameModelShader; - if (_shader == null) + if (_shader is null) { throw new ShaderNullException(typeof(GameModelShader)); } @@ -707,7 +707,7 @@ public void SetDisplayInfoByID(int variationID) /// The display info record to cache. private void CacheDisplayInfo(CreatureDisplayInfoRecord displayInfoRecord) { - if (displayInfoRecord == null) + if (displayInfoRecord is null) { throw new ArgumentNullException(nameof(displayInfoRecord)); } diff --git a/Everlook/Viewport/Rendering/RenderableWorldModel.cs b/Everlook/Viewport/Rendering/RenderableWorldModel.cs index 832853b..39bad76 100644 --- a/Everlook/Viewport/Rendering/RenderableWorldModel.cs +++ b/Everlook/Viewport/Rendering/RenderableWorldModel.cs @@ -206,7 +206,7 @@ public void Initialize() _shader = _renderCache.GetShader(EverlookShader.WorldModel) as WorldModelShader; - if (_shader == null) + if (_shader is null) { throw new ShaderNullException(typeof(WorldModelShader)); } @@ -295,7 +295,7 @@ public void LoadDoodads() var doodadReference = _gameContext.GetReferenceForDoodad(firstInstance); var doodadModel = DataLoadingRoutines.LoadGameModel(doodadReference); - if (doodadModel == null) + if (doodadModel is null) { Log.Warn($"Failed to load doodad \"{firstInstance.Name}\""); continue; diff --git a/Everlook/Viewport/Rendering/Shaders/GLSLExtended/GLSLPreprocessor.cs b/Everlook/Viewport/Rendering/Shaders/GLSLExtended/GLSLPreprocessor.cs index d9f5634..33921d3 100644 --- a/Everlook/Viewport/Rendering/Shaders/GLSLExtended/GLSLPreprocessor.cs +++ b/Everlook/Viewport/Rendering/Shaders/GLSLExtended/GLSLPreprocessor.cs @@ -57,7 +57,7 @@ public static string ProcessIncludes(string source, string baseResourceDirectory // Try loading it from the resource manifest var fileContents = Utility.ResourceManager.LoadStringResource($"{baseResourceDirectory}.{resourceName}"); - if (fileContents == null) + if (fileContents is null) { throw new FileNotFoundException ( diff --git a/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs b/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs index 776d1c6..cd551a8 100644 --- a/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs +++ b/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs @@ -178,7 +178,7 @@ public void BindTexture3(Texture2D texture) /// The material to use. public void SetMaterial(MDXMaterial modelMaterial) { - if (modelMaterial == null) + if (modelMaterial is null) { throw new ArgumentNullException(nameof(modelMaterial)); } diff --git a/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs b/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs index 131d717..f01fc7c 100644 --- a/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs +++ b/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs @@ -66,7 +66,7 @@ public WorldModelShader(GL gl) /// The material to use. public void SetMaterial(ModelMaterial modelMaterial) { - if (modelMaterial == null) + if (modelMaterial is null) { throw new ArgumentNullException(nameof(modelMaterial)); } diff --git a/Everlook/Viewport/ViewportRenderer.cs b/Everlook/Viewport/ViewportRenderer.cs index ad0ddb6..720b223 100644 --- a/Everlook/Viewport/ViewportRenderer.cs +++ b/Everlook/Viewport/ViewportRenderer.cs @@ -502,7 +502,7 @@ private void Calculate3DMovement() /// true if movement is disabled; false otherwise. public bool IsMovementDisabled() { - return this.RenderTarget == null || !this.RenderTarget.IsInitialized; + return this.RenderTarget is null || !this.RenderTarget.IsInitialized; } /// From b2e3642d8824cba154ba3e5477567089a59d3785 Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sun, 5 Apr 2020 11:54:58 +0200 Subject: [PATCH 13/18] Use "is null" instead of != null. --- Everlook/Audio/MP3/MP3AudioAsset.cs | 2 +- Everlook/Audio/Wave/WaveAudioAsset.cs | 2 +- Everlook/Explorer/FileReference.cs | 2 +- Everlook/UI/EverlookDirectoryExportDialog.cs | 2 +- Everlook/UI/MainWindow.cs | 4 ++-- Everlook/Utility/IconManager.cs | 2 +- Everlook/Utility/WarcraftGameContext.cs | 2 +- Everlook/Viewport/Rendering/RenderableGameModel.cs | 4 ++-- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Everlook/Audio/MP3/MP3AudioAsset.cs b/Everlook/Audio/MP3/MP3AudioAsset.cs index 3412506..880f134 100644 --- a/Everlook/Audio/MP3/MP3AudioAsset.cs +++ b/Everlook/Audio/MP3/MP3AudioAsset.cs @@ -72,7 +72,7 @@ public byte[] PCMData { ThrowIfDisposed(); - if (_pcmDataInternal != null) + if (!(_pcmDataInternal is null)) { return _pcmDataInternal; } diff --git a/Everlook/Audio/Wave/WaveAudioAsset.cs b/Everlook/Audio/Wave/WaveAudioAsset.cs index bcec2af..d8a2dfb 100644 --- a/Everlook/Audio/Wave/WaveAudioAsset.cs +++ b/Everlook/Audio/Wave/WaveAudioAsset.cs @@ -71,7 +71,7 @@ public byte[] PCMData { ThrowIfDisposed(); - if (_pcmDataInternal != null) + if (!(_pcmDataInternal is null)) { return _pcmDataInternal; } diff --git a/Everlook/Explorer/FileReference.cs b/Everlook/Explorer/FileReference.cs index f18feeb..e53b206 100644 --- a/Everlook/Explorer/FileReference.cs +++ b/Everlook/Explorer/FileReference.cs @@ -187,7 +187,7 @@ public override bool Equals(object? obj) /// public bool Equals(FileReference other) { - if (other != null) + if (!(other is null)) { return this.Context.Equals(other.Context) && diff --git a/Everlook/UI/EverlookDirectoryExportDialog.cs b/Everlook/UI/EverlookDirectoryExportDialog.cs index ad4d146..5e533fa 100644 --- a/Everlook/UI/EverlookDirectoryExportDialog.cs +++ b/Everlook/UI/EverlookDirectoryExportDialog.cs @@ -138,7 +138,7 @@ public void RunExport() Directory.CreateDirectory(Directory.GetParent(exportPath).FullName); byte[] fileData = referenceToExport.Extract(); - if (fileData != null) + if (!(fileData is null)) { File.WriteAllBytes(exportPath, fileData); } diff --git a/Everlook/UI/MainWindow.cs b/Everlook/UI/MainWindow.cs index 555ea5e..fbefc03 100644 --- a/Everlook/UI/MainWindow.cs +++ b/Everlook/UI/MainWindow.cs @@ -339,7 +339,7 @@ private void BindModelControlEvents() _modelVariationComboBox.GetActiveIter(out var activeIter); var variationObject = _modelVariationListStore.GetValue(activeIter, 1); - if (variationObject != null) + if (!(variationObject is null)) { var variationID = (int)variationObject; @@ -889,7 +889,7 @@ CancellationToken ct ct ); - if (renderable != null) + if (!(renderable is null)) { ct.ThrowIfCancellationRequested(); diff --git a/Everlook/Utility/IconManager.cs b/Everlook/Utility/IconManager.cs index 5a9fc6d..58f4ca4 100644 --- a/Everlook/Utility/IconManager.cs +++ b/Everlook/Utility/IconManager.cs @@ -125,7 +125,7 @@ public static void LoadEmbeddedIcons() var iconName = manifestNameParts.ElementAt(manifestNameParts.Length - 2); var iconBuffer = LoadEmbeddedImage(manifestIconName); - if (iconBuffer != null) + if (!(iconBuffer is null)) { IconTheme.AddBuiltinIcon(iconName, 16, iconBuffer); } diff --git a/Everlook/Utility/WarcraftGameContext.cs b/Everlook/Utility/WarcraftGameContext.cs index d475d6f..b7d6719 100644 --- a/Everlook/Utility/WarcraftGameContext.cs +++ b/Everlook/Utility/WarcraftGameContext.cs @@ -81,7 +81,7 @@ public WarcraftGameContext(WarcraftVersion version, PackageGroup assets, FileTre public FileReference GetReferenceForDoodad(DoodadInstance doodadInstance) { var doodadReference = GetReferenceForPath(doodadInstance.Name); - if (doodadReference != null) + if (!(doodadReference is null)) { return doodadReference; } diff --git a/Everlook/Viewport/Rendering/RenderableGameModel.cs b/Everlook/Viewport/Rendering/RenderableGameModel.cs index 93eb8ad..477d1ec 100644 --- a/Everlook/Viewport/Rendering/RenderableGameModel.cs +++ b/Everlook/Viewport/Rendering/RenderableGameModel.cs @@ -172,7 +172,7 @@ public RenderableGameModel(GL gl, RenderCache renderCache, MDX inModel, Warcraft // Set a default display info for this model var displayInfo = GetSkinVariations().FirstOrDefault(); - if (displayInfo != null) + if (!(displayInfo is null)) { this.CurrentDisplayInfo = displayInfo; } @@ -293,7 +293,7 @@ public void Initialize() } // Cache the default display info - if (this.CurrentDisplayInfo != null) + if (!(this.CurrentDisplayInfo is null)) { CacheDisplayInfo(this.CurrentDisplayInfo); } From 40fa7dd91c15558645e65f0e9df422ebd206c098 Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sun, 5 Apr 2020 12:02:40 +0200 Subject: [PATCH 14/18] Remove redundant null check code. --- Everlook/Audio/AudioSource.cs | 10 ---------- Everlook/Audio/MP3/MP3AudioAsset.cs | 5 ----- Everlook/Audio/Wave/WaveAudioAsset.cs | 5 ----- Everlook/Explorer/FileReference.cs | 12 ++++++------ Everlook/Explorer/FileTreeModel.cs | 5 ----- Everlook/Package/PackageGroup.cs | 7 +------ Everlook/Utility/DataLoadingRoutines.cs | 15 --------------- Everlook/Utility/ExtensionMethods.cs | 5 ----- Everlook/Utility/WarcraftGameContext.cs | 10 ---------- Everlook/Viewport/Rendering/Core/Buffer.cs | 10 ---------- .../Rendering/Core/RenderableActorReference.cs | 10 ---------- Everlook/Viewport/Rendering/Core/ShaderProgram.cs | 5 ----- Everlook/Viewport/Rendering/Core/Texture2D.cs | 5 ----- .../Viewport/Rendering/RenderableGameModel.cs | 5 ----- .../Viewport/Rendering/Shaders/GameModelShader.cs | 5 ----- .../Rendering/Shaders/WorldModelShader.cs | 5 ----- 16 files changed, 7 insertions(+), 112 deletions(-) diff --git a/Everlook/Audio/AudioSource.cs b/Everlook/Audio/AudioSource.cs index 3d9bb6c..bdce425 100644 --- a/Everlook/Audio/AudioSource.cs +++ b/Everlook/Audio/AudioSource.cs @@ -314,11 +314,6 @@ public static AudioSource CreateNew() /// An AudioSource. public static AudioSource CreateFromSoundEntry(SoundEntriesRecord soundEntry) { - if (soundEntry is null) - { - throw new ArgumentNullException(nameof(soundEntry)); - } - var source = CreateNew(); source.Attenuation = soundEntry.DistanceCutoff; @@ -369,11 +364,6 @@ public void Stop() /// An asynchronous task. public async Task SetAudioAsync(FileReference fileReference) { - if (fileReference is null) - { - throw new ArgumentNullException(nameof(fileReference)); - } - // First, clear the old audio ClearAudio(); diff --git a/Everlook/Audio/MP3/MP3AudioAsset.cs b/Everlook/Audio/MP3/MP3AudioAsset.cs index 880f134..c8d33b6 100644 --- a/Everlook/Audio/MP3/MP3AudioAsset.cs +++ b/Everlook/Audio/MP3/MP3AudioAsset.cs @@ -111,11 +111,6 @@ public byte[] PCMData /// Thrown if the file data can't be extracted. public MP3AudioAsset(FileReference fileReference) { - if (fileReference is null) - { - throw new ArgumentNullException(nameof(fileReference)); - } - if (fileReference.GetReferencedFileType() != WarcraftFileType.MP3Audio) { throw new ArgumentException diff --git a/Everlook/Audio/Wave/WaveAudioAsset.cs b/Everlook/Audio/Wave/WaveAudioAsset.cs index d8a2dfb..3186c65 100644 --- a/Everlook/Audio/Wave/WaveAudioAsset.cs +++ b/Everlook/Audio/Wave/WaveAudioAsset.cs @@ -111,11 +111,6 @@ public byte[] PCMData /// Thrown if the file data can't be extracted. public WaveAudioAsset(FileReference fileReference) { - if (fileReference is null) - { - throw new ArgumentNullException(nameof(fileReference)); - } - if (fileReference.GetReferencedFileType() != WarcraftFileType.WaveAudio) { throw new ArgumentException diff --git a/Everlook/Explorer/FileReference.cs b/Everlook/Explorer/FileReference.cs index e53b206..72a9f06 100644 --- a/Everlook/Explorer/FileReference.cs +++ b/Everlook/Explorer/FileReference.cs @@ -187,14 +187,14 @@ public override bool Equals(object? obj) /// public bool Equals(FileReference other) { - if (!(other is null)) + if (other is null) { - return - this.Context.Equals(other.Context) && - this.PackageName == other.PackageName && - this.FilePath == other.FilePath; + return false; } - return false; + + return this.Context.Equals(other.Context) && + this.PackageName == other.PackageName && + this.FilePath == other.FilePath; } /// diff --git a/Everlook/Explorer/FileTreeModel.cs b/Everlook/Explorer/FileTreeModel.cs index f6af209..d49ae0d 100644 --- a/Everlook/Explorer/FileTreeModel.cs +++ b/Everlook/Explorer/FileTreeModel.cs @@ -127,11 +127,6 @@ public string GetNodeFilePath(SerializedNode node) /// A set of all the child references of the given reference. public IEnumerable EnumerateFilesOfReference(FileReference fileReference) { - if (fileReference is null) - { - yield break; - } - if (fileReference.IsFile) { yield return fileReference; diff --git a/Everlook/Package/PackageGroup.cs b/Everlook/Package/PackageGroup.cs index cf72bf3..faf4df3 100644 --- a/Everlook/Package/PackageGroup.cs +++ b/Everlook/Package/PackageGroup.cs @@ -193,11 +193,6 @@ public void LoadPackagesFromPath(string path) /// Thrown if the package is null. public void AddPackage(PackageInteractionHandler package) { - if (package is null) - { - throw new ArgumentNullException(nameof(package)); - } - if (_packages.Contains(package)) { return; @@ -252,7 +247,7 @@ public bool TryExtractVersionedReference(FileReference fileReference, [NotNullWh } var package = GetPackageByName(fileReference.PackageName); - return !(package is null) && package.TryExtractReference(fileReference, out data); + return package.TryExtractReference(fileReference, out data); } /// diff --git a/Everlook/Utility/DataLoadingRoutines.cs b/Everlook/Utility/DataLoadingRoutines.cs index a6fe76c..635ecad 100644 --- a/Everlook/Utility/DataLoadingRoutines.cs +++ b/Everlook/Utility/DataLoadingRoutines.cs @@ -58,11 +58,6 @@ public static class DataLoadingRoutines /// A WMO object. public static WMO LoadWorldModel(FileReference fileReference) { - if (fileReference is null) - { - throw new ArgumentNullException(nameof(fileReference)); - } - WMO worldModel; try { @@ -201,11 +196,6 @@ FileReference fileReference /// A BLP object containing the image data pointed to by the reference. public static BLP LoadBinaryImage(FileReference fileReference) { - if (fileReference is null) - { - throw new ArgumentNullException(nameof(fileReference)); - } - BLP image; try { @@ -329,11 +319,6 @@ FileReference fileReference /// An object containing the model data pointed to by the reference. public static MDX LoadGameModel(FileReference fileReference) { - if (fileReference is null) - { - throw new ArgumentNullException(nameof(fileReference)); - } - MDX model; try { diff --git a/Everlook/Utility/ExtensionMethods.cs b/Everlook/Utility/ExtensionMethods.cs index c4f2bcb..b58e5bc 100644 --- a/Everlook/Utility/ExtensionMethods.cs +++ b/Everlook/Utility/ExtensionMethods.cs @@ -40,11 +40,6 @@ public static class ExtensionMethods /// The notebook to clear the pages from. public static void ClearPages(this Gtk.Notebook notebook) { - if (notebook is null) - { - throw new ArgumentNullException(nameof(notebook)); - } - while (notebook.NPages > 0) { notebook.RemovePage(-1); diff --git a/Everlook/Utility/WarcraftGameContext.cs b/Everlook/Utility/WarcraftGameContext.cs index b7d6719..5fb1fea 100644 --- a/Everlook/Utility/WarcraftGameContext.cs +++ b/Everlook/Utility/WarcraftGameContext.cs @@ -56,16 +56,6 @@ public sealed class WarcraftGameContext : IGameContext /// Thrown if the assets or the file tree are null. public WarcraftGameContext(WarcraftVersion version, PackageGroup assets, FileTreeModel fileTree) { - if (assets is null) - { - throw new ArgumentNullException(nameof(assets)); - } - - if (fileTree is null) - { - throw new ArgumentNullException(nameof(fileTree)); - } - this.Version = version; this.Assets = assets; this.FileTree = fileTree; diff --git a/Everlook/Viewport/Rendering/Core/Buffer.cs b/Everlook/Viewport/Rendering/Core/Buffer.cs index c92a174..d415d7a 100644 --- a/Everlook/Viewport/Rendering/Core/Buffer.cs +++ b/Everlook/Viewport/Rendering/Core/Buffer.cs @@ -112,11 +112,6 @@ public Buffer(GL gl, BufferTargetARB target, BufferUsageARB usage) /// public void AttachAttributePointer(VertexAttributePointer attributePointer) { - if (attributePointer is null) - { - throw new ArgumentNullException(nameof(attributePointer)); - } - Bind(); this.Attributes.Add(attributePointer); } @@ -124,11 +119,6 @@ public void AttachAttributePointer(VertexAttributePointer attributePointer) /// public void AttachAttributePointers(IEnumerable attributePointers) { - if (attributePointers is null) - { - throw new ArgumentNullException(nameof(attributePointers)); - } - Bind(); foreach (var attributePointer in attributePointers) { diff --git a/Everlook/Viewport/Rendering/Core/RenderableActorReference.cs b/Everlook/Viewport/Rendering/Core/RenderableActorReference.cs index cc8b4f6..784fa3a 100644 --- a/Everlook/Viewport/Rendering/Core/RenderableActorReference.cs +++ b/Everlook/Viewport/Rendering/Core/RenderableActorReference.cs @@ -65,16 +65,6 @@ public RenderableActorReference(T target) /// The transform of the instance. public RenderableActorReference(T target, Transform transform) { - if (target is null) - { - throw new ArgumentNullException(nameof(target)); - } - - if (transform is null) - { - throw new ArgumentNullException(nameof(transform)); - } - _target = target; _defaultTransform = target.ActorTransform; diff --git a/Everlook/Viewport/Rendering/Core/ShaderProgram.cs b/Everlook/Viewport/Rendering/Core/ShaderProgram.cs index 13ef11e..e060e14 100644 --- a/Everlook/Viewport/Rendering/Core/ShaderProgram.cs +++ b/Everlook/Viewport/Rendering/Core/ShaderProgram.cs @@ -174,11 +174,6 @@ protected void SetFloat(float value, string uniformName) /// The texture to bind. public void BindTexture2D(TextureUnit textureUnit, TextureUniform uniform, Texture2D texture) { - if (texture is null) - { - throw new ArgumentNullException(nameof(texture)); - } - Enable(); var textureVariableHandle = this.GL.GetUniformLocation(this.NativeShaderProgramID, uniform.ToString()); diff --git a/Everlook/Viewport/Rendering/Core/Texture2D.cs b/Everlook/Viewport/Rendering/Core/Texture2D.cs index fea59f0..1a7af46 100644 --- a/Everlook/Viewport/Rendering/Core/Texture2D.cs +++ b/Everlook/Viewport/Rendering/Core/Texture2D.cs @@ -115,11 +115,6 @@ private Texture2D(GL gl) public Texture2D(GL gl, Bitmap imageData, TextureWrapMode wrapMode = TextureWrapMode.Repeat) : this(gl) { - if (imageData is null) - { - throw new ArgumentNullException(nameof(imageData)); - } - CreateFromBitmap(imageData); this.MagnificationFilter = TextureMagFilter.Linear; diff --git a/Everlook/Viewport/Rendering/RenderableGameModel.cs b/Everlook/Viewport/Rendering/RenderableGameModel.cs index 477d1ec..aa6b22b 100644 --- a/Everlook/Viewport/Rendering/RenderableGameModel.cs +++ b/Everlook/Viewport/Rendering/RenderableGameModel.cs @@ -707,11 +707,6 @@ public void SetDisplayInfoByID(int variationID) /// The display info record to cache. private void CacheDisplayInfo(CreatureDisplayInfoRecord displayInfoRecord) { - if (displayInfoRecord is null) - { - throw new ArgumentNullException(nameof(displayInfoRecord)); - } - if (_modelPath is null) { throw new InvalidOperationException(); diff --git a/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs b/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs index cd551a8..05177b2 100644 --- a/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs +++ b/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs @@ -178,11 +178,6 @@ public void BindTexture3(Texture2D texture) /// The material to use. public void SetMaterial(MDXMaterial modelMaterial) { - if (modelMaterial is null) - { - throw new ArgumentNullException(nameof(modelMaterial)); - } - Enable(); // Set two-sided rendering diff --git a/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs b/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs index f01fc7c..b292889 100644 --- a/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs +++ b/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs @@ -66,11 +66,6 @@ public WorldModelShader(GL gl) /// The material to use. public void SetMaterial(ModelMaterial modelMaterial) { - if (modelMaterial is null) - { - throw new ArgumentNullException(nameof(modelMaterial)); - } - Enable(); // Set two-sided rendering From 6c892f967384fb0dd1dedd5e4b1dd8d5f7e203e8 Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sun, 5 Apr 2020 12:10:43 +0200 Subject: [PATCH 15/18] Invert a bunch of ifs and use using statements. --- .../.idea/dictionaries/jarl.xml | 3 + .../Configuration/EverlookConfiguration.cs | 44 ++++--- Everlook/Configuration/GamePathStorage.cs | 114 ++++++++---------- Everlook/Explorer/FileTreeModel.cs | 16 +-- Everlook/Explorer/GameLoader.cs | 18 ++- Everlook/Export/Model/AssimpConverter.cs | 16 +-- Everlook/UI/EverlookDirectoryExportDialog.cs | 16 ++- Everlook/UI/EverlookGameLoadingDialog.cs | 16 +-- Everlook/UI/EverlookImageExportDialog.cs | 40 +++--- Everlook/UI/EverlookPreferences.cs | 6 +- Everlook/UI/MainWindow.cs | 58 +++++---- Everlook/Utility/ResourceManager.cs | 18 ++- Everlook/Viewport/Rendering/Core/Texture2D.cs | 12 +- Everlook/Viewport/Rendering/RenderCache.cs | 24 ++-- .../Viewport/Rendering/RenderableGameModel.cs | 26 ++-- .../Rendering/RenderableWorldModel.cs | 32 ++--- .../Rendering/Shaders/GameModelShader.cs | 1 - .../Rendering/Shaders/WorldModelShader.cs | 1 - 18 files changed, 220 insertions(+), 241 deletions(-) create mode 100644 .idea/.idea.Everlook/.idea/dictionaries/jarl.xml diff --git a/.idea/.idea.Everlook/.idea/dictionaries/jarl.xml b/.idea/.idea.Everlook/.idea/dictionaries/jarl.xml new file mode 100644 index 0000000..f5f5680 --- /dev/null +++ b/.idea/.idea.Everlook/.idea/dictionaries/jarl.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Everlook/Configuration/EverlookConfiguration.cs b/Everlook/Configuration/EverlookConfiguration.cs index f83ea48..a438922 100644 --- a/Everlook/Configuration/EverlookConfiguration.cs +++ b/Everlook/Configuration/EverlookConfiguration.cs @@ -406,11 +406,13 @@ private void AddNewConfigurationSection(IniData configData, string keySection) private void AddNewConfigurationOption(IniData configData, string keySection, string keyName, string keyData) { - if (!configData.Sections[keySection].ContainsKey(keyName)) + if (configData.Sections[keySection].ContainsKey(keyName)) { - configData.Sections[keySection].AddKey(keyName); - configData.Sections[keySection][keyName] = keyData; + return; } + + configData.Sections[keySection].AddKey(keyName); + configData.Sections[keySection][keyName] = keyData; } private void RenameConfigurationOption @@ -421,25 +423,29 @@ private void RenameConfigurationOption string newKeyName ) { - if (configData.Sections[keySection].ContainsKey(oldKeyName)) + if (!configData.Sections[keySection].ContainsKey(oldKeyName)) { - var oldKeyData = configData.Sections[keySection][oldKeyName]; + return; + } - AddNewConfigurationOption(configData, keySection, newKeyName, oldKeyData); + var oldKeyData = configData.Sections[keySection][oldKeyName]; - configData.Sections[keySection].RemoveKey(oldKeyName); - } + AddNewConfigurationOption(configData, keySection, newKeyName, oldKeyData); + + configData.Sections[keySection].RemoveKey(oldKeyName); } private void RenameConfigurationSection(IniData configData, string oldSectionName, string newSectionName) { - if (configData.Sections.ContainsSection(oldSectionName)) + if (!configData.Sections.ContainsSection(oldSectionName)) { - var oldSectionData = configData.Sections.GetSectionData(oldSectionName); - configData.Sections.RemoveSection(oldSectionName); - configData.Sections.AddSection(newSectionName); - configData.Sections.SetSectionData(newSectionName, oldSectionData); + return; } + + var oldSectionData = configData.Sections.GetSectionData(oldSectionName); + configData.Sections.RemoveSection(oldSectionName); + configData.Sections.AddSection(newSectionName); + configData.Sections.SetSectionData(newSectionName, oldSectionData); } private void DeleteConfigurationSection(IniData configData, string sectionName) @@ -458,13 +464,15 @@ private void MoveConfigurationOption string keyName ) { - if (!configData.Sections[newKeySection].ContainsKey(keyName)) + if (configData.Sections[newKeySection].ContainsKey(keyName)) { - var keyValue = configData.Sections[oldKeySection][keyName]; - configData.Sections[newKeySection].AddKey(keyName, keyValue); - - configData.Sections[oldKeySection].RemoveKey(keyName); + return; } + + var keyValue = configData.Sections[oldKeySection][keyName]; + configData.Sections[newKeySection].AddKey(keyName, keyValue); + + configData.Sections[oldKeySection].RemoveKey(keyName); } /// diff --git a/Everlook/Configuration/GamePathStorage.cs b/Everlook/Configuration/GamePathStorage.cs index f97dfeb..8f66420 100644 --- a/Everlook/Configuration/GamePathStorage.cs +++ b/Everlook/Configuration/GamePathStorage.cs @@ -71,10 +71,8 @@ private GamePathStorage() int formatVersion; using (var fs = File.OpenRead(GetPathStoragePath())) { - using (var br = new BinaryReader(fs)) - { - formatVersion = br.ReadInt32(); - } + using var br = new BinaryReader(fs); + formatVersion = br.ReadInt32(); } if (formatVersion != FormatVersion) @@ -104,21 +102,19 @@ private GamePathStorage() /// Path to store. public void StorePath(string alias, WarcraftVersion version, string pathToStore) { - if (!this.GamePaths.Contains((alias, version, pathToStore))) + if (this.GamePaths.Contains((alias, version, pathToStore))) { - lock (_storageLock) - { - using (var fs = File.Open(GetPathStoragePath(), FileMode.Append, FileAccess.Write)) - { - using (var bw = new BinaryWriter(fs)) - { - bw.WriteNullTerminatedString(alias); - bw.Write((uint)version); - bw.WriteNullTerminatedString(pathToStore); - bw.Flush(); - } - } - } + return; + } + + lock (_storageLock) + { + using var fs = File.Open(GetPathStoragePath(), FileMode.Append, FileAccess.Write); + using var bw = new BinaryWriter(fs); + bw.WriteNullTerminatedString(alias); + bw.Write((uint)version); + bw.WriteNullTerminatedString(pathToStore); + bw.Flush(); } } @@ -131,26 +127,24 @@ public void StorePath(string alias, WarcraftVersion version, string pathToStore) public void RemoveStoredPath(string alias, WarcraftVersion version, string pathToRemove) { var storedPaths = this.GamePaths; - if (storedPaths.Contains((alias, version, pathToRemove))) + if (!storedPaths.Contains((alias, version, pathToRemove))) { - ClearPaths(); - lock (_storageLock) - { - storedPaths.Remove((alias, version, pathToRemove)); + return; + } - using (var fs = File.Open(GetPathStoragePath(), FileMode.Append, FileAccess.Write)) - { - using (var bw = new BinaryWriter(fs)) - { - foreach ((var remainingAlias, var remainingVersion, var remainingPath) in storedPaths) - { - bw.WriteNullTerminatedString(remainingAlias); - bw.Write((uint)remainingVersion); - bw.WriteNullTerminatedString(remainingPath); - bw.Flush(); - } - } - } + ClearPaths(); + lock (_storageLock) + { + storedPaths.Remove((alias, version, pathToRemove)); + + using var fs = File.Open(GetPathStoragePath(), FileMode.Append, FileAccess.Write); + using var bw = new BinaryWriter(fs); + foreach (var (remainingAlias, remainingVersion, remainingPath) in storedPaths) + { + bw.WriteNullTerminatedString(remainingAlias); + bw.Write((uint)remainingVersion); + bw.WriteNullTerminatedString(remainingPath); + bw.Flush(); } } } @@ -162,29 +156,25 @@ public void RemoveStoredPath(string alias, WarcraftVersion version, string pathT { try { - using (var fs = File.OpenRead(GetPathStoragePath())) + using var fs = File.OpenRead(GetPathStoragePath()); + using var br = new BinaryReader(fs); + var formatVersion = br.ReadInt32(); + if (formatVersion != FormatVersion) + { + Log.Warn("Read an unsupported path store version. Aborting."); + } + else { - using (var br = new BinaryReader(fs)) + while (br.BaseStream.Position != br.BaseStream.Length) { - var formatVersion = br.ReadInt32(); - if (formatVersion != FormatVersion) - { - Log.Warn("Read an unsupported path store version. Aborting."); - } - else - { - while (br.BaseStream.Position != br.BaseStream.Length) - { - storedPaths.Add - ( - ( - br.ReadNullTerminatedString(), - (WarcraftVersion)br.ReadUInt32(), - br.ReadNullTerminatedString() - ) - ); - } - } + storedPaths.Add + ( + ( + br.ReadNullTerminatedString(), + (WarcraftVersion)br.ReadUInt32(), + br.ReadNullTerminatedString() + ) + ); } } } @@ -204,13 +194,9 @@ private void ClearPaths() { File.Delete(GetPathStoragePath()); - using (var fs = File.Create(GetPathStoragePath())) - { - using (var bw = new BinaryWriter(fs)) - { - bw.Write(FormatVersion); - } - } + using var fs = File.Create(GetPathStoragePath()); + using var bw = new BinaryWriter(fs); + bw.Write(FormatVersion); } } diff --git a/Everlook/Explorer/FileTreeModel.cs b/Everlook/Explorer/FileTreeModel.cs index d49ae0d..267cf8c 100644 --- a/Everlook/Explorer/FileTreeModel.cs +++ b/Everlook/Explorer/FileTreeModel.cs @@ -369,13 +369,13 @@ public bool IterNext(ref TreeIter iter) var currentIndex = parentNode.ChildOffsets.IndexOf(currentOffset); var nextIndex = currentIndex + 1; - if (nextIndex < (int)parentNode.ChildCount) + if (nextIndex >= (int)parentNode.ChildCount) { - iter.UserData = new IntPtr((long)parentNode.ChildOffsets[nextIndex]); - return true; + return false; } - return false; + iter.UserData = new IntPtr((long)parentNode.ChildOffsets[nextIndex]); + return true; } /// @@ -399,13 +399,13 @@ public bool IterPrevious(ref TreeIter iter) var currentIndex = parentNode.ChildOffsets.IndexOf(currentOffset); var previousIndex = currentIndex - 1; - if (previousIndex >= 0 && previousIndex < (int)parentNode.ChildCount) + if (previousIndex < 0 || previousIndex >= (int)parentNode.ChildCount) { - iter.UserData = new IntPtr((long)parentNode.ChildOffsets[previousIndex]); - return true; + return false; } - return false; + iter.UserData = new IntPtr((long)parentNode.ChildOffsets[previousIndex]); + return true; } /// diff --git a/Everlook/Explorer/GameLoader.cs b/Everlook/Explorer/GameLoader.cs index 26da41e..3e7b058 100644 --- a/Everlook/Explorer/GameLoader.cs +++ b/Everlook/Explorer/GameLoader.cs @@ -257,12 +257,10 @@ private static Task LoadDictionaryAsync(CancellationToken ct var treeClosureCopy = tree; tree = await Task.Run(() => optimizer.OptimizeTree(treeClosureCopy, optimizeTreeProgress, ct), ct); - using (var fs = File.OpenWrite(packageTreeFilePath)) + await using (var fs = File.OpenWrite(packageTreeFilePath)) { - using (var serializer = new TreeSerializer(fs)) - { - await serializer.SerializeAsync(tree, ct); - } + using var serializer = new TreeSerializer(fs); + await serializer.SerializeAsync(tree, ct); } nodeTree = new SerializedTree(File.OpenRead(packageTreeFilePath)); @@ -309,13 +307,11 @@ private static string GeneratePathSetHash(IEnumerable packagePaths) sb.Append(packageSize); } - using (var md5 = MD5.Create()) - { - var input = Encoding.UTF8.GetBytes(sb.ToString()); - var hash = md5.ComputeHash(input); + using var md5 = MD5.Create(); + var input = Encoding.UTF8.GetBytes(sb.ToString()); + var hash = md5.ComputeHash(input); - return BitConverter.ToString(hash); - } + return BitConverter.ToString(hash); } } } diff --git a/Everlook/Export/Model/AssimpConverter.cs b/Everlook/Export/Model/AssimpConverter.cs index 5948493..32a1615 100644 --- a/Everlook/Export/Model/AssimpConverter.cs +++ b/Everlook/Export/Model/AssimpConverter.cs @@ -99,15 +99,17 @@ public static Scene FromMDX(MDX model) mesh.TextureCoordinateChannels[0].Add(new Vector3D(vertex.UV1.X, vertex.UV1.Y, 0.0f)); mesh.TextureCoordinateChannels[1].Add(new Vector3D(vertex.UV2.X, vertex.UV2.Y, 0.0f)); - if (mesh.HasBones) + if (!mesh.HasBones) { - for (var boneAttributeIndex = 0; boneAttributeIndex < 4; ++boneAttributeIndex) - { - var bone = mesh.Bones[vertex.BoneIndices[boneAttributeIndex]]; + continue; + } + + for (var boneAttributeIndex = 0; boneAttributeIndex < 4; ++boneAttributeIndex) + { + var bone = mesh.Bones[vertex.BoneIndices[boneAttributeIndex]]; - var weight = vertex.BoneWeights[boneAttributeIndex]; - bone.VertexWeights.Add(new VertexWeight(i, weight)); - } + var weight = vertex.BoneWeights[boneAttributeIndex]; + bone.VertexWeights.Add(new VertexWeight(i, weight)); } } diff --git a/Everlook/UI/EverlookDirectoryExportDialog.cs b/Everlook/UI/EverlookDirectoryExportDialog.cs index 5e533fa..477600b 100644 --- a/Everlook/UI/EverlookDirectoryExportDialog.cs +++ b/Everlook/UI/EverlookDirectoryExportDialog.cs @@ -50,15 +50,13 @@ public partial class EverlookDirectoryExportDialog : Dialog /// An initialized instance of the EverlookDirectoryExportDialog class. public static EverlookDirectoryExportDialog Create(FileReference inExportTarget) { - using (var builder = new Builder(null, "Everlook.interfaces.EverlookDirectoryExport.glade", null)) - { - return new EverlookDirectoryExportDialog - ( - builder, - builder.GetObject("EverlookDirectoryExportDialog").Handle, - inExportTarget - ); - } + using var builder = new Builder(null, "Everlook.interfaces.EverlookDirectoryExport.glade", null); + return new EverlookDirectoryExportDialog + ( + builder, + builder.GetObject("EverlookDirectoryExportDialog").Handle, + inExportTarget + ); } /// diff --git a/Everlook/UI/EverlookGameLoadingDialog.cs b/Everlook/UI/EverlookGameLoadingDialog.cs index a8bfd6f..c9c20bc 100644 --- a/Everlook/UI/EverlookGameLoadingDialog.cs +++ b/Everlook/UI/EverlookGameLoadingDialog.cs @@ -72,10 +72,8 @@ public partial class EverlookGameLoadingDialog : Dialog /// An initialized instance of the EverlookGameLoadingDialog class. public static EverlookGameLoadingDialog Create(Window parent) { - using (var builder = new Builder(null, "Everlook.interfaces.EverlookGameLoadingDialog.glade", null)) - { - return new EverlookGameLoadingDialog(builder, builder.GetObject("_gameLoadingDialog").Handle, parent); - } + using var builder = new Builder(null, "Everlook.interfaces.EverlookGameLoadingDialog.glade", null); + return new EverlookGameLoadingDialog(builder, builder.GetObject("_gameLoadingDialog").Handle, parent); } private EverlookGameLoadingDialog(Builder builder, IntPtr handle, Window parent) @@ -166,13 +164,11 @@ private EverlookGameLoadingDialog(Builder builder, IntPtr handle, Window parent) return; } - using (var sr = new StreamReader(shaderStream)) + using var sr = new StreamReader(shaderStream); + while (sr.BaseStream.Length > sr.BaseStream.Position) { - while (sr.BaseStream.Length > sr.BaseStream.Position) - { - // Add italics to all jokes. Jokes are in Pango markup format - _jokes.Add($"{sr.ReadLine()}"); - } + // Add italics to all jokes. Jokes are in Pango markup format + _jokes.Add($"{sr.ReadLine()}"); } } diff --git a/Everlook/UI/EverlookImageExportDialog.cs b/Everlook/UI/EverlookImageExportDialog.cs index 3bc3e45..9fbf68f 100644 --- a/Everlook/UI/EverlookImageExportDialog.cs +++ b/Everlook/UI/EverlookImageExportDialog.cs @@ -64,15 +64,13 @@ public partial class EverlookImageExportDialog : Dialog /// An initialized instance of the EverlookImageExportDialog class. public static EverlookImageExportDialog Create(FileReference inExportTarget) { - using (var builder = new Builder(null, "Everlook.interfaces.EverlookImageExport.glade", null)) - { - return new EverlookImageExportDialog - ( - builder, - builder.GetObject("EverlookImageExportDialog").Handle, - inExportTarget - ); - } + using var builder = new Builder(null, "Everlook.interfaces.EverlookImageExport.glade", null); + return new EverlookImageExportDialog + ( + builder, + builder.GetObject("EverlookImageExportDialog").Handle, + inExportTarget + ); } /// @@ -174,14 +172,12 @@ public void RunExport() var fullExportPath = $"{exportPath}_{i}.{formatExtension}"; - using (var fs = File.OpenWrite(fullExportPath)) - { - _image.GetMipMap((uint)i).Save - ( - fs, - GetImageEncoderFromFormat((ImageFormat)_exportFormatComboBox.Active) - ); - } + using var fs = File.OpenWrite(fullExportPath); + _image.GetMipMap((uint)i).Save + ( + fs, + GetImageEncoderFromFormat((ImageFormat)_exportFormatComboBox.Active) + ); } ++i; @@ -240,12 +236,14 @@ private static string GetFileExtensionFromImageFormat(ImageFormat format) [GLib.ConnectBefore] protected void OnMipListingButtonPressed(object? sender, ButtonPressEventArgs e) { - if (e.Event.Type == EventType.ButtonPress && e.Event.Button == 3) + if (e.Event.Type != EventType.ButtonPress || e.Event.Button != 3) { - _exportPopupMenu.ShowAll(); - - _exportPopupMenu.PopupAtPointer(e.Event); + return; } + + _exportPopupMenu.ShowAll(); + + _exportPopupMenu.PopupAtPointer(e.Event); } /// diff --git a/Everlook/UI/EverlookPreferences.cs b/Everlook/UI/EverlookPreferences.cs index ca621cc..9a7123c 100644 --- a/Everlook/UI/EverlookPreferences.cs +++ b/Everlook/UI/EverlookPreferences.cs @@ -60,10 +60,8 @@ public sealed partial class EverlookPreferences : Dialog /// An initialized instance of the EverlookPreferences class. public static EverlookPreferences Create() { - using (var builder = new Builder(null, "Everlook.interfaces.EverlookPreferences.glade", null)) - { - return new EverlookPreferences(builder, builder.GetObject("_preferencesDialog").Handle); - } + using var builder = new Builder(null, "Everlook.interfaces.EverlookPreferences.glade", null); + return new EverlookPreferences(builder, builder.GetObject("_preferencesDialog").Handle); } /// diff --git a/Everlook/UI/MainWindow.cs b/Everlook/UI/MainWindow.cs index fbefc03..6b01bff 100644 --- a/Everlook/UI/MainWindow.cs +++ b/Everlook/UI/MainWindow.cs @@ -1050,15 +1050,13 @@ private static Task OnExportItemRequested(GamePage page, FileReference fileRefer } case WarcraftFileType.BinaryImage: { - using (var exportDialog = EverlookImageExportDialog.Create(fileReference)) + using var exportDialog = EverlookImageExportDialog.Create(fileReference); + if (exportDialog.Run() == (int)ResponseType.Ok) { - if (exportDialog.Run() == (int)ResponseType.Ok) - { - exportDialog.RunExport(); - } - - exportDialog.Hide(); + exportDialog.RunExport(); } + + exportDialog.Hide(); break; } } @@ -1097,28 +1095,26 @@ private void OnAboutButtonClicked(object? sender, EventArgs e) /// E. private async void OnPreferencesButtonClicked(object? sender, EventArgs e) { - using (var preferencesDialog = EverlookPreferences.Create()) + using var preferencesDialog = EverlookPreferences.Create(); + preferencesDialog.TransientFor = this; + if (preferencesDialog.Run() == (int)ResponseType.Ok) { - preferencesDialog.TransientFor = this; - if (preferencesDialog.Run() == (int)ResponseType.Ok) - { - preferencesDialog.SavePreferences(); - } + preferencesDialog.SavePreferences(); + } - preferencesDialog.Hide(); + preferencesDialog.Hide(); - // Commit the changes - ReloadViewportBackground(); + // Commit the changes + ReloadViewportBackground(); - if (preferencesDialog.DidGameListChange) - { - await ReloadGames(); - } + if (preferencesDialog.DidGameListChange) + { + await ReloadGames(); + } - if (preferencesDialog.ShouldRefilterTree) - { - await RefilterTrees(); - } + if (preferencesDialog.ShouldRefilterTree) + { + await RefilterTrees(); } } @@ -1165,13 +1161,15 @@ private async Task OnSaveRequested(GamePage page, IEnumerable fil File.Delete(exportpath); } - using + await using var fs = new FileStream ( - var fs = new FileStream(exportpath, FileMode.CreateNew, FileAccess.Write, FileShare.None) - ) - { - await fs.WriteAsync(file, 0, file.Length); - } + exportpath, + FileMode.CreateNew, + FileAccess.Write, + FileShare.None + ); + + await fs.WriteAsync(file, 0, file.Length); } catch (UnauthorizedAccessException unex) { diff --git a/Everlook/Utility/ResourceManager.cs b/Everlook/Utility/ResourceManager.cs index bad0607..c954427 100644 --- a/Everlook/Utility/ResourceManager.cs +++ b/Everlook/Utility/ResourceManager.cs @@ -46,10 +46,8 @@ public static class ResourceManager return null; } - using (var sr = new StreamReader(resourceStream)) - { - resourceString = sr.ReadToEnd(); - } + using var sr = new StreamReader(resourceStream); + resourceString = sr.ReadToEnd(); } return resourceString; @@ -65,15 +63,13 @@ public static class ResourceManager var executingAssembly = Assembly.GetExecutingAssembly(); const string fallbackTextureName = "Everlook.Content.Textures.FallbackTexture.png"; - using (var imageStream = executingAssembly.GetManifestResourceStream(fallbackTextureName)) + using var imageStream = executingAssembly.GetManifestResourceStream(fallbackTextureName); + if (imageStream is null) { - if (imageStream is null) - { - return null; - } - - return new Bitmap(imageStream); + return null; } + + return new Bitmap(imageStream); } } } diff --git a/Everlook/Viewport/Rendering/Core/Texture2D.cs b/Everlook/Viewport/Rendering/Core/Texture2D.cs index 1a7af46..4b6d23f 100644 --- a/Everlook/Viewport/Rendering/Core/Texture2D.cs +++ b/Everlook/Viewport/Rendering/Core/Texture2D.cs @@ -194,18 +194,14 @@ public Texture2D finally { // Load a fallback bitmap instead - using (var mipZero = imageData.GetMipMap(0)) - { - CreateFromImage(mipZero); - } + using var mipZero = imageData.GetMipMap(0); + CreateFromImage(mipZero); } } else { - using (var mipZero = imageData.GetMipMap(0)) - { - CreateFromImage(mipZero); - } + using var mipZero = imageData.GetMipMap(0); + CreateFromImage(mipZero); } this.MagnificationFilter = magFilter; diff --git a/Everlook/Viewport/Rendering/RenderCache.cs b/Everlook/Viewport/Rendering/RenderCache.cs index d6d06d5..d7ce196 100644 --- a/Everlook/Viewport/Rendering/RenderCache.cs +++ b/Everlook/Viewport/Rendering/RenderCache.cs @@ -75,17 +75,19 @@ public Texture2D FallbackTexture { ThrowIfDisposed(); - if (_fallbackTextureInternal is null) + if (!(_fallbackTextureInternal is null)) { - var fallbackImage = ResourceManager.GetFallbackImage(); - if (fallbackImage is null) - { - throw new InvalidOperationException(); - } + return _fallbackTextureInternal; + } - _fallbackTextureInternal = new Texture2D(this.GL, fallbackImage); + var fallbackImage = ResourceManager.GetFallbackImage(); + if (fallbackImage is null) + { + throw new InvalidOperationException(); } + _fallbackTextureInternal = new Texture2D(this.GL, fallbackImage); + return _fallbackTextureInternal; } } @@ -262,11 +264,9 @@ public Texture2D GetTexture return this.FallbackTexture; } - using (var ms = new MemoryStream(data)) - { - var texture = new Bitmap(ms); - return CreateCachedTexture(texture, texturePath); - } + using var ms = new MemoryStream(data); + var texture = new Bitmap(ms); + return CreateCachedTexture(texture, texturePath); } } diff --git a/Everlook/Viewport/Rendering/RenderableGameModel.cs b/Everlook/Viewport/Rendering/RenderableGameModel.cs index aa6b22b..a16a7a8 100644 --- a/Everlook/Viewport/Rendering/RenderableGameModel.cs +++ b/Everlook/Viewport/Rendering/RenderableGameModel.cs @@ -275,20 +275,22 @@ public void Initialize() _skinIndexArrayBuffers.Add(skin, skinIndexBuffer); - if (_model.Version <= WarcraftVersion.Wrath) + if (_model.Version > WarcraftVersion.Wrath) { - // In models earlier than Cata, we need to calculate the shader selector value at runtime. - foreach (var renderBatch in skin.RenderBatches) - { - var shaderSelector = MDXShaderHelper.GetRuntimeShaderID - ( - renderBatch.ShaderID, - renderBatch, - _model - ); + continue; + } - renderBatch.ShaderID = shaderSelector; - } + // In models earlier than Cata, we need to calculate the shader selector value at runtime. + foreach (var renderBatch in skin.RenderBatches) + { + var shaderSelector = MDXShaderHelper.GetRuntimeShaderID + ( + renderBatch.ShaderID, + renderBatch, + _model + ); + + renderBatch.ShaderID = shaderSelector; } } diff --git a/Everlook/Viewport/Rendering/RenderableWorldModel.cs b/Everlook/Viewport/Rendering/RenderableWorldModel.cs index 39bad76..8e859eb 100644 --- a/Everlook/Viewport/Rendering/RenderableWorldModel.cs +++ b/Everlook/Viewport/Rendering/RenderableWorldModel.cs @@ -218,12 +218,14 @@ public void Initialize() // Load the textures used in this model foreach (var texture in _model.GetTextures()) { - if (!string.IsNullOrEmpty(texture)) + if (string.IsNullOrEmpty(texture)) { - if (!_textureLookup.ContainsKey(texture)) - { - _textureLookup.Add(texture, _renderCache.GetTexture(texture, _gameContext.Assets)); - } + continue; + } + + if (!_textureLookup.ContainsKey(texture)) + { + _textureLookup.Add(texture, _renderCache.GetTexture(texture, _gameContext.Assets)); } } @@ -462,17 +464,19 @@ public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCam } } - if (this.ShouldRenderDoodads) + if (!this.ShouldRenderDoodads) { - foreach (var doodadInstanceSet in _doodadSets[this.DoodadSet]) - { - doodadInstanceSet.ShouldRenderBounds = this.ShouldRenderBounds; - } + return; + } - foreach (var doodadInstanceSet in _doodadSets[this.DoodadSet]) - { - doodadInstanceSet.Render(viewMatrix, projectionMatrix, camera); - } + foreach (var doodadInstanceSet in _doodadSets[this.DoodadSet]) + { + doodadInstanceSet.ShouldRenderBounds = this.ShouldRenderBounds; + } + + foreach (var doodadInstanceSet in _doodadSets[this.DoodadSet]) + { + doodadInstanceSet.Render(viewMatrix, projectionMatrix, camera); } // TODO: Summarize the render batches from each group that has the same material ID diff --git a/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs b/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs index 05177b2..57c83e9 100644 --- a/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs +++ b/Everlook/Viewport/Rendering/Shaders/GameModelShader.cs @@ -20,7 +20,6 @@ // along with this program. If not, see . // -using System; using System.Numerics; using Everlook.Viewport.Rendering.Core; using Everlook.Viewport.Rendering.Shaders.Components; diff --git a/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs b/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs index b292889..dbe83b1 100644 --- a/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs +++ b/Everlook/Viewport/Rendering/Shaders/WorldModelShader.cs @@ -20,7 +20,6 @@ // along with this program. If not, see . // -using System; using Everlook.Viewport.Rendering.Core; using Everlook.Viewport.Rendering.Shaders.Components; using Silk.NET.OpenGL; From 7e7c8820ce0d4ce9772fce5a655a2bd4915aa739 Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sun, 5 Apr 2020 12:13:36 +0200 Subject: [PATCH 16/18] More language usage opportunities. --- Everlook/Audio/Wave/WaveAudioAsset.cs | 76 +++++++++---------- .../Configuration/EverlookConfiguration.cs | 2 +- Everlook/Viewport/Rendering/Core/Plane.cs | 2 +- .../Rendering/RenderableBoundingBox.cs | 2 +- .../Rendering/RenderableWorldModel.cs | 13 +--- 5 files changed, 43 insertions(+), 52 deletions(-) diff --git a/Everlook/Audio/Wave/WaveAudioAsset.cs b/Everlook/Audio/Wave/WaveAudioAsset.cs index 3186c65..eab1049 100644 --- a/Everlook/Audio/Wave/WaveAudioAsset.cs +++ b/Everlook/Audio/Wave/WaveAudioAsset.cs @@ -125,59 +125,55 @@ public WaveAudioAsset(FileReference fileReference) throw new ArgumentException("The file data could not be extracted.", nameof(fileReference)); } - using (var ms = new MemoryStream(fileBytes)) + using var ms = new MemoryStream(fileBytes); + using var br = new BinaryReader(ms); + var signature = new string(br.ReadChars(4)); + if (signature != "RIFF") { - using (var br = new BinaryReader(ms)) - { - var signature = new string(br.ReadChars(4)); - if (signature != "RIFF") - { - throw new NotSupportedException("The file data is not a wave file."); - } + throw new NotSupportedException("The file data is not a wave file."); + } - // Skip chunk size - br.BaseStream.Position += 4; + // Skip chunk size + br.BaseStream.Position += 4; - var format = new string(br.ReadChars(4)); - if (format != "WAVE") - { - throw new NotSupportedException("The file data is not a wave file."); - } + var format = new string(br.ReadChars(4)); + if (format != "WAVE") + { + throw new NotSupportedException("The file data is not a wave file."); + } - var formatSignature = new string(br.ReadChars(4)); - if (formatSignature != "fmt ") - { - throw new NotSupportedException("The file data is not a wave file."); - } + var formatSignature = new string(br.ReadChars(4)); + if (formatSignature != "fmt ") + { + throw new NotSupportedException("The file data is not a wave file."); + } - // Skip format chunk size - br.BaseStream.Position += 4; + // Skip format chunk size + br.BaseStream.Position += 4; - // Skip audio format - br.BaseStream.Position += 2; + // Skip audio format + br.BaseStream.Position += 2; - this.Channels = br.ReadInt16(); - this.SampleRate = br.ReadInt32(); + this.Channels = br.ReadInt16(); + this.SampleRate = br.ReadInt32(); - // Skip byte rate - br.BaseStream.Position += 4; + // Skip byte rate + br.BaseStream.Position += 4; - // Skip block alignment - br.BaseStream.Position += 2; + // Skip block alignment + br.BaseStream.Position += 2; - this.BitsPerSample = br.ReadInt16(); + this.BitsPerSample = br.ReadInt16(); - var dataSignature = new string(br.ReadChars(4)); - if (dataSignature != "data") - { - throw new NotSupportedException("The file data is not a wave file."); - } + var dataSignature = new string(br.ReadChars(4)); + if (dataSignature != "data") + { + throw new NotSupportedException("The file data is not a wave file."); + } - var dataChunkSize = br.ReadInt32(); + var dataChunkSize = br.ReadInt32(); - this.PCMStream = new MemoryStream(br.ReadBytes(dataChunkSize)); - } - } + this.PCMStream = new MemoryStream(br.ReadBytes(dataChunkSize)); } /// diff --git a/Everlook/Configuration/EverlookConfiguration.cs b/Everlook/Configuration/EverlookConfiguration.cs index a438922..a48f236 100644 --- a/Everlook/Configuration/EverlookConfiguration.cs +++ b/Everlook/Configuration/EverlookConfiguration.cs @@ -56,7 +56,7 @@ Section names private readonly object _writeLock = new object(); private readonly FileIniDataParser _defaultParser = new FileIniDataParser(); - private IniData _configurationData; + private readonly IniData _configurationData; /// /// Gets or sets the sprinting speed multiplier. diff --git a/Everlook/Viewport/Rendering/Core/Plane.cs b/Everlook/Viewport/Rendering/Core/Plane.cs index 263043c..10c2a91 100644 --- a/Everlook/Viewport/Rendering/Core/Plane.cs +++ b/Everlook/Viewport/Rendering/Core/Plane.cs @@ -58,7 +58,7 @@ public Plane(Vector3 inNormal, Vector3 inPointOnPlane) /// /// The point from which to measure the distance. /// The distance between the point and the plane. - public float Distance(Vector3 point) + public readonly float Distance(Vector3 point) { return Vector3.Dot(this.Normal, point - this.PointOnPlane); } diff --git a/Everlook/Viewport/Rendering/RenderableBoundingBox.cs b/Everlook/Viewport/Rendering/RenderableBoundingBox.cs index 85c0dfe..5e61dad 100644 --- a/Everlook/Viewport/Rendering/RenderableBoundingBox.cs +++ b/Everlook/Viewport/Rendering/RenderableBoundingBox.cs @@ -63,7 +63,7 @@ public sealed class RenderableBoundingBox : GraphicsObject, IInstancedRenderable /// private bool IsDisposed { get; set; } - private Box _boundingBoxData; + private readonly Box _boundingBoxData; private Buffer? _vertexBuffer; private Buffer? _vertexIndexesBuffer; diff --git a/Everlook/Viewport/Rendering/RenderableWorldModel.cs b/Everlook/Viewport/Rendering/RenderableWorldModel.cs index 8e859eb..8fb24cb 100644 --- a/Everlook/Viewport/Rendering/RenderableWorldModel.cs +++ b/Everlook/Viewport/Rendering/RenderableWorldModel.cs @@ -57,7 +57,7 @@ public sealed class RenderableWorldModel : /// /// Holds the render cache. /// - private RenderCache _renderCache; + private readonly RenderCache _renderCache; /// /// Gets or sets a value indicating whether this object has been disposed. @@ -539,14 +539,9 @@ private void RenderGroup(ModelGroup modelGroup, Matrix4x4 modelViewProjection) // Set the texture as the first diffuse texture in unit 0 var texture = _renderCache.GetCachedTexture(modelMaterial.DiffuseTexture); - if (modelMaterial.Flags.HasFlag(MaterialFlags.TextureWrappingClampS)) - { - texture.WrappingMode = TextureWrapMode.ClampToBorder; - } - else - { - texture.WrappingMode = TextureWrapMode.Repeat; - } + texture.WrappingMode = modelMaterial.Flags.HasFlag(MaterialFlags.TextureWrappingClampS) + ? TextureWrapMode.ClampToBorder + : TextureWrapMode.Repeat; _shader.BindTexture2D(TextureUnit.Texture0, TextureUniform.Texture0, texture); From 7ffce4519a554e51774108bd85b8b39808da0f8e Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sun, 5 Apr 2020 16:28:28 +0200 Subject: [PATCH 17/18] Upgrade libwarcraft. --- .../Database/Access/WMOAreaTableAccess.cs | 4 +- Everlook/Database/ClientDatabaseProvider.cs | 7 +- Everlook/Everlook.csproj | 2 +- Everlook/Export/Model/AssimpConverter.cs | 48 +++++++++++-- Everlook/Package/PackageGroup.cs | 31 +-------- Everlook/Package/PackageInteractionHandler.cs | 22 ------ .../Utility/StringReferenceListComparer.cs | 12 +--- Everlook/Utility/WarcraftGameContext.cs | 4 +- .../Viewport/Rendering/RenderableGameModel.cs | 69 ++++++++++--------- .../Rendering/RenderableWorldModel.cs | 12 ++-- NuGet.config | 5 -- stylecop.json | 3 +- 12 files changed, 100 insertions(+), 119 deletions(-) diff --git a/Everlook/Database/Access/WMOAreaTableAccess.cs b/Everlook/Database/Access/WMOAreaTableAccess.cs index fc64765..2e3cd6b 100644 --- a/Everlook/Database/Access/WMOAreaTableAccess.cs +++ b/Everlook/Database/Access/WMOAreaTableAccess.cs @@ -53,7 +53,7 @@ ForeignKey groupID throw new ArgumentException("The given foreign key is not valid for searching by WMO group ID."); } - return database.FirstOrDefault(x => x.WMOGroupID == groupID.Key); + return database.First(x => x?.WMOGroupID == groupID.Key) ?? throw new InvalidOperationException(); } /// @@ -72,7 +72,7 @@ public static WMOAreaTableRecord GetWMOArea(this DBC databas throw new ArgumentException("The given foreign key is not valid for searching by WMO ID."); } - return database.FirstOrDefault(x => x.WMOID == wmoID.Key); + return database.First(x => x?.WMOID == wmoID.Key) ?? throw new InvalidOperationException(); } } } diff --git a/Everlook/Database/ClientDatabaseProvider.cs b/Everlook/Database/ClientDatabaseProvider.cs index 0a0cf25..5bb1195 100644 --- a/Everlook/Database/ClientDatabaseProvider.cs +++ b/Everlook/Database/ClientDatabaseProvider.cs @@ -97,7 +97,7 @@ public ClientDatabaseProvider(WarcraftVersion version, IPackage contentSource) public T GetRecordByID(int id) where T : DBCRecord, new() { var database = GetDatabase(); - return database.GetRecordByID(id); + return database.GetRecordByID(id) ?? throw new InvalidOperationException(); } /// @@ -141,7 +141,10 @@ private void LoadDatabase(DatabaseName databaseName) var specificDBCType = genericDBCType.MakeGenericType(GetRecordTypeFromDatabaseName(databaseName)); var databasePath = GetDatabasePackagePath(databaseName); - var databaseData = _contentSource.ExtractFile(databasePath); + if (!_contentSource.TryExtractFile(databasePath, out var databaseData)) + { + throw new InvalidOperationException(); + } if (!(Activator.CreateInstance(specificDBCType, _version, databaseData) is IDBC database)) { diff --git a/Everlook/Everlook.csproj b/Everlook/Everlook.csproj index 2fa5312..a91e09c 100644 --- a/Everlook/Everlook.csproj +++ b/Everlook/Everlook.csproj @@ -61,7 +61,7 @@ - + diff --git a/Everlook/Export/Model/AssimpConverter.cs b/Everlook/Export/Model/AssimpConverter.cs index 32a1615..9b92ee2 100644 --- a/Everlook/Export/Model/AssimpConverter.cs +++ b/Everlook/Export/Model/AssimpConverter.cs @@ -21,9 +21,12 @@ // using System; +using System.Collections.Generic; using System.Linq; using Assimp; using Warcraft.MDX; +using Warcraft.MDX.Data; +using Warcraft.MDX.Geometry.Skin; namespace Everlook.Export.Model { @@ -50,12 +53,32 @@ public static Scene FromMDX(MDX model) var defaultMaterial = new Material(); scene.Materials.Add(defaultMaterial); + if (model.Skins is null) + { + return scene; + } + foreach (var skin in model.Skins) { var skinNode = new Node($"LOD_{model.Skins.ToList().IndexOf(skin)}", modelNode); modelNode.Children.Add(skinNode); - var skinVerts = skin.VertexIndices.Select(i => model.Vertices[i]).ToArray(); + if (skin.VertexIndices is null) + { + continue; + } + + if (model.Vertices is null) + { + continue; + } + + var skinVerts = skin.VertexIndices.Select(i => model.Vertices?[i]).ToArray(); + + if (skin.Sections is null) + { + continue; + } foreach (var section in skin.Sections) { @@ -64,13 +87,16 @@ public static Scene FromMDX(MDX model) mesh.MaterialIndex = scene.Materials.IndexOf(defaultMaterial); - var modelBones = model.Bones.Skip(section.StartBoneIndex).Take(section.BoneCount); - foreach (var modelBone in modelBones) + if (!(model.Bones is null)) { - var bone = new Bone(); + var modelBones = model.Bones.Skip(section.StartBoneIndex).Take(section.BoneCount); + foreach (var modelBone in modelBones) + { + var bone = new Bone(); - // TODO: Calculate offset matrices - mesh.Bones.Add(bone); + // TODO: Calculate offset matrices + mesh.Bones.Add(bone); + } } var batchNode = new Node($"Section_{skin.Sections.ToList().IndexOf(section)}", skinNode); @@ -93,6 +119,11 @@ public static Scene FromMDX(MDX model) var localIndex = skinVertexIndexes[i]; var vertex = skinVerts[localIndex]; + if (vertex is null) + { + continue; + } + mesh.Vertices.Add(new Vector3D(vertex.Position.X, vertex.Position.Y, vertex.Position.Z)); mesh.Normals.Add(new Vector3D(vertex.Normal.X, vertex.Normal.Y, vertex.Normal.Z)); @@ -113,6 +144,11 @@ public static Scene FromMDX(MDX model) } } + if (skin.Triangles is null) + { + continue; + } + var triangleIndexes = new Span ( skin.Triangles.ToArray(), diff --git a/Everlook/Package/PackageGroup.cs b/Everlook/Package/PackageGroup.cs index faf4df3..3727b13 100644 --- a/Everlook/Package/PackageGroup.cs +++ b/Everlook/Package/PackageGroup.cs @@ -323,21 +323,6 @@ public bool TryExtractFile(string filePath, [NotNullWhen(true)] out byte[]? data return false; } - /// - [Obsolete] - public byte[] ExtractFile(string filePath) - { - for (var i = _packages.Count - 1; i >= 0; --i) - { - if (_packages[i].TryExtractFile(filePath, out var data)) - { - return data; - } - } - - throw new FileNotFoundException("The specified file was not found in this package group.", filePath); - } - /// public bool HasFileList() { @@ -345,9 +330,9 @@ public bool HasFileList() } /// - public IEnumerable? GetFileList() + public IEnumerable GetFileList() { - return null; + return new List(); } /// @@ -380,18 +365,6 @@ public bool TryGetFileInfo(string filePath, [NotNullWhen(true)] out MPQFileInfo? return false; } - /// - [Obsolete] - public MPQFileInfo GetFileInfo(string filePath) - { - if (!TryGetFileInfo(filePath, out var fileInfo)) - { - throw new FileNotFoundException("The specified file was not found in this package group.", filePath); - } - - return fileInfo; - } - /// public override bool Equals(object? obj) { diff --git a/Everlook/Package/PackageInteractionHandler.cs b/Everlook/Package/PackageInteractionHandler.cs index 2ae7ae9..d86ad39 100644 --- a/Everlook/Package/PackageInteractionHandler.cs +++ b/Everlook/Package/PackageInteractionHandler.cs @@ -179,13 +179,6 @@ public bool TryExtractFile(string filePath, [NotNullWhen(true)] out byte[]? data return _package.TryExtractFile(filePath, out data); } - /// - [Obsolete] - public byte[]? ExtractFile(string filePath) - { - return _package?.ExtractFile(filePath); - } - /// public bool HasFileList() { @@ -231,21 +224,6 @@ public bool TryGetFileInfo(string filePath, [NotNullWhen(true)] out MPQFileInfo? return _package.TryGetFileInfo(filePath, out fileInfo); } - /// - [Obsolete] - public MPQFileInfo? GetFileInfo(string filePath) - { - try - { - return _package?.GetFileInfo(filePath); - } - catch (FileNotFoundException) - { - // TODO: YUCK - return null; - } - } - /// public void Dispose() { diff --git a/Everlook/Utility/StringReferenceListComparer.cs b/Everlook/Utility/StringReferenceListComparer.cs index 26fc5d2..643a9e2 100644 --- a/Everlook/Utility/StringReferenceListComparer.cs +++ b/Everlook/Utility/StringReferenceListComparer.cs @@ -34,16 +34,6 @@ public class StringReferenceListComparer : IEqualityComparer public bool Equals(IReadOnlyList x, IReadOnlyList y) { - if (x is null && y is null) - { - return true; - } - - if (x is null || y is null) - { - return false; - } - if (x.Count != y.Count) { return false; @@ -80,7 +70,7 @@ public int GetHashCode(IReadOnlyList obj) foreach (var reference in obj) { - hash *= 23 + reference.Value.GetHashCode(); + hash *= 23 + (reference.Value?.GetHashCode()).GetValueOrDefault(); hash *= 23 + reference.Offset.GetHashCode(); } diff --git a/Everlook/Utility/WarcraftGameContext.cs b/Everlook/Utility/WarcraftGameContext.cs index 5fb1fea..c036631 100644 --- a/Everlook/Utility/WarcraftGameContext.cs +++ b/Everlook/Utility/WarcraftGameContext.cs @@ -91,11 +91,11 @@ public FileReference GetReferenceForDoodad(DoodadInstance doodadInstance) } /// - public FileReference? GetReferenceForPath(string path) + public FileReference? GetReferenceForPath(string? path) { if (string.IsNullOrEmpty(path)) { - throw new ArgumentNullException(nameof(path)); + return null; } var treePath = this.FileTree.GetPath(path); diff --git a/Everlook/Viewport/Rendering/RenderableGameModel.cs b/Everlook/Viewport/Rendering/RenderableGameModel.cs index a16a7a8..3e1d4a0 100644 --- a/Everlook/Viewport/Rendering/RenderableGameModel.cs +++ b/Everlook/Viewport/Rendering/RenderableGameModel.cs @@ -101,10 +101,10 @@ public Vector3 DefaultCameraPosition public Transform ActorTransform { get; set; } /// - public int PolygonCount => (int)_model.Skins.Sum(s => s.Triangles.Count / 3); + public int PolygonCount => (int)_model.Skins!.Sum(s => s.Triangles!.Count / 3); /// - public int VertexCount => (int)_model.Vertices.Count; + public int VertexCount => (int)_model.Vertices!.Count; private readonly string? _modelPath; private readonly RenderCache _renderCache; @@ -199,7 +199,7 @@ public void Initialize() _vertexBuffer = new Buffer(this.GL, BufferTargetARB.ArrayBuffer, BufferUsageARB.StaticDraw) { - Data = _model.Vertices.Select(v => v.PackForOpenGL()).SelectMany(b => b).ToArray() + Data = _model.Vertices!.Select(v => v.PackForOpenGL()).SelectMany(b => b).ToArray() }; var attributePointers = new[] @@ -244,7 +244,7 @@ public void Initialize() _boundingBox = new RenderableBoundingBox(this.GL, _renderCache, _model.BoundingBox, this.ActorTransform); _boundingBox.Initialize(); - foreach (var texture in _model.Textures) + foreach (var texture in _model.Textures!) { if (!_textureLookup.ContainsKey(texture.Filename)) { @@ -256,11 +256,11 @@ public void Initialize() } } - foreach (var skin in _model.Skins) + foreach (var skin in _model.Skins!) { - var absoluteTriangleVertexIndexes = skin.Triangles.Select + var absoluteTriangleVertexIndexes = skin.Triangles!.Select ( - relativeIndex => skin.VertexIndices[relativeIndex] + relativeIndex => skin.VertexIndices![relativeIndex] ).ToArray(); var skinIndexBuffer = new Buffer @@ -281,7 +281,7 @@ public void Initialize() } // In models earlier than Cata, we need to calculate the shader selector value at runtime. - foreach (var renderBatch in skin.RenderBatches) + foreach (var renderBatch in skin.RenderBatches!) { var shaderSelector = MDXShaderHelper.GetRuntimeShaderID ( @@ -349,7 +349,7 @@ public void RenderInstances(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, Vi this.GL.Enable(EnableCap.Blend); } - foreach (var skin in _model.Skins) + foreach (var skin in _model.Skins!) { _skinIndexArrayBuffers[skin].Bind(); if (this.ShouldRenderWireframe) @@ -358,7 +358,7 @@ public void RenderInstances(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, Vi this.GL.Enable(EnableCap.Blend); } - foreach (var renderBatch in skin.RenderBatches) + foreach (var renderBatch in skin.RenderBatches!) { if (renderBatch.ShaderID == 0xFFFFu) { @@ -367,7 +367,7 @@ public void RenderInstances(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, Vi PrepareBatchForRender(renderBatch); - var skinSection = skin.Sections[renderBatch.SkinSectionIndex]; + var skinSection = skin.Sections![renderBatch.SkinSectionIndex]; unsafe { @@ -433,7 +433,7 @@ public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCam this.GL.Enable(EnableCap.Blend); } - foreach (var skin in _model.Skins) + foreach (var skin in _model.Skins!) { _skinIndexArrayBuffers[skin].Bind(); if (this.ShouldRenderWireframe) @@ -442,7 +442,7 @@ public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCam this.GL.Enable(EnableCap.Blend); } - foreach (var renderBatch in skin.RenderBatches) + foreach (var renderBatch in skin.RenderBatches!) { if (renderBatch.ShaderID == 0xFFFFu) { @@ -451,7 +451,7 @@ public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCam PrepareBatchForRender(renderBatch); - var skinSection = skin.Sections[renderBatch.SkinSectionIndex]; + var skinSection = skin.Sections![renderBatch.SkinSectionIndex]; unsafe { this.GL.DrawElements @@ -472,7 +472,7 @@ public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCam } // Release the attribute arrays - _vertexBuffer.DisableAttributes(); + _vertexBuffer?.DisableAttributes(); } /// @@ -484,7 +484,7 @@ private void PrepareBatchForRender(MDXRenderBatch renderBatch) { var fragmentShader = MDXShaderHelper.GetFragmentShaderType(renderBatch.TextureCount, renderBatch.ShaderID); var vertexShader = MDXShaderHelper.GetVertexShaderType(renderBatch.TextureCount, renderBatch.ShaderID); - var batchMaterial = _model.Materials[renderBatch.MaterialIndex]; + var batchMaterial = _model.Materials![renderBatch.MaterialIndex]; if (_shader is null) { @@ -498,7 +498,7 @@ private void PrepareBatchForRender(MDXRenderBatch renderBatch) var baseColour = Vector4.One; if (renderBatch.ColorIndex >= 0) { - var colorAnimation = _model.ColourAnimations[renderBatch.ColorIndex]; + var colorAnimation = _model.ColourAnimations![renderBatch.ColorIndex]; // TODO: Sample based on animated values RGB rgb; @@ -506,13 +506,13 @@ private void PrepareBatchForRender(MDXRenderBatch renderBatch) if (colorAnimation.ColourTrack.IsComposite) { - rgb = colorAnimation.ColourTrack.CompositeTimelineValues.First(); - alpha = (float)colorAnimation.OpacityTrack.CompositeTimelineValues.First() / 0x7fff; + rgb = colorAnimation.ColourTrack.CompositeTimelineValues!.First(); + alpha = (float)colorAnimation.OpacityTrack.CompositeTimelineValues!.First() / 0x7fff; } else { - rgb = colorAnimation.ColourTrack.Values.First().First(); - alpha = (float)colorAnimation.OpacityTrack.Values.First().First() / 0x7fff; + rgb = colorAnimation.ColourTrack.Values!.First().First(); + alpha = (float)colorAnimation.OpacityTrack.Values!.First().First() / 0x7fff; } baseColour = new Vector4 @@ -526,17 +526,17 @@ private void PrepareBatchForRender(MDXRenderBatch renderBatch) if ((short)renderBatch.TransparencyLookupTableIndex >= 0) { - var transparencyAnimationIndex = _model.TransparencyLookupTable[renderBatch.TransparencyLookupTableIndex]; - var transparencyAnimation = _model.TransparencyAnimations[transparencyAnimationIndex]; + var transparencyAnimationIndex = _model.TransparencyLookupTable![renderBatch.TransparencyLookupTableIndex]; + var transparencyAnimation = _model.TransparencyAnimations![transparencyAnimationIndex]; float alphaWeight; if (transparencyAnimation.Weight.IsComposite) { - alphaWeight = (float)transparencyAnimation.Weight.CompositeTimelineValues.First() / 0x7fff; + alphaWeight = (float)transparencyAnimation.Weight.CompositeTimelineValues!.First() / 0x7fff; } else { - alphaWeight = (float)transparencyAnimation.Weight.Values.First().First() / 0x7fff; + alphaWeight = (float)transparencyAnimation.Weight.Values!.First().First() / 0x7fff; } baseColour.W *= alphaWeight; @@ -544,9 +544,9 @@ private void PrepareBatchForRender(MDXRenderBatch renderBatch) _shader.SetBaseInputColour(baseColour); - var textureIndexes = _model.TextureLookupTable.Skip(renderBatch.TextureLookupTableIndex) + var textureIndexes = _model.TextureLookupTable!.Skip(renderBatch.TextureLookupTableIndex) .Take(renderBatch.TextureCount); - var textures = _model.Textures.Where((t, i) => textureIndexes.Contains((short)i)).ToList(); + var textures = _model.Textures!.Where((t, i) => textureIndexes.Contains((short)i)).ToList(); for (var i = 0; i < textures.Count; ++i) { @@ -626,7 +626,7 @@ public IEnumerable GetSkinVariations() r => string.Equals ( - Path.ChangeExtension(r.ModelPath.Value, "mdx"), + Path.ChangeExtension(r!.ModelPath.Value, "mdx"), Path.ChangeExtension(_modelPath, "mdx"), StringComparison.InvariantCultureIgnoreCase ) @@ -638,13 +638,13 @@ public IEnumerable GetSkinVariations() } // Then flatten out their IDs - var modelDataRecordIDs = modelDataRecords.Select(r => r.ID).ToList(); + var modelDataRecordIDs = modelDataRecords.Select(r => r!.ID).ToList(); // Then get any display info record which references this model var displayInfoDatabase = _gameContext.Database.GetDatabase(); var modelDisplayRecords = displayInfoDatabase.Where ( - r => modelDataRecordIDs.Contains(r.Model.Key) + r => modelDataRecordIDs.Contains(r!.Model.Key) ).ToList(); if (!modelDisplayRecords.Any()) @@ -660,6 +660,11 @@ public IEnumerable GetSkinVariations() // Finally, return any record with a unique set of textures foreach (var displayRecord in modelDisplayRecords) { + if (displayRecord is null) + { + continue; + } + if (textureListMapping.ContainsKey(displayRecord.TextureVariations)) { continue; @@ -700,7 +705,7 @@ public void SetDisplayInfoByID(int variationID) { this.CurrentDisplayInfo = _gameContext.Database.GetDatabase() .GetRecordByID(variationID); - CacheDisplayInfo(this.CurrentDisplayInfo); + CacheDisplayInfo(this.CurrentDisplayInfo!); } /// @@ -714,7 +719,7 @@ private void CacheDisplayInfo(CreatureDisplayInfoRecord displayInfoRecord) throw new InvalidOperationException(); } - foreach (var texture in _model.Textures) + foreach (var texture in _model.Textures!) { int textureIndex; switch (texture.TextureType) diff --git a/Everlook/Viewport/Rendering/RenderableWorldModel.cs b/Everlook/Viewport/Rendering/RenderableWorldModel.cs index 8fb24cb..b098f98 100644 --- a/Everlook/Viewport/Rendering/RenderableWorldModel.cs +++ b/Everlook/Viewport/Rendering/RenderableWorldModel.cs @@ -143,10 +143,10 @@ public Vector3 DefaultCameraPosition new Dictionary>>(); /// - public int PolygonCount => _model.Groups.Sum(g => g.GroupData.VertexIndices.VertexIndices.Count / 3); + public int PolygonCount => _model.Groups.Sum(g => g.GroupData.VertexIndices!.VertexIndices.Count / 3); /// - public int VertexCount => _model.Groups.Sum(g => g.GroupData.Vertices.Vertices.Count); + public int VertexCount => _model.Groups.Sum(g => g.GroupData.Vertices!.Vertices.Count); /// public bool IsInitialized { get; set; } @@ -341,7 +341,7 @@ public void LoadDoodads() doodadSetInstanceGroups.Add(instanceSet); } - _doodadSets.Add(doodadSet.Name, doodadSetInstanceGroups); + _doodadSets.Add(doodadSet.Name!, doodadSetInstanceGroups); } } @@ -469,7 +469,7 @@ public void Render(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, ViewportCam return; } - foreach (var doodadInstanceSet in _doodadSets[this.DoodadSet]) + foreach (var doodadInstanceSet in _doodadSets[this.DoodadSet!]) { doodadInstanceSet.ShouldRenderBounds = this.ShouldRenderBounds; } @@ -538,7 +538,7 @@ private void RenderGroup(ModelGroup modelGroup, Matrix4x4 modelViewProjection) _shader.SetMVPMatrix(modelViewProjection); // Set the texture as the first diffuse texture in unit 0 - var texture = _renderCache.GetCachedTexture(modelMaterial.DiffuseTexture); + var texture = _renderCache.GetCachedTexture(modelMaterial.DiffuseTexture!); texture.WrappingMode = modelMaterial.Flags.HasFlag(MaterialFlags.TextureWrappingClampS) ? TextureWrapMode.ClampToBorder : TextureWrapMode.Repeat; @@ -572,7 +572,7 @@ private void RenderGroup(ModelGroup modelGroup, Matrix4x4 modelViewProjection) /// The names of the doodad sets. public IEnumerable GetDoodadSetNames() { - return _model.RootInformation.DoodadSets.DoodadSets.Select(ds => ds.Name); + return _model.RootInformation.DoodadSets.DoodadSets.Select(ds => ds.Name!); } /// diff --git a/NuGet.config b/NuGet.config index e72b594..f072f57 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,8 +1,3 @@  - - - - - diff --git a/stylecop.json b/stylecop.json index 4a23c77..9e910ec 100644 --- a/stylecop.json +++ b/stylecop.json @@ -30,7 +30,8 @@ "db", "x", "y", - "z" + "z", + "uv" ] }, "maintainabilityRules" : { From c8ffa76f2e810ad07d798086d0b361a494d4352e Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Sun, 5 Apr 2020 17:13:24 +0200 Subject: [PATCH 18/18] Fix 3D movement. --- Everlook/UI/MainWindow.cs | 3 ++ Everlook/Viewport/ViewportRenderer.cs | 44 ++++++++++++++++++++------- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/Everlook/UI/MainWindow.cs b/Everlook/UI/MainWindow.cs index 6b01bff..8f6c83a 100644 --- a/Everlook/UI/MainWindow.cs +++ b/Everlook/UI/MainWindow.cs @@ -973,6 +973,9 @@ private void OnViewportButtonPressed(object o, ButtonPressEventArgs args) _renderingEngine.InitialMouseX = args.Event.X; _renderingEngine.InitialMouseY = args.Event.Y; + _renderingEngine.CurrentMouseX = args.Event.X; + _renderingEngine.CurrentMouseY = args.Event.Y; + _renderingEngine.WantsToMove = true; } diff --git a/Everlook/Viewport/ViewportRenderer.cs b/Everlook/Viewport/ViewportRenderer.cs index 720b223..782be62 100644 --- a/Everlook/Viewport/ViewportRenderer.cs +++ b/Everlook/Viewport/ViewportRenderer.cs @@ -30,8 +30,11 @@ using Everlook.Viewport.Rendering.Core; using Everlook.Viewport.Rendering.Interfaces; using Gdk; +using Gtk; using log4net; using Silk.NET.OpenGL; +using Key = Gdk.Key; +using Window = Gtk.Window; namespace Everlook.Viewport { @@ -186,8 +189,22 @@ public ViewportRenderer(GL gl, RenderCache renderCache, ViewportArea viewportWid return; } - this.CurrentMouseX = args.Event.X; - this.CurrentMouseY = args.Event.Y; + if + ( + Math.Abs(args.Event.X - this.InitialMouseX) < 1.0f && + Math.Abs(args.Event.Y - this.InitialMouseY) < 1.0f + ) + { + // When we warp the mouse, there may be some floating-point errors. We take a tolerance of one + // pixel, and reset the current to initial if we're within that tolerance. + this.CurrentMouseX = this.InitialMouseX; + this.CurrentMouseY = this.InitialMouseY; + } + else + { + this.CurrentMouseX = args.Event.X; + this.CurrentMouseY = args.Event.Y; + } }; _viewportWidget.KeyPressEvent += (o, args) => @@ -482,18 +499,23 @@ private void Calculate3DMovement() _movement.Calculate3DMovement(deltaMouseX, deltaMouseY, this.DeltaTime); - // Return the mouse to its original position - /*motionEvent.Device.Warp + _viewportWidget.Toplevel.Window.GetOrigin(out var windowX, out var windowY); + _viewportWidget.TranslateCoordinates ( - motionEvent.Window.Screen, - (int)(motionEvent.XRoot - deltaMouseX), - (int)(motionEvent.YRoot - deltaMouseY) + _viewportWidget.Toplevel, + 0, + 0, + out var widgetX, + out var widgetY ); - */ - // Update the initial location for the next frame - this.InitialMouseX = this.CurrentMouseX; - this.InitialMouseY = this.CurrentMouseY; + // Return the mouse to its original position + Display.Default.DeviceManager.ClientPointer.Warp + ( + Screen.Default, + (int)(windowX + this.InitialMouseX + widgetX), + (int)(windowY + this.InitialMouseY + widgetY) + ); } ///