1.0.14
NUGET-Changes: + Materials now have a method to draw. That should allow more freedom on how materials can have a effect on the resulting shader. ~ PostProcessEffect.Draw now needs a source ColorAttachment. ~ Added some missing summaries GIT-/SOLUTION-Changes: Remade the folder structure, to something more senseable.
This commit is contained in:
parent
db7f01dca1
commit
89de4258e1
181 changed files with 584 additions and 698 deletions
25
src/optionals/SM.Intergrations/OpenTK.dll.config
Normal file
25
src/optionals/SM.Intergrations/OpenTK.dll.config
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<configuration>
|
||||
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||
<dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
|
||||
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
|
||||
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
|
||||
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
|
||||
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
|
||||
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
|
||||
<dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
|
||||
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
|
||||
<dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
|
||||
<!-- XQuartz compatibility (X11 on Mac) -->
|
||||
<dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/>
|
||||
<dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/>
|
||||
<dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/>
|
||||
<dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/>
|
||||
<dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/>
|
||||
<dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/>
|
||||
</configuration>
|
||||
36
src/optionals/SM.Intergrations/Properties/AssemblyInfo.cs
Normal file
36
src/optionals/SM.Intergrations/Properties/AssemblyInfo.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("SM.Intergrations")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("SM.Intergrations")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2021")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("4cb351f4-b3f2-4f77-acc2-02f21dbf5ec2")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
73
src/optionals/SM.Intergrations/SM.Intergrations.csproj
Normal file
73
src/optionals/SM.Intergrations/SM.Intergrations.csproj
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{4CB351F4-B3F2-4F77-ACC2-02F21DBF5EC2}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SM.Intergrations</RootNamespace>
|
||||
<AssemblyName>SM.Intergrations</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="OpenTK, Version=3.3.1.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\OpenTK.3.3.1\lib\net20\OpenTK.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ShaderToolParser, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\ShaderToolParser.1.0.0-pre3\lib\net450\ShaderToolParser.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ShaderTool\STMaterial.cs" />
|
||||
<Compile Include="ShaderTool\STMaterialShader.cs" />
|
||||
<Compile Include="ShaderTool\STPostProcessEffect.cs" />
|
||||
<Compile Include="ShaderTool\STPostProcessShader.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\renderer\SM.Base\SM.Base.csproj">
|
||||
<Project>{8e733844-4204-43e7-b3dc-3913cddabb0d}</Project>
|
||||
<Name>SM.Base</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\renderer\SM.OGL\SM.OGL.csproj">
|
||||
<Project>{f604d684-bc1d-4819-88b5-8b5d03a17be0}</Project>
|
||||
<Name>SM.OGL</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="OpenTK.dll.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
50
src/optionals/SM.Intergrations/ShaderTool/STMaterial.cs
Normal file
50
src/optionals/SM.Intergrations/ShaderTool/STMaterial.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Pipes;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using ShaderToolParser.Nodes;
|
||||
using ShaderToolParser.Nodes.Textures;
|
||||
using ShaderToolParser.Variables;
|
||||
using SM.Base.Drawing;
|
||||
using SM.Base.Textures;
|
||||
using SM.Base.Window;
|
||||
|
||||
namespace SM.Intergrations.ShaderTool
|
||||
{
|
||||
public class STMaterial : Material
|
||||
{
|
||||
private Vector4 _tintVector = Vector4.One;
|
||||
|
||||
public override Color4 Tint
|
||||
{
|
||||
get => Color4.FromXyz(_tintVector);
|
||||
set => _tintVector = Color4.ToXyz(value);
|
||||
}
|
||||
|
||||
public STMaterial(STPDrawNode node)
|
||||
{
|
||||
if (node.OGLEffect == null)
|
||||
throw new Exception("[ERROR AT IMPORTING MATERIAL] DrawNode didn't contain a OpenGL-shader.");
|
||||
|
||||
CustomShader = new STMaterialShader(node);
|
||||
|
||||
foreach (KeyValuePair<string, STPVariable> pair in node.Variables)
|
||||
{
|
||||
if (pair.Value.Type == STPBasisType.Texture)
|
||||
ShaderArguments[pair.Key] = new Texture(((STPTextureNode) pair.Value.Texture).Bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Draw(DrawContext context)
|
||||
{
|
||||
ShaderArguments["MVP"] = context.Instances[0].ModelMatrix * context.ModelMatrix * context.View * context.World;
|
||||
ShaderArguments["MasterTextureMatrix"] = context.Instances[0].TextureMatrix * context.TextureMatrix;
|
||||
ShaderArguments["HasVColor"] = context.Mesh.Attributes.Has("color");
|
||||
|
||||
ShaderArguments["_MATColor"] = _tintVector;
|
||||
|
||||
base.Draw(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenTK;
|
||||
using ShaderToolParser.Nodes;
|
||||
using ShaderToolParser.Variables;
|
||||
using SM.Base.Shaders;
|
||||
using SM.Base.Textures;
|
||||
using SM.Base.Window;
|
||||
using SM.OGL.Shaders;
|
||||
using SM.OGL.Texture;
|
||||
|
||||
namespace SM.Intergrations.ShaderTool
|
||||
{
|
||||
public class STMaterialShader : MaterialShader
|
||||
{
|
||||
private event Action<DrawContext> _uniforms;
|
||||
|
||||
public STMaterialShader(STPDrawNode drawNode) : base(new ShaderFileCollection())
|
||||
{
|
||||
if (drawNode.OGLEffect == null)
|
||||
throw new Exception("[ERROR AT IMPORTING SHADER] DrawNode didn't contain a OpenGL-shader.");
|
||||
|
||||
STPCompositeNode composeNode = drawNode.OGLEffect;
|
||||
|
||||
ShaderFileFiles.Vertex = new[] { new ShaderFile(composeNode.Vertex.ShaderCode) };
|
||||
ShaderFileFiles.Fragment = new [] {new ShaderFile(composeNode.Fragment.ShaderCode)};
|
||||
if (composeNode.Geometry != null)
|
||||
ShaderFileFiles.Geometry = new[] {new ShaderFile(composeNode.Geometry.ShaderCode)};
|
||||
|
||||
foreach (KeyValuePair<string, STPVariable> pair in drawNode.Variables)
|
||||
{
|
||||
switch (pair.Value.Type)
|
||||
{
|
||||
case STPBasisType.Bool:
|
||||
_uniforms += context => Uniforms[pair.Key].SetUniform1(context.Material.ShaderArguments.Get(pair.Key, false));
|
||||
break;
|
||||
case STPBasisType.Float:
|
||||
_uniforms += context => Uniforms[pair.Key].SetUniform1(context.Material.ShaderArguments.Get(pair.Key, 0.0f));
|
||||
break;
|
||||
case STPBasisType.Vector2:
|
||||
_uniforms += context => Uniforms[pair.Key].SetUniform2(context.Material.ShaderArguments.Get(pair.Key, Vector2.Zero));
|
||||
break;
|
||||
case STPBasisType.Vector3:
|
||||
_uniforms += context => Uniforms[pair.Key].SetUniform3(context.Material.ShaderArguments.Get(pair.Key, Vector3.Zero));
|
||||
break;
|
||||
case STPBasisType.Vector4:
|
||||
_uniforms += context =>
|
||||
Uniforms[pair.Key].SetUniform4(context.Material.ShaderArguments.Get(pair.Key, Vector4.Zero));
|
||||
break;
|
||||
case STPBasisType.Matrix:
|
||||
_uniforms += context => Uniforms[pair.Key].SetMatrix4(context.Material.ShaderArguments.Get(pair.Key, Matrix4.Identity));
|
||||
break;
|
||||
case STPBasisType.Texture:
|
||||
_uniforms += context => Uniforms[pair.Key].SetTexture(context.Material.ShaderArguments.Get<TextureBase>(pair.Key, null));
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DrawProcess(DrawContext context)
|
||||
{
|
||||
_uniforms.Invoke(context);
|
||||
|
||||
DrawObject(context.ForcedType.GetValueOrDefault(context.Mesh.PrimitiveType), context.Mesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using ShaderToolParser.Nodes;
|
||||
using ShaderToolParser.Nodes.Textures;
|
||||
using ShaderToolParser.Variables;
|
||||
using SM.Base.Drawing;
|
||||
using SM.Base.PostProcess;
|
||||
using SM.Base.Textures;
|
||||
using SM.Base.Window;
|
||||
using SM.OGL.Framebuffer;
|
||||
using SM.OGL.Texture;
|
||||
|
||||
namespace SM.Intergrations.ShaderTool
|
||||
{
|
||||
public class STPostProcessEffect : PostProcessEffect
|
||||
{
|
||||
private STPostProcessShader _shader;
|
||||
|
||||
public ShaderArguments Arguments;
|
||||
|
||||
public STPostProcessEffect(STPDrawNode postEffectNode)
|
||||
{
|
||||
Arguments = Arguments ?? new ShaderArguments();
|
||||
|
||||
if (postEffectNode.OGLEffect == null)
|
||||
throw new Exception("[ERROR AT IMPORTING EFFECT] DrawNode didn't contain a OpenGL-shader.");
|
||||
|
||||
_shader = new STPostProcessShader(postEffectNode);
|
||||
|
||||
foreach (KeyValuePair<string, STPVariable> pair in postEffectNode.Variables)
|
||||
{
|
||||
|
||||
if (pair.Value.Type == STPBasisType.Texture)
|
||||
{
|
||||
if (pair.Value.Texture == null) continue;
|
||||
Arguments[pair.Key] = new Texture(((STPTextureNode)pair.Value.Texture).Bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Draw(ColorAttachment source, DrawContext context)
|
||||
{
|
||||
Arguments["_Scene"] = (TextureBase)source;
|
||||
Arguments["_MVP"] = Mvp;
|
||||
Arguments["_ViewportSize"] = context.Window.WindowSize;
|
||||
|
||||
_shader.Draw(Arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using ShaderToolParser.Nodes;
|
||||
using ShaderToolParser.Variables;
|
||||
using SM.Base.Drawing;
|
||||
using SM.Base.Objects.Static;
|
||||
using SM.Base.Textures;
|
||||
using SM.OGL.Shaders;
|
||||
using SM.OGL.Texture;
|
||||
|
||||
namespace SM.Intergrations.ShaderTool
|
||||
{
|
||||
public class STPostProcessShader : GenericShader
|
||||
{
|
||||
private event Action<ShaderArguments> _uniforms;
|
||||
|
||||
public STPostProcessShader(STPDrawNode postProcessNode) : base(new ShaderFileCollection())
|
||||
{
|
||||
if (postProcessNode.OGLEffect == null)
|
||||
throw new Exception("[ERROR AT IMPORTING SHADER] DrawNode didn't contain a OpenGL-shader.");
|
||||
|
||||
STPCompositeNode composeNode = postProcessNode.OGLEffect;
|
||||
|
||||
ShaderFileFiles.Vertex = new[] { new ShaderFile(composeNode.Vertex.ShaderCode) };
|
||||
ShaderFileFiles.Fragment = new[] { new ShaderFile(composeNode.Fragment.ShaderCode) };
|
||||
if (composeNode.Geometry != null)
|
||||
ShaderFileFiles.Geometry = new[] { new ShaderFile(composeNode.Geometry.ShaderCode) };
|
||||
|
||||
foreach (KeyValuePair<string, STPVariable> pair in postProcessNode.Variables)
|
||||
{
|
||||
switch (pair.Value.Type)
|
||||
{
|
||||
case STPBasisType.Bool:
|
||||
_uniforms += context => Uniforms[pair.Key].SetUniform1(context.Get(pair.Key, false));
|
||||
break;
|
||||
case STPBasisType.Float:
|
||||
_uniforms += context => Uniforms[pair.Key].SetUniform1(context.Get(pair.Key, 0.0f));
|
||||
break;
|
||||
case STPBasisType.Vector2:
|
||||
_uniforms += context => Uniforms[pair.Key].SetUniform2(context.Get(pair.Key, Vector2.Zero));
|
||||
break;
|
||||
case STPBasisType.Vector3:
|
||||
_uniforms += context => Uniforms[pair.Key].SetUniform3(context.Get(pair.Key, Vector3.Zero));
|
||||
break;
|
||||
case STPBasisType.Vector4:
|
||||
_uniforms += context =>
|
||||
Uniforms[pair.Key].SetUniform4(context.Get(pair.Key, Vector4.Zero));
|
||||
break;
|
||||
case STPBasisType.Matrix:
|
||||
_uniforms += context => Uniforms[pair.Key].SetMatrix4(context.Get(pair.Key, Matrix4.Identity));
|
||||
break;
|
||||
case STPBasisType.Texture:
|
||||
_uniforms += context => Uniforms[pair.Key].SetTexture(context.Get<TextureBase>(pair.Key, null));
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(ShaderArguments arguments)
|
||||
{
|
||||
Activate();
|
||||
Plate.Object.Activate();
|
||||
|
||||
_uniforms.Invoke(arguments);
|
||||
|
||||
GL.DrawArrays(PrimitiveType.Quads, 0, 4);
|
||||
CleanUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
5
src/optionals/SM.Intergrations/packages.config
Normal file
5
src/optionals/SM.Intergrations/packages.config
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="OpenTK" version="3.3.1" targetFramework="net452" />
|
||||
<package id="ShaderToolParser" version="1.0.0-pre3" targetFramework="net452" />
|
||||
</packages>
|
||||
39
src/optionals/SM.Utils/Controls/GameController.cs
Normal file
39
src/optionals/SM.Utils/Controls/GameController.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
using SharpDX.XInput;
|
||||
|
||||
namespace SM.Optionals.Controls
|
||||
{
|
||||
public struct GameController
|
||||
{
|
||||
public static float GlobalDeadband = 2500;
|
||||
|
||||
private Controller _controller;
|
||||
|
||||
public float Deadband { get; set; }
|
||||
public bool IsConnected => _controller.IsConnected;
|
||||
|
||||
public UserIndex Index { get; private set; }
|
||||
|
||||
public GameController(int id) : this((UserIndex)id)
|
||||
{}
|
||||
|
||||
public GameController(UserIndex index = UserIndex.Any)
|
||||
{
|
||||
_controller = new Controller(index);
|
||||
Index = index;
|
||||
Deadband = GlobalDeadband;
|
||||
}
|
||||
|
||||
public GameControllerState GetState()
|
||||
{
|
||||
if (!IsConnected)
|
||||
{
|
||||
return new GameControllerState(true);
|
||||
}
|
||||
|
||||
Gamepad state = _controller.GetState().Gamepad;
|
||||
|
||||
return new GameControllerState(state, ref this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
57
src/optionals/SM.Utils/Controls/GameControllerState.cs
Normal file
57
src/optionals/SM.Utils/Controls/GameControllerState.cs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
using System;
|
||||
using OpenTK;
|
||||
using SharpDX.XInput;
|
||||
|
||||
namespace SM.Optionals.Controls
|
||||
{
|
||||
public struct GameControllerState
|
||||
{
|
||||
public GameControllerStateThumbs Thumbs;
|
||||
public GameControllerStateTriggers Triggers;
|
||||
public GameControllerStateDPad DPad;
|
||||
public GameControllerStateButtons Buttons;
|
||||
|
||||
public bool FromConnected { get; }
|
||||
|
||||
internal GameControllerState(bool empty)
|
||||
{
|
||||
FromConnected = false;
|
||||
|
||||
Thumbs = GameControllerStateThumbs.Default;
|
||||
Triggers = GameControllerStateTriggers.Default;
|
||||
DPad = GameControllerStateDPad.Default;
|
||||
Buttons = GameControllerStateButtons.Default;
|
||||
}
|
||||
internal GameControllerState(Gamepad state, ref GameController controller)
|
||||
{
|
||||
FromConnected = true;
|
||||
|
||||
Thumbs = new GameControllerStateThumbs
|
||||
{
|
||||
Left = new Vector2(
|
||||
Math.Abs((float)state.LeftThumbX) < controller.Deadband ? 0 : (float)state.LeftThumbX / short.MaxValue,
|
||||
Math.Abs((float)state.LeftThumbY) < controller.Deadband ? 0 : (float)state.LeftThumbY / short.MaxValue),
|
||||
Right = new Vector2(
|
||||
Math.Abs((float)state.RightThumbX) < controller.Deadband ? 0 : (float)state.RightThumbX / short.MaxValue,
|
||||
Math.Abs((float)state.RightThumbY) < controller.Deadband ? 0 : (float)state.RightThumbY / short.MaxValue),
|
||||
|
||||
PressedLeft = state.Buttons.HasFlag(GamepadButtonFlags.LeftThumb),
|
||||
PressedRight = state.Buttons.HasFlag(GamepadButtonFlags.RightThumb)
|
||||
};
|
||||
|
||||
Triggers = new GameControllerStateTriggers()
|
||||
{
|
||||
Left = (float)state.LeftTrigger / byte.MaxValue,
|
||||
Right = (float)state.RightTrigger / byte.MaxValue
|
||||
};
|
||||
|
||||
DPad = new GameControllerStateDPad(state.Buttons);
|
||||
Buttons = new GameControllerStateButtons(state.Buttons);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return !FromConnected ? "[From a disconnected controller]" : $"Thumbs: [{Thumbs}]; Trigger: [{Triggers}]; DPad: [{DPad}]; Buttons: [{Buttons}]";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
using SharpDX.XInput;
|
||||
|
||||
namespace SM.Optionals.Controls
|
||||
{
|
||||
public struct GameControllerStateButtons
|
||||
{
|
||||
public static GameControllerStateButtons Default = new GameControllerStateButtons(GamepadButtonFlags.None);
|
||||
|
||||
private GamepadButtonFlags _buttonFlags;
|
||||
|
||||
public bool X;
|
||||
public bool Y;
|
||||
public bool A;
|
||||
public bool B;
|
||||
|
||||
public bool LB;
|
||||
public bool RB;
|
||||
|
||||
public bool LeftThumb;
|
||||
public bool RightThumb;
|
||||
|
||||
public bool this[GamepadButtonFlags flags] => _buttonFlags.HasFlag(flags);
|
||||
|
||||
internal GameControllerStateButtons(GamepadButtonFlags flags)
|
||||
{
|
||||
_buttonFlags = flags;
|
||||
|
||||
X = flags.HasFlag(GamepadButtonFlags.X);
|
||||
Y = flags.HasFlag(GamepadButtonFlags.Y);
|
||||
A = flags.HasFlag(GamepadButtonFlags.A);
|
||||
B = flags.HasFlag(GamepadButtonFlags.B);
|
||||
|
||||
LB = flags.HasFlag(GamepadButtonFlags.LeftShoulder);
|
||||
RB = flags.HasFlag(GamepadButtonFlags.RightShoulder);
|
||||
|
||||
LeftThumb = flags.HasFlag(GamepadButtonFlags.LeftThumb);
|
||||
RightThumb = flags.HasFlag(GamepadButtonFlags.RightThumb);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"X: {(X ? "1" : "0")}; Y: {(Y ? "1" : "0")}; A: {(A ? "1" : "0")}; B: {(B ? "1" : "0")}; LB: {(LB ? "1" : "0")}; RB: {(RB ? "1" : "0")}; LT: {(LeftThumb ? "1" : "0")}; RT: {(RightThumb ? "1" : "0")}";
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/optionals/SM.Utils/Controls/GameControllerStateDPad.cs
Normal file
28
src/optionals/SM.Utils/Controls/GameControllerStateDPad.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
using SharpDX.XInput;
|
||||
|
||||
namespace SM.Optionals.Controls
|
||||
{
|
||||
public struct GameControllerStateDPad
|
||||
{
|
||||
public static GameControllerStateDPad Default = new GameControllerStateDPad(GamepadButtonFlags.None);
|
||||
|
||||
public bool Up;
|
||||
public bool Down;
|
||||
public bool Left;
|
||||
public bool Right;
|
||||
|
||||
internal GameControllerStateDPad(GamepadButtonFlags flags)
|
||||
{
|
||||
Up = flags.HasFlag(GamepadButtonFlags.DPadUp);
|
||||
Down = flags.HasFlag(GamepadButtonFlags.DPadDown);
|
||||
Left = flags.HasFlag(GamepadButtonFlags.DPadLeft);
|
||||
Right = flags.HasFlag(GamepadButtonFlags.DPadRight);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return
|
||||
$"Up: {(Up ? "1" : "0")}; Down: {(Down ? "1" : "0")}; Left: {(Left ? "1" : "0")}; Right: {(Right ? "1" : "0")};";
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/optionals/SM.Utils/Controls/GameControllerStateThumbs.cs
Normal file
21
src/optionals/SM.Utils/Controls/GameControllerStateThumbs.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
using OpenTK;
|
||||
|
||||
namespace SM.Optionals.Controls
|
||||
{
|
||||
public struct GameControllerStateThumbs
|
||||
{
|
||||
public static GameControllerStateThumbs Default = new GameControllerStateThumbs()
|
||||
{Left = Vector2.Zero, Right = Vector2.Zero};
|
||||
|
||||
public Vector2 Left;
|
||||
public Vector2 Right;
|
||||
|
||||
public bool PressedLeft;
|
||||
public bool PressedRight;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Left: ({Left.X}; {Left.Y}){(PressedLeft ? " Pressed" : "")}; Right: ({Right.X}; {Right.Y}){(PressedRight ? " Pressed" : "")}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
namespace SM.Optionals.Controls
|
||||
{
|
||||
public struct GameControllerStateTriggers
|
||||
{
|
||||
public static GameControllerStateTriggers Default = new GameControllerStateTriggers {Left = 0f, Right = 0f};
|
||||
|
||||
public float Left;
|
||||
public float Right;
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Left: {Left}; Right: {Right}";
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/optionals/SM.Utils/Controls/GameKeybind.cs
Normal file
29
src/optionals/SM.Utils/Controls/GameKeybind.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
|
||||
namespace SM.Optionals.Controls
|
||||
{
|
||||
public class GameKeybind
|
||||
{
|
||||
public Func<GameKeybindContext, object> Keyboard;
|
||||
public Func<GameKeybindContext, object> Controller;
|
||||
public Func<GameKeybindContext, object> AI;
|
||||
|
||||
public Func<GameKeybindContext, object> this[GameKeybindActorType type]
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case GameKeybindActorType.AI:
|
||||
return AI;
|
||||
case GameKeybindActorType.Keyboard:
|
||||
return Keyboard;
|
||||
case GameKeybindActorType.Controller:
|
||||
return Controller;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(type), type, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
88
src/optionals/SM.Utils/Controls/GameKeybindActor.cs
Normal file
88
src/optionals/SM.Utils/Controls/GameKeybindActor.cs
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
using OpenTK.Input;
|
||||
|
||||
namespace SM.Optionals.Controls
|
||||
{
|
||||
public enum GameKeybindActorType
|
||||
{
|
||||
AI,
|
||||
Keyboard,
|
||||
Controller
|
||||
}
|
||||
|
||||
public struct GameKeybindActor
|
||||
{
|
||||
private GameKeybindActorType _type;
|
||||
private GameController? _controller;
|
||||
|
||||
private GameKeybindHost _keybindHost;
|
||||
|
||||
public GameKeybindActorType Type => _type;
|
||||
public GameController? Controller => _controller;
|
||||
|
||||
public object[] Parameter;
|
||||
|
||||
private GameKeybindActor(GameKeybindActorType type, GameController? controller)
|
||||
{
|
||||
_type = type;
|
||||
_controller = controller;
|
||||
|
||||
_keybindHost = null;
|
||||
|
||||
Parameter = new object[0];
|
||||
}
|
||||
|
||||
public void ConnectHost(GameKeybindHost host)
|
||||
{
|
||||
_keybindHost = host;
|
||||
}
|
||||
|
||||
public ReturnType Get<ReturnType>(string name, params object[] param)
|
||||
{
|
||||
return (ReturnType) Get(name, param);
|
||||
}
|
||||
|
||||
public object Get(string name, params object[] objects)
|
||||
{
|
||||
if (_keybindHost == null) return null;
|
||||
if (!_keybindHost._actions.ContainsKey(name)) return null;
|
||||
|
||||
GameKeybind keybind = _keybindHost._actions[name];
|
||||
|
||||
GameKeybindContext context = new GameKeybindContext()
|
||||
{
|
||||
Actor = this,
|
||||
Host = _keybindHost,
|
||||
|
||||
ActorParameter = Parameter,
|
||||
InstanceParameter = objects,
|
||||
|
||||
KeyboardState = Keyboard.GetState(),
|
||||
MouseState = Mouse.GetState(),
|
||||
ControllerState = Controller?.GetState(),
|
||||
};
|
||||
|
||||
return keybind[Type].Invoke(context);
|
||||
}
|
||||
|
||||
public static GameKeybindActor CreateAIActor()
|
||||
{
|
||||
return new GameKeybindActor(GameKeybindActorType.AI, null);
|
||||
}
|
||||
|
||||
public static GameKeybindActor CreateKeyboardActor()
|
||||
{
|
||||
return new GameKeybindActor(GameKeybindActorType.Keyboard, null);
|
||||
}
|
||||
|
||||
public static GameKeybindActor CreateControllerActor(int id)
|
||||
{
|
||||
return CreateControllerActor(new GameController(id));
|
||||
}
|
||||
|
||||
public static GameKeybindActor CreateControllerActor(GameController controller)
|
||||
{
|
||||
return new GameKeybindActor(GameKeybindActorType.Controller, controller);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
17
src/optionals/SM.Utils/Controls/GameKeybindContext.cs
Normal file
17
src/optionals/SM.Utils/Controls/GameKeybindContext.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
using OpenTK.Input;
|
||||
|
||||
namespace SM.Optionals.Controls
|
||||
{
|
||||
public struct GameKeybindContext
|
||||
{
|
||||
public KeyboardState KeyboardState;
|
||||
public MouseState MouseState;
|
||||
public GameControllerState? ControllerState;
|
||||
|
||||
public GameKeybindActor Actor;
|
||||
public GameKeybindHost Host;
|
||||
|
||||
public object[] InstanceParameter;
|
||||
public object[] ActorParameter;
|
||||
}
|
||||
}
|
||||
39
src/optionals/SM.Utils/Controls/GameKeybindHost.cs
Normal file
39
src/optionals/SM.Utils/Controls/GameKeybindHost.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SM.Optionals.Controls
|
||||
{
|
||||
public class GameKeybindHost
|
||||
{
|
||||
internal Dictionary<string, GameKeybind> _actions = new Dictionary<string, GameKeybind>();
|
||||
|
||||
public GameKeybindHost()
|
||||
{ }
|
||||
|
||||
public GameKeybindHost(GameKeybindList setup)
|
||||
{
|
||||
for (int i = 0; i < setup.Count; i++)
|
||||
{
|
||||
_actions[setup[i].Key] = setup[i].Value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Setup(string name, Func<GameKeybindContext, object> keyboard = null, Func<GameKeybindContext, object> gameController = null, Func<GameKeybindContext, object> ai = null)
|
||||
{
|
||||
GameKeybind bind;
|
||||
if (_actions.ContainsKey(name))
|
||||
{
|
||||
bind = _actions[name];
|
||||
}
|
||||
else
|
||||
{
|
||||
bind = new GameKeybind();
|
||||
_actions.Add(name, bind);
|
||||
}
|
||||
|
||||
bind.Keyboard = keyboard;
|
||||
bind.Controller = gameController;
|
||||
bind.AI = ai;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
src/optionals/SM.Utils/Controls/GameKeybindList.cs
Normal file
24
src/optionals/SM.Utils/Controls/GameKeybindList.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SM.Optionals.Controls
|
||||
{
|
||||
public class GameKeybindList : List<KeyValuePair<string, GameKeybind>>
|
||||
{
|
||||
public void Add(string name, GameKeybind keybind)
|
||||
{
|
||||
Add(new KeyValuePair<string, GameKeybind>(name, keybind));
|
||||
}
|
||||
|
||||
public void Add(string name, Func<GameKeybindContext, object> keyboard = null,
|
||||
Func<GameKeybindContext, object> controller = null)
|
||||
{
|
||||
Add(new KeyValuePair<string, GameKeybind>(name, new GameKeybind()
|
||||
{
|
||||
AI = null,
|
||||
Controller = controller,
|
||||
Keyboard = keyboard
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
25
src/optionals/SM.Utils/OpenTK.dll.config
Normal file
25
src/optionals/SM.Utils/OpenTK.dll.config
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<configuration>
|
||||
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||
<dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
|
||||
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
|
||||
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
|
||||
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
|
||||
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
|
||||
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
|
||||
<dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
|
||||
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
|
||||
<dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
|
||||
<!-- XQuartz compatibility (X11 on Mac) -->
|
||||
<dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/>
|
||||
<dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/>
|
||||
<dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/>
|
||||
<dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/>
|
||||
<dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/>
|
||||
<dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/>
|
||||
</configuration>
|
||||
35
src/optionals/SM.Utils/Properties/AssemblyInfo.cs
Normal file
35
src/optionals/SM.Utils/Properties/AssemblyInfo.cs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("SM.Game")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("SM.Game")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2021")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("079bab31-3dc4-40da-90c7-efaa8517c647")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
65
src/optionals/SM.Utils/SM.Utils.csproj
Normal file
65
src/optionals/SM.Utils/SM.Utils.csproj
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{079BAB31-3DC4-40DA-90C7-EFAA8517C647}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SM.Utils</RootNamespace>
|
||||
<AssemblyName>SM.Utils</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="OpenTK, Version=3.3.1.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\OpenTK.3.3.1\lib\net20\OpenTK.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SharpDX, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\SharpDX.4.2.0\lib\net45\SharpDX.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SharpDX.XInput, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\SharpDX.XInput.4.2.0\lib\net45\SharpDX.XInput.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Controls\GameController.cs" />
|
||||
<Compile Include="Controls\GameControllerState.cs" />
|
||||
<Compile Include="Controls\GameControllerStateButtons.cs" />
|
||||
<Compile Include="Controls\GameControllerStateDPad.cs" />
|
||||
<Compile Include="Controls\GameControllerStateThumbs.cs" />
|
||||
<Compile Include="Controls\GameControllerStateTriggers.cs" />
|
||||
<Compile Include="Controls\GameKeybind.cs" />
|
||||
<Compile Include="Controls\GameKeybindActor.cs" />
|
||||
<Compile Include="Controls\GameKeybindContext.cs" />
|
||||
<Compile Include="Controls\GameKeybindHost.cs" />
|
||||
<Compile Include="Controls\GameKeybindList.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="OpenTK.dll.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
6
src/optionals/SM.Utils/packages.config
Normal file
6
src/optionals/SM.Utils/packages.config
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="OpenTK" version="3.3.1" targetFramework="net452" />
|
||||
<package id="SharpDX" version="4.2.0" targetFramework="net452" />
|
||||
<package id="SharpDX.XInput" version="4.2.0" targetFramework="net452" />
|
||||
</packages>
|
||||
20
src/renderer/SM.Base/Animation/AnimationCurves.cs
Normal file
20
src/renderer/SM.Base/Animation/AnimationCurves.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
using OpenTK;
|
||||
|
||||
namespace SM.Base.Animation
|
||||
{
|
||||
/// <summary>
|
||||
/// Preset Animation curves.
|
||||
/// </summary>
|
||||
public class AnimationCurves
|
||||
{
|
||||
/// <summary>
|
||||
/// Linear Curve
|
||||
/// </summary>
|
||||
public static readonly BezierCurve Linear = new BezierCurve(Vector2.Zero, Vector2.One);
|
||||
|
||||
/// <summary>
|
||||
/// Smooth curve
|
||||
/// </summary>
|
||||
public static readonly BezierCurve Smooth = new BezierCurve(Vector2.Zero, new Vector2(.5f, 0), new Vector2(.5f, 1), Vector2.One);
|
||||
}
|
||||
}
|
||||
90
src/renderer/SM.Base/Animation/InterpolationProcess.cs
Normal file
90
src/renderer/SM.Base/Animation/InterpolationProcess.cs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
using System;
|
||||
using OpenTK;
|
||||
using SM.Base.Time;
|
||||
using SM.Base.Types;
|
||||
using SM.Base.Window;
|
||||
|
||||
namespace SM.Base.Animation
|
||||
{
|
||||
/// <summary>
|
||||
/// A handle to control the interpolation process.
|
||||
/// </summary>
|
||||
public class InterpolationProcess : Timer
|
||||
{
|
||||
/// <summary>
|
||||
/// The CVector object, that is interpolated.
|
||||
/// </summary>
|
||||
public CVectorBase TargetVector { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// From where the interpolation process started.
|
||||
/// </summary>
|
||||
public Vector4 From { get; }
|
||||
/// <summary>
|
||||
/// To where the interpolation is heading.
|
||||
/// </summary>
|
||||
public Vector4 To { get; }
|
||||
/// <summary>
|
||||
/// The direction towards the <see cref="To"/>
|
||||
/// </summary>
|
||||
public Vector4 Direction { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets/Sets the interpolation curve.
|
||||
/// </summary>
|
||||
public BezierCurve InterpolationCurve { get; set; }
|
||||
|
||||
internal InterpolationProcess(CVectorBase targetVector, TimeSpan timeSpan, Vector4 from, Vector4 to, BezierCurve interpolationCurve) : base(timeSpan)
|
||||
{
|
||||
TargetVector = targetVector;
|
||||
|
||||
From = from;
|
||||
To = to;
|
||||
InterpolationCurve = interpolationCurve;
|
||||
|
||||
Direction = to - from;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the interpolation process.
|
||||
/// <para>This keeps the state where the interpolation was.</para>
|
||||
/// </summary>
|
||||
public new void Stop()
|
||||
{
|
||||
Stop(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the interplation process.
|
||||
/// </summary>
|
||||
/// <param name="keepState">If true, it will not set the state to the <see cref="To"/> state.</param>
|
||||
public void Stop(bool keepState)
|
||||
{
|
||||
if (Active && !keepState) SetTarget(To);
|
||||
|
||||
base.Stop();
|
||||
|
||||
}
|
||||
|
||||
private protected override void Ticking(UpdateContext context)
|
||||
{
|
||||
base.Ticking(context);
|
||||
|
||||
float posInCurve = InterpolationCurve.CalculatePoint(ElapsedNormalized).Y;
|
||||
Vector4 nextPos = From + (Direction * posInCurve);
|
||||
SetTarget(nextPos);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Stopping(UpdateContext context)
|
||||
{
|
||||
base.Stopping(context);
|
||||
SetTarget(To);
|
||||
}
|
||||
|
||||
private void SetTarget(Vector4 vec)
|
||||
{
|
||||
TargetVector.SetRaw(vec.X, vec.Y, vec.Z, vec.W);
|
||||
}
|
||||
}
|
||||
}
|
||||
188
src/renderer/SM.Base/Controls/Keyboard.cs
Normal file
188
src/renderer/SM.Base/Controls/Keyboard.cs
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenTK.Input;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// A static class to get keyboard inputs.
|
||||
/// </summary>
|
||||
public static class Keyboard
|
||||
{
|
||||
private static KeyboardState? _keyboardState;
|
||||
private static List<Key> _lastPressedKeys = new List<Key>();
|
||||
|
||||
/// <summary>
|
||||
/// True, when ANY key pressed.
|
||||
/// </summary>
|
||||
public static bool IsAnyKeyPressed => _keyboardState?.IsAnyKeyDown == true;
|
||||
|
||||
|
||||
internal static void SetStage()
|
||||
{
|
||||
if (_keyboardState.HasValue)
|
||||
{
|
||||
_lastPressedKeys = new List<Key>();
|
||||
|
||||
foreach (object o in Enum.GetValues(typeof(Key)))
|
||||
if (_keyboardState.Value[(Key) o])
|
||||
_lastPressedKeys.Add((Key) o);
|
||||
}
|
||||
|
||||
_keyboardState = OpenTK.Input.Keyboard.GetState();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a key is down.
|
||||
/// </summary>
|
||||
/// <param name="key">The key</param>
|
||||
/// <param name="once">If true, the method doesn't return true, when it was pressed one stage before.</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsDown(Key key, bool once = false)
|
||||
{
|
||||
return _keyboardState?[key] == true && !(once && _lastPressedKeys.Contains(key));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a key was down but not anymore.
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public static bool WasDown(Key key)
|
||||
{
|
||||
return _keyboardState?[key] == false && _lastPressedKeys.Contains(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a is up.
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="once">If true, the method doesn't return true, when it was up one stage before.</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsUp(Key key, bool once = false)
|
||||
{
|
||||
return _keyboardState?[key] == false && !(once && !_lastPressedKeys.Contains(key));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if specific keys are down.
|
||||
/// </summary>
|
||||
/// <param name="startIndex">Startindex</param>
|
||||
/// <param name="endIndex">Endindex</param>
|
||||
/// <param name="once">If true, it ignores keys that were down a state before.</param>
|
||||
/// <returns>True if any of the specific keys where found down.</returns>
|
||||
/// <exception cref="ArgumentException">The start index can't be greater then the end index.</exception>
|
||||
public static bool AreSpecificKeysPressed(int startIndex, int endIndex, bool once = false)
|
||||
{
|
||||
if (startIndex > endIndex)
|
||||
throw new ArgumentException("The startIndex is greater than the endIndex.", nameof(startIndex));
|
||||
|
||||
int length = endIndex - startIndex;
|
||||
for (int i = 0; i < length + 1; i++)
|
||||
{
|
||||
int actualIndex = i + startIndex;
|
||||
Key key = (Key) actualIndex;
|
||||
if (IsDown(key, once)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if any of the specific keys are pressed.
|
||||
/// </summary>
|
||||
/// <param name="keys"></param>
|
||||
/// <returns></returns>
|
||||
public static bool AreSpecificKeysPressed(params Key[] keys)
|
||||
{
|
||||
return AreSpecificKeysPressed(false, keys);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if any of the specific keys are pressed.
|
||||
/// </summary>
|
||||
/// <param name="once">If true, it ignores keys that were down a state before.</param>
|
||||
/// <param name="keys"></param>
|
||||
/// <returns></returns>
|
||||
public static bool AreSpecificKeysPressed(bool once, params Key[] keys)
|
||||
{
|
||||
foreach (Key key in keys)
|
||||
if (IsDown(key, once))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if specific keys are down and returns the pressed keys.
|
||||
/// </summary>
|
||||
/// <param name="startIndex">Startindex</param>
|
||||
/// <param name="endIndex">Endindex</param>
|
||||
/// <param name="pressedKeys"></param>
|
||||
/// <param name="once">If true, it ignores keys that were down a state before.</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
public static bool AreSpecificKeysPressed(int startIndex, int endIndex, out Key[] pressedKeys,
|
||||
bool once = false)
|
||||
{
|
||||
if (startIndex > endIndex)
|
||||
throw new ArgumentException("The startIndex is greater than the endIndex.", nameof(startIndex));
|
||||
|
||||
int length = endIndex - startIndex;
|
||||
|
||||
bool success = false;
|
||||
List<Key> keys = new List<Key>();
|
||||
for (int i = 0; i < length + 1; i++)
|
||||
{
|
||||
int actualIndex = i + startIndex;
|
||||
Key key = (Key) actualIndex;
|
||||
if (IsDown(key, once))
|
||||
{
|
||||
keys.Add(key);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
pressedKeys = keys.ToArray();
|
||||
return success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if any of the specific keys are pressed and returns them.
|
||||
/// </summary>
|
||||
/// <param name="pressedKey"></param>
|
||||
/// <param name="keys"></param>
|
||||
/// <returns></returns>
|
||||
public static bool AreSpecificKeysPressed(out Key[] pressedKey, params Key[] keys)
|
||||
{
|
||||
return AreSpecificKeysPressed(false, out pressedKey, keys);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if any of the specific keys are pressed and returns them.
|
||||
/// </summary>
|
||||
/// <param name="once">If true, it ignores keys that were down a state before.</param>
|
||||
/// <param name="pressedKeys"></param>
|
||||
/// <param name="keys"></param>
|
||||
/// <returns></returns>
|
||||
public static bool AreSpecificKeysPressed(bool once, out Key[] pressedKeys, params Key[] keys)
|
||||
{
|
||||
List<Key> pressedKey = new List<Key>();
|
||||
bool success = false;
|
||||
|
||||
foreach (Key key in keys)
|
||||
if (IsDown(key, once))
|
||||
{
|
||||
pressedKey.Add(key);
|
||||
success = true;
|
||||
}
|
||||
|
||||
pressedKeys = pressedKey.ToArray();
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
88
src/renderer/SM.Base/Controls/Mouse.cs
Normal file
88
src/renderer/SM.Base/Controls/Mouse.cs
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
using SM.Base.Window;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Mouse controller
|
||||
/// </summary>
|
||||
public class Mouse
|
||||
{
|
||||
private static MouseState? _mouseState;
|
||||
private static List<MouseButton> _lastButtonsPressed = new List<MouseButton>();
|
||||
|
||||
/// <summary>
|
||||
/// The current position of the mouse in the screen.
|
||||
/// </summary>
|
||||
public static Vector2 InScreen { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current position of the mouse in the screen from 0..1.
|
||||
/// </summary>
|
||||
public static Vector2 InScreenNormalized { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// This returns true, if the left mouse button was pressed.
|
||||
/// <para>Its pretty much: IsDown(MouseButton.Left, true)</para>
|
||||
/// </summary>
|
||||
public static bool LeftClick => IsDown(MouseButton.Left, true);
|
||||
|
||||
/// <summary>
|
||||
/// This returns true, if the right mouse button was pressed.
|
||||
/// <para>Its pretty much: IsDown(MouseButton.Right, true)</para>
|
||||
/// </summary>
|
||||
public static bool RightClick => IsDown(MouseButton.Right, true);
|
||||
|
||||
/// <summary>
|
||||
/// The event to update the values.
|
||||
/// </summary>
|
||||
/// <param name="mmea">The event args.</param>
|
||||
/// <param name="window">The window where the mouse is checked</param>
|
||||
internal static void MouseMoveEvent(MouseMoveEventArgs mmea, IGenericWindow window)
|
||||
{
|
||||
InScreen = new Vector2(mmea.X, mmea.Y);
|
||||
InScreenNormalized = new Vector2(mmea.X / (float) window.Width, mmea.Y / (float) window.Height);
|
||||
}
|
||||
|
||||
internal static void SetState()
|
||||
{
|
||||
if (_mouseState.HasValue)
|
||||
{
|
||||
_lastButtonsPressed = new List<MouseButton>();
|
||||
|
||||
foreach (object o in Enum.GetValues(typeof(MouseButton)))
|
||||
if (_mouseState.Value[(MouseButton) o])
|
||||
_lastButtonsPressed.Add((MouseButton) o);
|
||||
}
|
||||
|
||||
_mouseState = OpenTK.Input.Mouse.GetState();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the mouse is pressed.
|
||||
/// </summary>
|
||||
/// <param name="button"></param>
|
||||
/// <param name="once">If true, it will not get called, when it was pressed in the last update.</param>
|
||||
public static bool IsDown(MouseButton button, bool once = false)
|
||||
{
|
||||
return _mouseState?[button] == true && !(once && _lastButtonsPressed.Contains(button));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the mouse is not pressed.
|
||||
/// </summary>
|
||||
/// <param name="button"></param>
|
||||
/// <param name="once">If true, it will not get called, when it was not pressed in the last update.</param>
|
||||
public static bool IsUp(MouseButton button, bool once = false)
|
||||
{
|
||||
return _mouseState?[button] == false && !(once && !_lastButtonsPressed.Contains(button));
|
||||
}
|
||||
}
|
||||
}
|
||||
118
src/renderer/SM.Base/Drawing/DrawingBasis.cs
Normal file
118
src/renderer/SM.Base/Drawing/DrawingBasis.cs
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
#region usings
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using SM.Base.Scene;
|
||||
using SM.Base.Window;
|
||||
using SM.OGL.Mesh;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains general basis systems for drawing objects.
|
||||
/// </summary>
|
||||
public abstract class DrawingBasis : IShowItem, IModelItem
|
||||
{
|
||||
/// <summary>
|
||||
/// The camera, that was used last time the object was rendered.
|
||||
/// </summary>
|
||||
public GenericCamera LastDrawingCamera { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The material it should use.
|
||||
/// </summary>
|
||||
public Material Material { get; set; } = new Material();
|
||||
|
||||
/// <summary>
|
||||
/// Transformation for the textures.
|
||||
/// </summary>
|
||||
public TextureTransformation TextureTransform { get; set; } = new TextureTransformation();
|
||||
|
||||
/// <summary>
|
||||
/// This allows custom shaders to add own arguments.
|
||||
/// </summary>
|
||||
public ShaderArguments ShaderArguments => Material.ShaderArguments;
|
||||
|
||||
/// <summary>
|
||||
/// This can force a shader to render the object with the specified mesh type.
|
||||
/// </summary>
|
||||
public PrimitiveType? ForcedMeshType { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The mesh it should use.
|
||||
/// </summary>
|
||||
public GenericMesh Mesh { get; set; } = SMRenderer.DefaultMesh;
|
||||
|
||||
/// <inheritdoc />
|
||||
public object Parent { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name { get; set; } = "Unnamed draw object";
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICollection<string> Flags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This value determents if the object should draw something.
|
||||
/// </summary>
|
||||
public bool Active { get; set; } = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool RenderActive { get; set; } = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Draw(DrawContext context)
|
||||
{
|
||||
context.Material = Material;
|
||||
context.Mesh = Mesh;
|
||||
|
||||
DrawContext(ref context);
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public virtual void OnAdded(object sender)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void OnRemoved(object sender)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the context, that was given to them.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
protected virtual void DrawContext(ref DrawContext context)
|
||||
{
|
||||
context.ForcedType = ForcedMeshType;
|
||||
context.TextureMatrix *= TextureTransform.GetMatrix();
|
||||
context.LastObject = this;
|
||||
|
||||
LastDrawingCamera = context.UseCamera;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains general basis systems for drawing objects.
|
||||
/// </summary>
|
||||
/// <typeparam name="TTransformation">The transformation type</typeparam>
|
||||
public abstract class DrawingBasis<TTransformation> : DrawingBasis, IShowTransformItem<TTransformation>
|
||||
where TTransformation : GenericTransformation, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// The current transformation.
|
||||
/// </summary>
|
||||
public TTransformation Transform { get; set; } = new TTransformation();
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void DrawContext(ref DrawContext context)
|
||||
{
|
||||
base.DrawContext(ref context);
|
||||
Transform.LastMaster = context.ModelMatrix;
|
||||
context.ModelMatrix = Transform.InWorldSpace;
|
||||
}
|
||||
}
|
||||
}
|
||||
72
src/renderer/SM.Base/Drawing/GenericTransformation.cs
Normal file
72
src/renderer/SM.Base/Drawing/GenericTransformation.cs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#region usings
|
||||
|
||||
using OpenTK;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains methods for using transformations right.
|
||||
/// </summary>
|
||||
public abstract class GenericTransformation
|
||||
{
|
||||
/// <summary>
|
||||
/// If true, ignores the transformation and sends <see cref="Matrix4.Identity" />, when requested.
|
||||
/// </summary>
|
||||
public bool Ignore = false;
|
||||
|
||||
/// <summary>
|
||||
/// The last matrix that was used to calculate the real world matrix.
|
||||
/// </summary>
|
||||
public Matrix4 LastMaster { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The transformation in world space.
|
||||
/// </summary>
|
||||
public Matrix4 InWorldSpace => MergeMatrix(LastMaster);
|
||||
|
||||
/// <summary>
|
||||
/// Contains the current model matrix.
|
||||
/// </summary>
|
||||
protected Matrix4 _modelMatrix { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Contains the last frame the matrix was calculated.
|
||||
/// </summary>
|
||||
protected ulong _lastFrame { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current model matrix.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Matrix4 GetMatrix()
|
||||
{
|
||||
if (Ignore) return Matrix4.Identity;
|
||||
|
||||
if (_lastFrame != SMRenderer.CurrentFrame)
|
||||
{
|
||||
_lastFrame = SMRenderer.CurrentFrame;
|
||||
_modelMatrix = RequestMatrix();
|
||||
}
|
||||
|
||||
return _modelMatrix;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This combines the current matrix with the provided one.
|
||||
/// </summary>
|
||||
/// <param name="matrix"></param>
|
||||
/// <returns></returns>
|
||||
public Matrix4 MergeMatrix(Matrix4 matrix)
|
||||
{
|
||||
return GetMatrix() * matrix;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the current matrix.
|
||||
/// </summary>
|
||||
/// <returns>The current matrix.</returns>
|
||||
protected abstract Matrix4 RequestMatrix();
|
||||
}
|
||||
}
|
||||
24
src/renderer/SM.Base/Drawing/Instance.cs
Normal file
24
src/renderer/SM.Base/Drawing/Instance.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#region usings
|
||||
|
||||
using OpenTK;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// This represens a drawing instance.
|
||||
/// </summary>
|
||||
public class Instance
|
||||
{
|
||||
/// <summary>
|
||||
/// The model matrix.
|
||||
/// </summary>
|
||||
public Matrix4 ModelMatrix = Matrix4.Identity;
|
||||
|
||||
/// <summary>
|
||||
/// The Texture matrix
|
||||
/// </summary>
|
||||
public Matrix3 TextureMatrix = Matrix3.Identity;
|
||||
}
|
||||
}
|
||||
47
src/renderer/SM.Base/Drawing/Material.cs
Normal file
47
src/renderer/SM.Base/Drawing/Material.cs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#region usings
|
||||
|
||||
using OpenTK.Graphics;
|
||||
using SM.Base.Shaders;
|
||||
using SM.Base.Window;
|
||||
using SM.OGL.Texture;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a material.
|
||||
/// </summary>
|
||||
public class Material
|
||||
{
|
||||
/// <summary>
|
||||
/// A setting to enable Blending.
|
||||
/// </summary>
|
||||
public virtual bool Blending { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// A custom shader, that is used to draw this material.
|
||||
/// </summary>
|
||||
public virtual MaterialShader CustomShader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The base texture. (aka. Diffuse Texture)
|
||||
/// </summary>
|
||||
public virtual TextureBase Texture { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The tint or color.
|
||||
/// </summary>
|
||||
public virtual Color4 Tint { get; set; } = Color4.White;
|
||||
|
||||
/// <summary>
|
||||
/// This allows custom shaders to use own shader arguments.
|
||||
/// </summary>
|
||||
public ShaderArguments ShaderArguments { get; internal set; } = new ShaderArguments();
|
||||
|
||||
public virtual void Draw(DrawContext context)
|
||||
{
|
||||
context.Shader.Draw(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
212
src/renderer/SM.Base/Drawing/Particles/ParticleDrawingBasis.cs
Normal file
212
src/renderer/SM.Base/Drawing/Particles/ParticleDrawingBasis.cs
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenTK;
|
||||
using SM.Base.Scene;
|
||||
using SM.Base.Time;
|
||||
using SM.Base.Window;
|
||||
using Stopwatch = System.Diagnostics.Stopwatch;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Drawing.Particles
|
||||
{
|
||||
/// <summary>
|
||||
/// The (drawing) basis for particles
|
||||
/// </summary>
|
||||
public abstract class ParticleDrawingBasis<TTransform, TDirection> : DrawingBasis<TTransform>, IScriptable
|
||||
where TTransform : GenericTransformation, new()
|
||||
where TDirection : struct
|
||||
{
|
||||
private float? _continuesIntervalSeconds = null;
|
||||
private Interval _continuesInterval;
|
||||
|
||||
/// <summary>
|
||||
/// The stopwatch of the particles.
|
||||
/// </summary>
|
||||
protected Timer timer;
|
||||
|
||||
/// <summary>
|
||||
/// This contains the different instances for the particles.
|
||||
/// </summary>
|
||||
protected List<ParticleInstance<TDirection>> instances;
|
||||
|
||||
/// <summary>
|
||||
/// The amount of particles
|
||||
/// </summary>
|
||||
public int Amount = 32;
|
||||
|
||||
/// <summary>
|
||||
/// The base lifetime for particles in seconds.
|
||||
/// </summary>
|
||||
public float Lifetime;
|
||||
/// <summary>
|
||||
/// Randomizes the lifetime for particles.
|
||||
/// </summary>
|
||||
public float LifetimeRandomize = 0;
|
||||
|
||||
/// <summary>
|
||||
/// If set to any value (except null), it will create the particles continuously.
|
||||
/// </summary>
|
||||
public float? ContinuousInterval
|
||||
{
|
||||
get => _continuesIntervalSeconds;
|
||||
set
|
||||
{
|
||||
if (value.HasValue)
|
||||
{
|
||||
_continuesInterval.Target = value.Value;
|
||||
}
|
||||
|
||||
_continuesIntervalSeconds = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If true, the particles will spawn in Worldspace and can't be moved by the transformation.
|
||||
/// </summary>
|
||||
public bool DetachedParticles;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum speed of the particles
|
||||
/// <para>Default: 25</para>
|
||||
/// </summary>
|
||||
public float MaxSpeed = 25;
|
||||
|
||||
/// <summary>
|
||||
/// Sets up the timer.
|
||||
/// </summary>
|
||||
/// <param name="duration">Duration how long the particles should live</param>
|
||||
protected ParticleDrawingBasis(TimeSpan duration)
|
||||
{
|
||||
timer = new Timer(duration);
|
||||
_continuesInterval = new Interval(0);
|
||||
_continuesInterval.End += CreateContinuesParticles;
|
||||
|
||||
Lifetime = (float) duration.TotalSeconds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/Sets the state of pausing.
|
||||
/// </summary>
|
||||
public bool Paused
|
||||
{
|
||||
get => timer.Paused;
|
||||
set => timer.Paused = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Controls the movement of each particles.
|
||||
/// </summary>
|
||||
public abstract Func<ParticleInstance<TDirection>, TDirection> MovementCalculation { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool UpdateActive {
|
||||
get => timer.Active || _continuesInterval.Active;
|
||||
set { return; }
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Update(UpdateContext context)
|
||||
{
|
||||
Stopwatch stp = new Stopwatch();
|
||||
stp.Start();
|
||||
for (int i = 0; i < instances.Count; i++)
|
||||
{
|
||||
instances[i].Lifetime -= context.Deltatime;
|
||||
if (instances[i].Lifetime <= 0)
|
||||
{
|
||||
instances.Remove(instances[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
instances[i].ModelMatrix = CreateMatrix(instances[i], MovementCalculation(instances[i]));
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers the particles.
|
||||
/// </summary>
|
||||
public void Trigger()
|
||||
{
|
||||
instances = new List<ParticleInstance<TDirection>>();
|
||||
if (_continuesIntervalSeconds.HasValue)
|
||||
{
|
||||
_continuesInterval.Target = _continuesIntervalSeconds.Value;
|
||||
_continuesInterval.Start();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
timer.Start();
|
||||
|
||||
CreateParticles();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the particles.
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
if (_continuesInterval.Active)
|
||||
{
|
||||
_continuesInterval.Stop();
|
||||
}
|
||||
|
||||
timer.Stop();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnRemoved(object sender)
|
||||
{
|
||||
base.OnRemoved(sender);
|
||||
|
||||
Stop();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void DrawContext(ref DrawContext context)
|
||||
{
|
||||
if (!timer.Active && _continuesInterval != null && !_continuesInterval.Active) return;
|
||||
|
||||
base.DrawContext(ref context);
|
||||
|
||||
if (DetachedParticles) context.ModelMatrix = Matrix4.Identity;
|
||||
|
||||
context.Instances = instances.ConvertAll(a => (Instance)a);
|
||||
|
||||
Material.Draw(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the particles.
|
||||
/// </summary>
|
||||
protected virtual void CreateParticles()
|
||||
{
|
||||
|
||||
|
||||
for (int i = 0; i < Amount; i++)
|
||||
{
|
||||
instances.Add(CreateObject(i));
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateContinuesParticles(Timer arg1, UpdateContext arg2)
|
||||
{
|
||||
instances.Add(CreateObject(0));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a particle.
|
||||
/// </summary>
|
||||
protected abstract ParticleInstance<TDirection> CreateObject(int index);
|
||||
|
||||
/// <summary>
|
||||
/// Generates the desired matrix for drawing.
|
||||
/// </summary>
|
||||
protected abstract Matrix4 CreateMatrix(ParticleInstance<TDirection> Struct, TDirection relativePosition);
|
||||
}
|
||||
}
|
||||
40
src/renderer/SM.Base/Drawing/Particles/ParticleInstance.cs
Normal file
40
src/renderer/SM.Base/Drawing/Particles/ParticleInstance.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
using OpenTK;
|
||||
|
||||
namespace SM.Base.Drawing.Particles
|
||||
{
|
||||
/// <summary>
|
||||
/// This describes a instance of a particle
|
||||
/// </summary>
|
||||
public class ParticleInstance : Instance
|
||||
{
|
||||
/// <summary>
|
||||
/// The lifetime the particle started with.
|
||||
/// </summary>
|
||||
public float StartLifetime = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The lifetime this particular particle still has.
|
||||
/// </summary>
|
||||
public float Lifetime = 0;
|
||||
|
||||
/// <summary>
|
||||
/// A additional matrix to store rotation and scale.
|
||||
/// </summary>
|
||||
public Matrix4 Matrix;
|
||||
|
||||
/// <summary>
|
||||
/// Speeeeeeeeeed
|
||||
/// </summary>
|
||||
public float Speed;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public class ParticleInstance<TValue> : ParticleInstance
|
||||
where TValue : struct
|
||||
{
|
||||
/// <summary>
|
||||
/// A direction, that the particle should travel.
|
||||
/// </summary>
|
||||
public TValue Direction;
|
||||
}
|
||||
}
|
||||
30
src/renderer/SM.Base/Drawing/Particles/ParticleMovement.cs
Normal file
30
src/renderer/SM.Base/Drawing/Particles/ParticleMovement.cs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#region usings
|
||||
|
||||
using OpenTK;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Drawing.Particles
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains methods for particle movements.
|
||||
/// </summary>
|
||||
public class ParticleMovement
|
||||
{
|
||||
/// <summary>
|
||||
/// Default movement for 2D.
|
||||
/// </summary>
|
||||
public static Vector2 Default2D(ParticleInstance<Vector2> particle)
|
||||
{
|
||||
return particle.Direction * ((particle.StartLifetime - particle.Lifetime) * particle.Speed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default movement for 3D.
|
||||
/// </summary>
|
||||
public static Vector3 Default3D(ParticleInstance<Vector3> particle)
|
||||
{
|
||||
return particle.Direction * ((particle.StartLifetime - particle.Lifetime) * particle.Speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/renderer/SM.Base/Drawing/ShaderArguments.cs
Normal file
26
src/renderer/SM.Base/Drawing/ShaderArguments.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#region usings
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// A custom dictionary, with a few useful methods.
|
||||
/// </summary>
|
||||
public class ShaderArguments : Dictionary<string, object>
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the stored value or the default value if the name doesn't exist.
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <typeparam name="TType"></typeparam>
|
||||
/// <returns></returns>
|
||||
public TType Get<TType>(string name, TType defaultValue = default)
|
||||
{
|
||||
return ContainsKey(name) ? (TType) this[name] : defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
37
src/renderer/SM.Base/Drawing/Text/CharParameter.cs
Normal file
37
src/renderer/SM.Base/Drawing/Text/CharParameter.cs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using OpenTK;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Drawing.Text
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains information for a font character.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public struct CharParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// The advance on the X-axis.
|
||||
/// </summary>
|
||||
public int Advance;
|
||||
|
||||
/// <summary>
|
||||
/// The bearing for this char.
|
||||
/// </summary>
|
||||
public float BearingX;
|
||||
|
||||
/// <summary>
|
||||
/// The width of the character.
|
||||
/// </summary>
|
||||
public float Width;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Matrix for the texture.
|
||||
/// </summary>
|
||||
public Matrix3 TextureMatrix;
|
||||
}
|
||||
}
|
||||
125
src/renderer/SM.Base/Drawing/Text/Font.cs
Normal file
125
src/renderer/SM.Base/Drawing/Text/Font.cs
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Windows.Forms;
|
||||
using OpenTK;
|
||||
using SharpFont;
|
||||
using SM.Base.Textures;
|
||||
|
||||
namespace SM.Base.Drawing.Text
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a font to be used in DrawText-classes.
|
||||
/// </summary>
|
||||
public class Font : Texture
|
||||
{
|
||||
private static Library _lib;
|
||||
|
||||
private Face _fontFace;
|
||||
|
||||
/// <summary>
|
||||
/// The amount the cursor should move forward when a space was found.
|
||||
/// </summary>
|
||||
public float SpaceWidth { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The char set the font should contain.
|
||||
/// <para>See <see cref="FontCharStorage"/> for some default values.</para>
|
||||
/// <para>Default: <see cref="FontCharStorage.SimpleUTF8"/></para>
|
||||
/// </summary>
|
||||
public ICollection<char> CharSet { get; set; } = FontCharStorage.SimpleUTF8;
|
||||
|
||||
/// <summary>
|
||||
/// The font-size defines how large the result texture should be.
|
||||
/// <para>Lower equals less quality, but also less memory usage.</para>
|
||||
/// <para>Higher equals high quality, but also high memory usage.</para>
|
||||
/// <para>Default: 12</para>
|
||||
/// </summary>
|
||||
public float FontSize { get; set; } = 12;
|
||||
|
||||
/// <summary>
|
||||
/// The character positions.
|
||||
/// </summary>
|
||||
public Dictionary<char, CharParameter> Positions = new Dictionary<char, CharParameter>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a font, by using a path
|
||||
/// </summary>
|
||||
/// <param name="path">Path to the font-file.</param>
|
||||
public Font(string path)
|
||||
{
|
||||
_lib ??= new Library();
|
||||
|
||||
_fontFace = new Face(_lib, path);
|
||||
UnpackAlignment = 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// (Re-)Generates the texture.
|
||||
/// </summary>
|
||||
public void RegenerateTexture()
|
||||
{
|
||||
Width = Height = 0;
|
||||
Positions = new Dictionary<char, CharParameter>();
|
||||
|
||||
_fontFace.SetCharSize(0, FontSize, 0, 96);
|
||||
|
||||
var pos = new Dictionary<char, float[]>();
|
||||
foreach (char c in CharSet)
|
||||
{
|
||||
_fontFace.LoadChar(c, LoadFlags.Render, LoadTarget.Normal);
|
||||
|
||||
pos.Add(c, new []{(float)_fontFace.Glyph.Bitmap.Width, Width});
|
||||
Width += (int)_fontFace.Glyph.Advance.X + 2;
|
||||
Height = Math.Max(_fontFace.Glyph.Bitmap.Rows, Height);
|
||||
}
|
||||
|
||||
_fontFace.LoadChar('_', LoadFlags.Render, LoadTarget.Normal);
|
||||
SpaceWidth = _fontFace.Glyph.Advance.X.ToSingle();
|
||||
|
||||
float bBoxHeight = (Math.Abs(_fontFace.BBox.Bottom) + _fontFace.BBox.Top);
|
||||
float bBoxTopScale = _fontFace.BBox.Top / bBoxHeight;
|
||||
float baseline = Height * bBoxTopScale + 1;
|
||||
|
||||
Map = new Bitmap(Width, Height);
|
||||
using (Graphics g = Graphics.FromImage(Map))
|
||||
{
|
||||
g.Clear(Color.Transparent);
|
||||
|
||||
|
||||
foreach (var keyvalue in pos)
|
||||
{
|
||||
_fontFace.LoadChar(keyvalue.Key, LoadFlags.Render, LoadTarget.Normal);
|
||||
|
||||
int y = ((int)baseline - (int)_fontFace.Glyph.Metrics.HorizontalBearingY);
|
||||
|
||||
g.DrawImageUnscaled(_fontFace.Glyph.Bitmap.ToGdipBitmap(Color.White), (int)keyvalue.Value[1], y);
|
||||
|
||||
Vector2 offset = new Vector2(keyvalue.Value[1] / Width, 0);
|
||||
Vector2 scale = new Vector2(keyvalue.Value[0] / Width, 1);
|
||||
Positions.Add(keyvalue.Key, new CharParameter()
|
||||
{
|
||||
Advance = (int)_fontFace.Glyph.LinearHorizontalAdvance,
|
||||
BearingX = _fontFace.Glyph.BitmapLeft,
|
||||
|
||||
Width = keyvalue.Value[0],
|
||||
|
||||
TextureMatrix = TextureTransformation.CalculateMatrix(offset,
|
||||
scale, 0),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Compile()
|
||||
{
|
||||
RegenerateTexture();
|
||||
base.Compile();
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/renderer/SM.Base/Drawing/Text/FontCharStorage.cs
Normal file
29
src/renderer/SM.Base/Drawing/Text/FontCharStorage.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
namespace SM.Base.Drawing.Text
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains default char sets.
|
||||
/// </summary>
|
||||
public class FontCharStorage
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the english alphabet and the common special character.
|
||||
/// </summary>
|
||||
public static readonly char[] SimpleUTF8 =
|
||||
{
|
||||
'!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5',
|
||||
'6',
|
||||
'7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
|
||||
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
|
||||
'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~'
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Contains only numbers.
|
||||
/// </summary>
|
||||
public static readonly char[] Numbers =
|
||||
{
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
|
||||
};
|
||||
}
|
||||
}
|
||||
202
src/renderer/SM.Base/Drawing/Text/TextDrawingBasis.cs
Normal file
202
src/renderer/SM.Base/Drawing/Text/TextDrawingBasis.cs
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using SM.Base.Objects.Static;
|
||||
using SM.Base.Window;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Drawing.Text
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the options for <see cref="TextDrawingBasis{TTransform}.Origin"/>
|
||||
/// </summary>
|
||||
public enum TextOrigin
|
||||
{
|
||||
/// <summary>
|
||||
/// The position equals (0,0) in the left side of the text.
|
||||
/// </summary>
|
||||
Left,
|
||||
/// <summary>
|
||||
/// The position equals (0,0) in the center of the text.
|
||||
/// </summary>
|
||||
Center,
|
||||
/// <summary>
|
||||
/// The position equals (0,0) in the right side of the text.
|
||||
/// </summary>
|
||||
Right
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines a basis for text drawing.
|
||||
/// </summary>
|
||||
/// <typeparam name="TTransform">Transformation type</typeparam>
|
||||
public abstract class TextDrawingBasis<TTransform> : DrawingBasis<TTransform>
|
||||
where TTransform : GenericTransformation, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// The different instances for drawing.
|
||||
/// </summary>
|
||||
protected Instance[] _instances;
|
||||
|
||||
/// <summary>
|
||||
/// The text, that is drawn.
|
||||
/// </summary>
|
||||
protected string _text;
|
||||
|
||||
/// <summary>
|
||||
/// The width of the text object.
|
||||
/// </summary>
|
||||
public float Width;
|
||||
|
||||
/// <summary>
|
||||
/// The height of the text object.
|
||||
/// </summary>
|
||||
public float Height;
|
||||
|
||||
/// <summary>
|
||||
/// Allow to change the origin of the text.
|
||||
/// <para>Default: <see cref="TextOrigin.Left"/></para>
|
||||
/// </summary>
|
||||
public TextOrigin Origin = TextOrigin.Left;
|
||||
|
||||
/// <summary>
|
||||
/// The spacing between numbers.
|
||||
/// <para>Default: 1</para>
|
||||
/// </summary>
|
||||
public float Spacing = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// The font.
|
||||
/// </summary>
|
||||
public Font Font
|
||||
{
|
||||
get => (Font)Material.Texture;
|
||||
set
|
||||
{
|
||||
Material.Texture = value;
|
||||
GenerateMatrixes();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The text, that is drawn.
|
||||
/// </summary>
|
||||
public string Text
|
||||
{
|
||||
get => _text;
|
||||
set
|
||||
{
|
||||
_text = value;
|
||||
GenerateMatrixes();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The font color.
|
||||
/// </summary>
|
||||
public Color4 Color
|
||||
{
|
||||
get => Material.Tint;
|
||||
set => Material.Tint = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a text object with a font.
|
||||
/// </summary>
|
||||
/// <param name="font">The font.</param>
|
||||
protected TextDrawingBasis(Font font)
|
||||
{
|
||||
Material.Texture = font;
|
||||
Material.Blending = true;
|
||||
Mesh = Plate.Object;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void DrawContext(ref DrawContext context)
|
||||
{
|
||||
base.DrawContext(ref context);
|
||||
if (_instances == null) GenerateMatrixes();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This generates the instances.
|
||||
/// </summary>
|
||||
/// <exception cref="Exception">The font doesn't contain a character that is needed for the text.</exception>
|
||||
public void GenerateMatrixes()
|
||||
{
|
||||
if (!Font.WasCompiled) Font.RegenerateTexture();
|
||||
|
||||
_text = _text.Replace("\r\n", "\n").Replace("\t", " ");
|
||||
|
||||
_instances = new Instance[_text.Length];
|
||||
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
for (var i = 0; i < _text.Length; i++)
|
||||
{
|
||||
if (_text[i] == ' ')
|
||||
{
|
||||
x += Font.SpaceWidth * Spacing;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_text[i] == '\n')
|
||||
{
|
||||
y += Font.Height;
|
||||
Width = Math.Max(Width, x);
|
||||
x = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
CharParameter parameter;
|
||||
try
|
||||
{
|
||||
parameter = Font.Positions[_text[i]];
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new Exception("Font doesn't contain '" + _text[i] + "'");
|
||||
}
|
||||
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
x += parameter.Width / 2;
|
||||
}
|
||||
|
||||
var matrix = Matrix4.CreateScale(parameter.Width, Font.Height, 1) *
|
||||
Matrix4.CreateTranslation(x + parameter.Width / 2, -y, 0);
|
||||
_instances[i] = new Instance
|
||||
{
|
||||
ModelMatrix = matrix,
|
||||
TextureMatrix = parameter.TextureMatrix
|
||||
};
|
||||
|
||||
x += parameter.Advance;
|
||||
}
|
||||
Height = y + Font.Height;
|
||||
Width = x;
|
||||
|
||||
if (Origin != TextOrigin.Left)
|
||||
{
|
||||
foreach (Instance i in _instances)
|
||||
{
|
||||
if (i == null) continue;
|
||||
switch (Origin)
|
||||
{
|
||||
case TextOrigin.Center:
|
||||
i.ModelMatrix *= Matrix4.CreateTranslation(-Width / 2, 0, 0);
|
||||
break;
|
||||
case TextOrigin.Right:
|
||||
i.ModelMatrix *= Matrix4.CreateTranslation(-Width, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
89
src/renderer/SM.Base/Drawing/TextureTransformation.cs
Normal file
89
src/renderer/SM.Base/Drawing/TextureTransformation.cs
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#region usings
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.ES10;
|
||||
using SM.Base.Textures;
|
||||
using SM.Base.Types;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// Stores transformations for the textures.
|
||||
/// </summary>
|
||||
public class TextureTransformation
|
||||
{
|
||||
/// <summary>
|
||||
/// The offset from the origin.
|
||||
/// </summary>
|
||||
public CVector2 Offset = new CVector2(0);
|
||||
/// <summary>
|
||||
/// The rotation of the texture.
|
||||
/// </summary>
|
||||
public CVector1 Rotation = new CVector1(0);
|
||||
/// <summary>
|
||||
/// The scale of the texture.
|
||||
/// </summary>
|
||||
public CVector2 Scale = new CVector2(1);
|
||||
|
||||
/// <summary>
|
||||
/// Get the texture matrix.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Matrix3 GetMatrix()
|
||||
{
|
||||
return CalculateMatrix(Offset, Scale, Rotation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the offset relative to the pixels of the texture.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture it should use.</param>
|
||||
/// <param name="pixelLocation">The offset in pixel.</param>
|
||||
public void SetOffsetRelative(Texture texture, Vector2 pixelLocation)
|
||||
{
|
||||
Vector2 textureSize = new Vector2(texture.Width, texture.Height);
|
||||
Offset.Set( Vector2.Divide(pixelLocation, textureSize) );
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the scale relative to the pixels of the texture.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture.</param>
|
||||
/// <param name="rectangleSize">The scale in pixel.</param>
|
||||
public void SetScaleRelative(Texture texture, Vector2 rectangleSize)
|
||||
{
|
||||
Vector2 textureSize = new Vector2(texture.Width, texture.Height);
|
||||
Scale.Set( Vector2.Divide(rectangleSize, textureSize) );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the offset and scale relative to the pixels of the texture.
|
||||
/// </summary>
|
||||
/// <param name="texture">The texture.</param>
|
||||
/// <param name="location">Offset in pixel</param>
|
||||
/// <param name="rectangleSize">Scale in pixel.</param>
|
||||
public void SetRectangleRelative(Texture texture, Vector2 location, Vector2 rectangleSize)
|
||||
{
|
||||
Vector2 textureSize = new Vector2(texture.Width, texture.Height);
|
||||
|
||||
Offset.Set(Vector2.Divide(location, textureSize));
|
||||
Scale.Set(Vector2.Divide(rectangleSize, textureSize));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates a texture matrix.
|
||||
/// </summary>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="scale"></param>
|
||||
/// <param name="rotation"></param>
|
||||
/// <returns></returns>
|
||||
public static Matrix3 CalculateMatrix(Vector2 offset, Vector2 scale, float rotation)
|
||||
{
|
||||
float radians = MathHelper.DegreesToRadians(rotation);
|
||||
Matrix3 result = Matrix3.CreateScale(scale.X, scale.Y, 1) * Matrix3.CreateRotationZ(radians);
|
||||
result.Row2 = new Vector3(offset.X, offset.Y, 1);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
144
src/renderer/SM.Base/Legacy/Font.cs
Normal file
144
src/renderer/SM.Base/Legacy/Font.cs
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
#region usings
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Text;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using SM.Base.Textures;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Drawing.Text
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a font.
|
||||
/// </summary>
|
||||
public class Font : Texture
|
||||
{
|
||||
/// <summary>
|
||||
/// The char set for the font.
|
||||
/// <para>Default: <see cref="FontCharStorage.SimpleUTF8" /></para>
|
||||
/// </summary>
|
||||
public ICollection<char> CharSet = FontCharStorage.SimpleUTF8;
|
||||
|
||||
/// <summary>
|
||||
/// The font family, that is used to find the right font.
|
||||
/// </summary>
|
||||
public FontFamily FontFamily;
|
||||
|
||||
/// <summary>
|
||||
/// The font size.
|
||||
/// <para>Default: 12</para>
|
||||
/// </summary>
|
||||
public float FontSize = 12;
|
||||
|
||||
public float SpaceWidth { get; private set; }
|
||||
|
||||
public float Spacing = 1;
|
||||
|
||||
/// <summary>
|
||||
/// The font style.
|
||||
/// <para>Default: <see cref="System.Drawing.FontStyle.Regular" /></para>
|
||||
/// </summary>
|
||||
public FontStyle FontStyle = FontStyle.Regular;
|
||||
|
||||
/// <summary>
|
||||
/// This contains all information for the different font character.
|
||||
/// </summary>
|
||||
public Dictionary<char, CharParameter> Positions = new Dictionary<char, CharParameter>();
|
||||
|
||||
/// <summary>
|
||||
/// Generates a font from a font family from the specified path.
|
||||
/// </summary>
|
||||
/// <param name="path">The specified path</param>
|
||||
public Font(string path)
|
||||
{
|
||||
var pfc = new PrivateFontCollection();
|
||||
pfc.AddFontFile(path);
|
||||
FontFamily = pfc.Families[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a font from a specified font family.
|
||||
/// </summary>
|
||||
/// <param name="font">Font-Family</param>
|
||||
public Font(FontFamily font)
|
||||
{
|
||||
FontFamily = font;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override TextureWrapMode WrapMode { get; set; } = TextureWrapMode.ClampToEdge;
|
||||
|
||||
/// <summary>
|
||||
/// Regenerates the texture.
|
||||
/// </summary>
|
||||
public void RegenerateTexture()
|
||||
{
|
||||
Width = 0;
|
||||
Height = 0;
|
||||
Positions = new Dictionary<char, CharParameter>();
|
||||
|
||||
|
||||
var map = new Bitmap(1000, 20);
|
||||
var charParams = new Dictionary<char, float[]>();
|
||||
using (var f = new System.Drawing.Font(FontFamily, FontSize, FontStyle))
|
||||
{
|
||||
using (var g = Graphics.FromImage(map))
|
||||
{
|
||||
g.Clear(Color.Transparent);
|
||||
|
||||
foreach (var c in CharSet)
|
||||
{
|
||||
var s = c.ToString();
|
||||
var size = g.MeasureString(s, f, 0, StringFormat.GenericTypographic);
|
||||
try
|
||||
{
|
||||
charParams.Add(c, new[] {size.Width, Width});
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
if (Height < size.Height) Height = (int) size.Height;
|
||||
Width += (int) size.Width + 1;
|
||||
}
|
||||
|
||||
SpaceWidth = g.MeasureString("_", f, 0, StringFormat.GenericTypographic).Width;
|
||||
}
|
||||
|
||||
map = new Bitmap(Width, Height);
|
||||
using (var g = Graphics.FromImage(map))
|
||||
{
|
||||
foreach (var keyValuePair in charParams)
|
||||
{
|
||||
var normalizedX = (keyValuePair.Value[1]+ 0.00001f) / Width;
|
||||
var normalizedWidth = keyValuePair.Value[0] / Width;
|
||||
|
||||
CharParameter parameter;
|
||||
Positions.Add(keyValuePair.Key, parameter = new CharParameter
|
||||
{
|
||||
NormalizedWidth = normalizedWidth,
|
||||
NormalizedX = normalizedX,
|
||||
Width = keyValuePair.Value[0],
|
||||
X = (int) keyValuePair.Value[1]
|
||||
});
|
||||
|
||||
g.DrawString(keyValuePair.Key.ToString(), f, Brushes.White, parameter.X, 0, StringFormat.GenericTypographic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map = map;
|
||||
Recompile();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Compile()
|
||||
{
|
||||
RegenerateTexture();
|
||||
base.Compile();
|
||||
}
|
||||
}
|
||||
}
|
||||
248
src/renderer/SM.Base/Log.cs
Normal file
248
src/renderer/SM.Base/Log.cs
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Windows.Forms;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using SM.OGL;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the target.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum LogTarget
|
||||
{
|
||||
/// <summary>
|
||||
/// No target, will not draw.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Takes the <see cref="Log.DefaultTarget" />.
|
||||
/// </summary>
|
||||
Default = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Writes the log to the console.
|
||||
/// </summary>
|
||||
Console = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Writes the log to the debugger at <see cref="Debug" />.
|
||||
/// </summary>
|
||||
Debugger = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Writes the log to the specific file.
|
||||
/// </summary>
|
||||
File = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Writes the log to every target.
|
||||
/// </summary>
|
||||
All = Console | Debugger | File
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Preset log types.
|
||||
/// </summary>
|
||||
public enum LogType
|
||||
{
|
||||
/// <summary>
|
||||
/// Informations. Console Color: Green
|
||||
/// </summary>
|
||||
Info,
|
||||
|
||||
/// <summary>
|
||||
/// Warnings. Console Color: Yellow
|
||||
/// </summary>
|
||||
Warning,
|
||||
|
||||
/// <summary>
|
||||
/// Error. Console Color: Red
|
||||
/// </summary>
|
||||
Error
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains the system for logging.
|
||||
/// </summary>
|
||||
public class Log
|
||||
{
|
||||
private static StreamWriter _logStream;
|
||||
private static bool _init;
|
||||
|
||||
/// <summary>
|
||||
/// Presets for the log targets.
|
||||
/// </summary>
|
||||
public static Dictionary<LogTarget, string> Preset = new()
|
||||
{
|
||||
{LogTarget.Console, "[%type%] %msg%"},
|
||||
{LogTarget.Debugger, "[%type%] %msg%"},
|
||||
{LogTarget.File, "<%date%, %time%> [%type%] %msg%"}
|
||||
};
|
||||
|
||||
private static readonly Dictionary<LogType, ConsoleColor> Colors = new()
|
||||
{
|
||||
{LogType.Info, ConsoleColor.Green},
|
||||
{LogType.Warning, ConsoleColor.Yellow},
|
||||
{LogType.Error, ConsoleColor.Red}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Specified the default target.
|
||||
/// </summary>
|
||||
public static LogTarget DefaultTarget = LogTarget.All;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the log file. At wish compresses the old file to a zip file.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the log file.</param>
|
||||
/// <param name="compressionFolder">Path for the compression, if desired.</param>
|
||||
public static void SetLogFile(string path = "sm.log", string compressionFolder = "")
|
||||
{
|
||||
_logStream?.Close();
|
||||
|
||||
if (!_init) Init();
|
||||
|
||||
if (File.Exists(path))
|
||||
{
|
||||
if (compressionFolder != "")
|
||||
{
|
||||
if (!Directory.Exists(compressionFolder)) Directory.CreateDirectory(compressionFolder);
|
||||
|
||||
var creation = File.GetLastWriteTime(path);
|
||||
try
|
||||
{
|
||||
using var archive =
|
||||
ZipFile.Open(
|
||||
$"{compressionFolder}{Path.DirectorySeparatorChar}{Path.GetFileName(path)}_{creation.Year.ToString() + creation.Month + creation.Day}_{creation.Hour.ToString() + creation.Minute + creation.Second + creation.Millisecond}.zip",
|
||||
ZipArchiveMode.Create);
|
||||
archive.CreateEntryFromFile(path, Path.GetFileName(path));
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
File.Delete(path);
|
||||
}
|
||||
|
||||
_logStream = new StreamWriter(path) {AutoFlush = true};
|
||||
|
||||
Write(LogType.Info, $"Activate new log file. ['{path}']");
|
||||
}
|
||||
|
||||
internal static void Init()
|
||||
{
|
||||
if (_init) return;
|
||||
|
||||
AppDomain.CurrentDomain.UnhandledException += ExceptionHandler;
|
||||
AppDomain.CurrentDomain.DomainUnload += (sender, args) =>
|
||||
{
|
||||
_logStream.WriteLine("Unload application");
|
||||
_logStream.Close();
|
||||
};
|
||||
|
||||
GLCustomActions.AtKHRDebug = GLDebugAction;
|
||||
GLCustomActions.AtError = err => Write(LogType.Error, err);
|
||||
GLCustomActions.AtWarning = warning => Write(LogType.Warning, warning);
|
||||
GLCustomActions.AtInfo = info => Write(LogType.Info, info);
|
||||
|
||||
_init = true;
|
||||
}
|
||||
|
||||
private static void GLDebugAction(DebugSource source, DebugType type, DebugSeverity severity, string msg)
|
||||
{
|
||||
if (type.HasFlag(DebugType.DebugTypeError)) throw new Exception("[GLError] " + msg);
|
||||
Write("GL"+ (type != DebugType.DontCare ? type.ToString().Substring(9) : "DontCare"), ConsoleColor.Gray, msg);
|
||||
}
|
||||
|
||||
[DebuggerStepThrough]
|
||||
private static void ExceptionHandler(object sender, UnhandledExceptionEventArgs e)
|
||||
{
|
||||
Write(e.IsTerminating ? "Terminating Error" : LogType.Error.ToString(),
|
||||
e.IsTerminating ? ConsoleColor.DarkRed : ConsoleColor.Red, e.ExceptionObject);
|
||||
|
||||
if (e.IsTerminating)
|
||||
{
|
||||
MessageBox.Show($"Critical error occured.\n\n{e.ExceptionObject}",
|
||||
$"Terminating Error: {e.ExceptionObject.GetType().Name}");
|
||||
_logStream?.Close();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes multiple lines of the same type to the log.
|
||||
/// </summary>
|
||||
public static void Write<T>(LogType type, params T[] values)
|
||||
{
|
||||
Write(type.ToString(), Colors[type], values);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes multiple lines of the same type to the log.
|
||||
/// </summary>
|
||||
public static void Write<T>(string type, ConsoleColor color, params T[] values)
|
||||
{
|
||||
for (var i = 0; i < values.Length; i++) Write(type, color, values[i], DefaultTarget);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes one line to the log.
|
||||
/// </summary>
|
||||
public static void Write<T>(LogType type, T value, LogTarget target = LogTarget.Default)
|
||||
{
|
||||
Write(type.ToString(), Colors[type], value, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes one line to the log.
|
||||
/// </summary>
|
||||
public static void Write<T>(string type, ConsoleColor color, T value, LogTarget target = LogTarget.Default)
|
||||
{
|
||||
if (target == LogTarget.Default)
|
||||
target = DefaultTarget;
|
||||
|
||||
if (target.HasFlag(LogTarget.Console))
|
||||
ColorfulWriteLine(color, ProcessPreset(LogTarget.Console, type, value.ToString()));
|
||||
if (target.HasFlag(LogTarget.Debugger))
|
||||
Debug.WriteLine(ProcessPreset(LogTarget.Debugger, type, value.ToString()));
|
||||
if (target.HasFlag(LogTarget.File))
|
||||
_logStream?.WriteLine(ProcessPreset(LogTarget.File, type, value.ToString()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a text with a different color.
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void ColorfulWriteLine(ConsoleColor color, string value)
|
||||
{
|
||||
var before = Console.ForegroundColor;
|
||||
|
||||
Console.ForegroundColor = color;
|
||||
Console.WriteLine(value);
|
||||
Console.ForegroundColor = before;
|
||||
}
|
||||
|
||||
private static string ProcessPreset(LogTarget target, string type, string msg)
|
||||
{
|
||||
var preset = Preset[target];
|
||||
var now = DateTime.Now;
|
||||
|
||||
return preset.Replace("%date%", now.ToShortDateString())
|
||||
.Replace("%time%", now.ToShortTimeString())
|
||||
.Replace("%type%", type)
|
||||
.Replace("%msg%", msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
43
src/renderer/SM.Base/Objects/InstancedMesh.cs
Normal file
43
src/renderer/SM.Base/Objects/InstancedMesh.cs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#region usings
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using SM.OGL.Mesh;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// This class allows for fast mesh creation.
|
||||
/// </summary>
|
||||
public class InstancedMesh : Mesh
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates a mesh, with a primitive and attributes, that are required.
|
||||
/// </summary>
|
||||
/// <param name="type">The mesh type</param>
|
||||
/// <param name="enabledAttibute">A list of (additional) attributes.
|
||||
/// <para> Possible values: uv, normals and color </para>
|
||||
/// </param>
|
||||
public InstancedMesh(PrimitiveType type, string[] enabledAttibute) : base(type)
|
||||
{
|
||||
Attributes["vertex"] = Vertex = new VBO<Vector3>();
|
||||
|
||||
foreach (string attribute in enabledAttibute)
|
||||
switch (attribute)
|
||||
{
|
||||
case "uv":
|
||||
Attributes["uv"] = UVs = new VBO<Vector2>();
|
||||
break;
|
||||
case "normals":
|
||||
Attributes["normal"] = Normals = new VBO<Vector3>();
|
||||
break;
|
||||
case "color":
|
||||
Attributes["color"] = Color = new VBO<Color4>();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/renderer/SM.Base/Objects/Mesh.cs
Normal file
31
src/renderer/SM.Base/Objects/Mesh.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#region usings
|
||||
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using SM.OGL.Mesh;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Objects
|
||||
{
|
||||
/// <inheritdoc cref="GenericMesh" />
|
||||
public class Mesh : GenericMesh, ILineMesh
|
||||
{
|
||||
/// <summary>
|
||||
/// While initializing, it will add the <see cref="Color" /> to the data index.
|
||||
/// </summary>
|
||||
public Mesh(PrimitiveType type)
|
||||
{
|
||||
PrimitiveType = type;
|
||||
Attributes.Add(3, "color", Color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains vertex colors
|
||||
/// </summary>
|
||||
public virtual VBO<Color4> Color { get; protected set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public float LineWidth { get; set; } = 1;
|
||||
}
|
||||
}
|
||||
52
src/renderer/SM.Base/Objects/Static/AxisHelper.cs
Normal file
52
src/renderer/SM.Base/Objects/Static/AxisHelper.cs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#region usings
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using SM.OGL.Mesh;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Objects.Static
|
||||
{
|
||||
/// <summary>
|
||||
/// An AxisHelper-Model
|
||||
/// <para>White: -X, -Y, -Z</para>
|
||||
/// <para>Red: +X </para>
|
||||
/// <para>Green: +Y </para>
|
||||
/// <para>Blue: +Z </para>
|
||||
/// </summary>
|
||||
public class AxisHelper : Mesh
|
||||
{
|
||||
/// <summary>
|
||||
/// Object
|
||||
/// </summary>
|
||||
public static AxisHelper Object = new AxisHelper();
|
||||
|
||||
private AxisHelper() : base(PrimitiveType.Lines)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override VBO<Vector3> Vertex { get; protected set; } = new VBO<Vector3>
|
||||
{
|
||||
new Vector3(0, 0, 0),
|
||||
new Vector3(.5f, 0, 0),
|
||||
new Vector3(0, 0, 0),
|
||||
new Vector3(0, .5f, 0),
|
||||
new Vector3(0, 0, -.5f),
|
||||
new Vector3(0, 0, .5f)
|
||||
};
|
||||
|
||||
/// <inheritdoc />
|
||||
public override VBO<Color4> Color { get; protected set; } = new VBO<Color4>
|
||||
{
|
||||
Color4.White,
|
||||
Color4.Red,
|
||||
Color4.White,
|
||||
Color4.Green,
|
||||
Color4.White,
|
||||
Color4.DarkBlue
|
||||
};
|
||||
}
|
||||
}
|
||||
52
src/renderer/SM.Base/Objects/Static/Plate.cs
Normal file
52
src/renderer/SM.Base/Objects/Static/Plate.cs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#region usings
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using SM.OGL.Mesh;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Objects.Static
|
||||
{
|
||||
/// <summary>
|
||||
/// A basic plate
|
||||
/// </summary>
|
||||
public class Plate : GenericMesh
|
||||
{
|
||||
/// <summary>
|
||||
/// The object.
|
||||
/// </summary>
|
||||
public static Plate Object = new Plate();
|
||||
|
||||
//public override int[] Indices { get; set; } = new[] {0, 1, 2, 3};
|
||||
|
||||
private Plate()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override VBO<Vector3> Vertex { get; protected set; } = new VBO<Vector3>
|
||||
{
|
||||
new Vector3(-.5f, -.5f, 0),
|
||||
new Vector3(-.5f, .5f, 0),
|
||||
new Vector3(.5f, .5f, 0),
|
||||
new Vector3(.5f, -.5f, 0),
|
||||
};
|
||||
|
||||
/// <inheritdoc />
|
||||
public override VBO<Vector2> UVs { get; protected set; } = new VBO<Vector2>
|
||||
{
|
||||
new Vector2(0, 1),
|
||||
new Vector2(0, 0),
|
||||
new Vector2(1, 0),
|
||||
new Vector2(1, 1),
|
||||
};
|
||||
|
||||
/// <inheritdoc />
|
||||
public override PrimitiveType PrimitiveType { get; protected set; } = PrimitiveType.Quads;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override BoundingBox BoundingBox { get; } =
|
||||
new BoundingBox(new Vector3(-.5f, -.5f, 0), new Vector3(.5f, .5f, 0));
|
||||
}
|
||||
}
|
||||
25
src/renderer/SM.Base/OpenTK.dll.config
Normal file
25
src/renderer/SM.Base/OpenTK.dll.config
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<configuration>
|
||||
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||
<dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
|
||||
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
|
||||
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
|
||||
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
|
||||
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
|
||||
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
|
||||
<dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
|
||||
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
|
||||
<dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
|
||||
<!-- XQuartz compatibility (X11 on Mac) -->
|
||||
<dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/>
|
||||
<dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/>
|
||||
<dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/>
|
||||
<dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/>
|
||||
<dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/>
|
||||
<dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/>
|
||||
</configuration>
|
||||
212
src/renderer/SM.Base/PostEffects/BloomEffect.cs
Normal file
212
src/renderer/SM.Base/PostEffects/BloomEffect.cs
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
#region usings
|
||||
|
||||
using System.Drawing;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using SM.Base.Drawing;
|
||||
using SM.Base.PostProcess;
|
||||
using SM.Base.Utility;
|
||||
using SM.Base.Window;
|
||||
using SM.OGL.Framebuffer;
|
||||
using SM.OGL.Texture;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.PostEffects
|
||||
{
|
||||
/// <summary>
|
||||
/// A bloom post process effect.
|
||||
/// </summary>
|
||||
public class BloomEffect : PostProcessEffect
|
||||
{
|
||||
private static BezierCurve _defaultCurve = new BezierCurve(Vector2.UnitY, Vector2.Zero, new Vector2(0.4f, 0), new Vector2(.5f,0));
|
||||
private static readonly PostProcessShader _mergeShader = new PostProcessShader(
|
||||
AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath + ".bloom_merge_vert.glsl"),
|
||||
AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath + ".bloom_merge.glsl"));
|
||||
|
||||
private static readonly PostProcessShader _shader =
|
||||
new PostProcessShader(AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath + ".bloom_blur.glsl"));
|
||||
private const float _defaultTextureScale = .75f;
|
||||
|
||||
private Framebuffer _source;
|
||||
|
||||
private Framebuffer _bloomBuffer1;
|
||||
private Framebuffer _bloomBuffer2;
|
||||
|
||||
private readonly bool _hdr;
|
||||
|
||||
private readonly float _textureScale = .75f;
|
||||
|
||||
private BezierCurve _weightCurve;
|
||||
private float[] _weights;
|
||||
|
||||
private ColorAttachment _xBuffer;
|
||||
private ColorAttachment _yBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// A texture where you can define the amount of the bloom effect at each pixel.
|
||||
/// </summary>
|
||||
public TextureBase AmountMap;
|
||||
/// <summary>
|
||||
/// The transformation for the amount map.
|
||||
/// </summary>
|
||||
public TextureTransformation AmountTransform = new TextureTransformation();
|
||||
/// <summary>
|
||||
/// The maximal amount the amount map is clamped to.
|
||||
/// <para>Default: 1</para>
|
||||
/// </summary>
|
||||
public float MaxAmount = 1;
|
||||
/// <summary>
|
||||
/// The minimal amount the amount map is clamped to.
|
||||
/// <para>Default: 0</para>
|
||||
/// </summary>
|
||||
public float MinAmount = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The defines how often the x-y-flipflop happens.
|
||||
/// <para>Default: 8</para>
|
||||
/// </summary>
|
||||
public int Iterations = 8;
|
||||
/// <summary>
|
||||
/// The Threshold for the bloom effect.
|
||||
/// <para>Default: .8f</para>
|
||||
/// </summary>
|
||||
public float Threshold = .8f;
|
||||
/// <summary>
|
||||
/// Increases the brightness of the resulting effect.
|
||||
/// <para>Default: 1</para>
|
||||
/// </summary>
|
||||
public float Power = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Radius of the effect
|
||||
/// <para>Default: 2</para>
|
||||
/// </summary>
|
||||
public float Radius = 1;
|
||||
|
||||
/// <summary>
|
||||
/// This can disable the bloom calculation.
|
||||
/// <para>Default: true</para>
|
||||
/// </summary>
|
||||
public bool Enable = true;
|
||||
|
||||
/// <summary>
|
||||
/// This defines the weight curve.
|
||||
/// </summary>
|
||||
public BezierCurve WeightCurve
|
||||
{
|
||||
get => _weightCurve;
|
||||
set
|
||||
{
|
||||
_weightCurve = value;
|
||||
UpdateWeights();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// This defines how many picks the effect should pick from the weight curve.
|
||||
/// </summary>
|
||||
public int WeightCurvePickAmount = 4;
|
||||
|
||||
/// <summary>
|
||||
/// This creates a bloom effect.
|
||||
/// </summary>
|
||||
/// <param name="source">This can specify a own source framebuffer. If not set, it will take the Pipeline MainFramebuffer.</param>
|
||||
/// <param name="hdr">This allows to enable hdr returns.</param>
|
||||
/// <param name="textureScale">This allows for a increase in performance, by lowering the calculating texture scale.</param>
|
||||
public BloomEffect(Framebuffer source = null, bool hdr = false, float? textureScale = null)
|
||||
{
|
||||
_source = source;
|
||||
_hdr = hdr;
|
||||
_textureScale = textureScale.GetValueOrDefault(_defaultTextureScale);
|
||||
|
||||
WeightCurve = _defaultCurve;
|
||||
}
|
||||
|
||||
|
||||
private void UpdateWeights()
|
||||
{
|
||||
_weights = new float[WeightCurvePickAmount];
|
||||
|
||||
for (int i = 0; i < WeightCurvePickAmount; i++)
|
||||
_weights[i] = _weightCurve.CalculatePoint((float) (i + 1) / (WeightCurvePickAmount + 1)).Y;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void InitProcess()
|
||||
{
|
||||
_source ??= Pipeline.MainFramebuffer;
|
||||
|
||||
_source.ColorAttachments["color"].PixelInformation = PixelInformation.RGBA_HDR;
|
||||
|
||||
_bloomBuffer1 = new Framebuffer(Pipeline.ConnectedWindow, _textureScale)
|
||||
{
|
||||
Name = "BloomX"
|
||||
};
|
||||
_bloomBuffer1.Append("xBuffer", _xBuffer = new ColorAttachment(0, PixelInformation.RGBA_HDR));
|
||||
_bloomBuffer1.Compile();
|
||||
_bloomBuffer2 = new Framebuffer(Pipeline.ConnectedWindow, _textureScale)
|
||||
{
|
||||
Name = "BloomY"
|
||||
};
|
||||
_bloomBuffer2.Append("yBuffer", _yBuffer = new ColorAttachment(0, PixelInformation.RGBA_HDR));
|
||||
_bloomBuffer2.Compile();
|
||||
|
||||
Pipeline.Framebuffers.Add(_bloomBuffer1);
|
||||
Pipeline.Framebuffers.Add(_bloomBuffer2);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Draw(ColorAttachment source, DrawContext context)
|
||||
{
|
||||
if (Enable)
|
||||
{
|
||||
GL.Viewport(0, 0, (int) (Pipeline.ConnectedWindow.Width * _textureScale),
|
||||
(int) (Pipeline.ConnectedWindow.Height * _textureScale));
|
||||
|
||||
Framebuffer target = Framebuffer.GetCurrentlyActive();
|
||||
bool first = true, hoz = true;
|
||||
int iter = Iterations * 2;
|
||||
for (int i = 0; i < iter; i++)
|
||||
{
|
||||
(hoz ? _bloomBuffer1 : _bloomBuffer2).Activate(false);
|
||||
|
||||
_shader.Draw(collection =>
|
||||
{
|
||||
collection["renderedTexture"].SetTexture(first ? source : (hoz ? _yBuffer : _xBuffer));
|
||||
|
||||
collection["First"].SetUniform1(first);
|
||||
collection["Threshold"].SetUniform1(Threshold);
|
||||
|
||||
collection["Horizontal"].SetUniform1(hoz);
|
||||
|
||||
collection["Weights"].SetUniform1(_weights);
|
||||
collection["WeightCount"].SetUniform1(WeightCurvePickAmount);
|
||||
collection["Power"].SetUniform1(Power);
|
||||
|
||||
collection["Radius"].SetUniform1(_textureScale * Radius);
|
||||
});
|
||||
|
||||
hoz = !hoz;
|
||||
if (first) first = false;
|
||||
}
|
||||
|
||||
GL.Viewport(Pipeline.ConnectedWindow.ClientRectangle);
|
||||
target.Activate();
|
||||
}
|
||||
|
||||
_mergeShader.Draw(collection =>
|
||||
{
|
||||
collection["Scene"].SetTexture(source);
|
||||
collection["Bloom"].SetTexture(_yBuffer);
|
||||
|
||||
collection["MinAmount"].SetUniform1(MinAmount);
|
||||
collection["MaxAmount"].SetUniform1(MaxAmount);
|
||||
collection["AmountMap"].SetTexture(AmountMap, collection["HasAmountMap"]);
|
||||
collection["TextureTransform"].SetMatrix3(AmountTransform.GetMatrix());
|
||||
|
||||
collection["Exposure"].SetUniform1(context.UseCamera.Exposure);
|
||||
collection["HDR"].SetUniform1(_hdr);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
74
src/renderer/SM.Base/PostEffects/PostProcessUtility.cs
Normal file
74
src/renderer/SM.Base/PostEffects/PostProcessUtility.cs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#region usings
|
||||
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using SM.Base.PostProcess;
|
||||
using SM.Base.Utility;
|
||||
using SM.OGL.Framebuffer;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.PostEffects
|
||||
{
|
||||
/// <summary>
|
||||
/// This class has some utility for render pipelines
|
||||
/// </summary>
|
||||
public static class PostProcessUtility
|
||||
{
|
||||
private static readonly PostProcessShader _hdrExposureShader =
|
||||
new PostProcessShader(AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath + ".finalize_hdr.glsl"));
|
||||
|
||||
private static readonly PostProcessShader _gammaShader =
|
||||
new PostProcessShader(
|
||||
AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath + ".finalize_gamma.glsl"));
|
||||
|
||||
/// <summary>
|
||||
/// The gamma that is used for <see cref="FinalizeGamma"/> and <see cref="FinalizeHDR"/>.
|
||||
/// </summary>
|
||||
public static float Gamma = 2.2f;
|
||||
|
||||
/// <summary>
|
||||
/// This resolves a multisampled framebuffer to a non-multisampled renderbuffer.
|
||||
/// <para>This removes the depth buffer.</para>
|
||||
/// </summary>
|
||||
/// <param name="multisampledBuffers"></param>
|
||||
/// <param name="target"></param>
|
||||
public static void ResolveMultisampledBuffers(Framebuffer multisampledBuffers, Framebuffer target)
|
||||
{
|
||||
multisampledBuffers.Activate(FramebufferTarget.ReadFramebuffer);
|
||||
target.Activate(FramebufferTarget.DrawFramebuffer);
|
||||
GL.BlitFramebuffer(0, 0, (int) multisampledBuffers.Size.X, (int) multisampledBuffers.Size.Y, 0, 0,
|
||||
(int) target.Size.X, (int) target.Size.Y, ClearBufferMask.ColorBufferBit,
|
||||
BlitFramebufferFilter.Nearest);
|
||||
|
||||
target.Activate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This converts HDR to LDR and applys gamma.
|
||||
/// </summary>
|
||||
/// <param name="attachment"></param>
|
||||
/// <param name="exposure"></param>
|
||||
public static void FinalizeHDR(ColorAttachment attachment, float exposure)
|
||||
{
|
||||
_hdrExposureShader.Draw(u =>
|
||||
{
|
||||
u["Gamma"].SetUniform1(Gamma);
|
||||
u["Exposure"].SetUniform1(exposure);
|
||||
u["Scene"].SetTexture(attachment);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This applys gamma
|
||||
/// </summary>
|
||||
/// <param name="attachment"></param>
|
||||
public static void FinalizeGamma(ColorAttachment attachment)
|
||||
{
|
||||
_gammaShader.Draw(u =>
|
||||
{
|
||||
u["Gamma"].SetUniform1(Gamma);
|
||||
u["Scene"].SetTexture(attachment);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
48
src/renderer/SM.Base/PostEffects/Shaders/bloom_blur.glsl
Normal file
48
src/renderer/SM.Base/PostEffects/Shaders/bloom_blur.glsl
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#version 330
|
||||
#define PI 3.14159265359
|
||||
|
||||
uniform sampler2D renderedTexture;
|
||||
uniform float RenderScale;
|
||||
|
||||
uniform bool First;
|
||||
uniform float Threshold;
|
||||
|
||||
uniform bool Horizontal;
|
||||
|
||||
uniform float[32] Weights;
|
||||
uniform int WeightCount;
|
||||
uniform float Power;
|
||||
|
||||
uniform float Radius;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
vec4 GetRenderColorOffset(vec2 offset);
|
||||
|
||||
float brightness(vec3 c)
|
||||
{
|
||||
return max(max(c.r, c.g), c.b);
|
||||
}
|
||||
|
||||
float bright;
|
||||
|
||||
float GetWeight(int dif) {
|
||||
return Weights[dif];
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 thres = vec3(First ? Threshold : 0);
|
||||
|
||||
vec2 tex_offset = 1.0 / textureSize(renderedTexture, 0) * vec2(Horizontal ? 1 : 0, Horizontal ? 0 : 1);
|
||||
|
||||
vec3 result = max(GetRenderColorOffset(vec2(0)).rgb - thres, 0) * (First ? Power : 1) * GetWeight(0);
|
||||
|
||||
float radi = Radius + (length(result));
|
||||
|
||||
for(int i = 1; i < WeightCount; i++) {
|
||||
result += max(GetRenderColorOffset(tex_offset * i * radi).rgb - thres, 0) * (First ? Power : 1) * GetWeight(i);
|
||||
result += max(GetRenderColorOffset(-tex_offset * i * radi).rgb - thres, 0) * (First ? Power : 1) * GetWeight(i);
|
||||
}
|
||||
|
||||
color = vec4(result, 1);
|
||||
}
|
||||
30
src/renderer/SM.Base/PostEffects/Shaders/bloom_merge.glsl
Normal file
30
src/renderer/SM.Base/PostEffects/Shaders/bloom_merge.glsl
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#version 330
|
||||
|
||||
in vec2 vTexture;
|
||||
in vec2 TransformedTexture;
|
||||
|
||||
uniform sampler2D Scene;
|
||||
uniform sampler2D Bloom;
|
||||
|
||||
uniform float MinAmount;
|
||||
uniform float MaxAmount;
|
||||
uniform sampler2D AmountMap;
|
||||
uniform bool HasAmountMap;
|
||||
|
||||
uniform float Exposure;
|
||||
uniform bool HDR;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
void main() {
|
||||
vec3 result = texture(Bloom, vTexture).rgb;
|
||||
if (HasAmountMap) result *= clamp(length(texture(AmountMap, TransformedTexture).rgb) * (MaxAmount - MinAmount) + MinAmount, 0, 1);
|
||||
if (!HDR) {
|
||||
result = vec3(1.0) - exp(-result * Exposure);
|
||||
}
|
||||
|
||||
|
||||
result = texture(Scene, vTexture).rgb + result;
|
||||
|
||||
color = vec4(result, 1);
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#version 330
|
||||
|
||||
layout(location = 1) in vec2 aTex;
|
||||
|
||||
uniform mat3 TextureTransform;
|
||||
|
||||
out vec2 TransformedTexture;
|
||||
|
||||
void vertex() {
|
||||
TransformedTexture = vec2(TextureTransform * vec3(aTex, 1));
|
||||
}
|
||||
12
src/renderer/SM.Base/PostEffects/Shaders/finalize_gamma.glsl
Normal file
12
src/renderer/SM.Base/PostEffects/Shaders/finalize_gamma.glsl
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#version 330
|
||||
|
||||
in vec2 vTexture;
|
||||
|
||||
uniform sampler2D Scene;
|
||||
uniform float Gamma;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
void main() {
|
||||
color = vec4(pow(texture(Scene, vTexture).rgb, vec3(1 / Gamma)), 1);
|
||||
}
|
||||
15
src/renderer/SM.Base/PostEffects/Shaders/finalize_hdr.glsl
Normal file
15
src/renderer/SM.Base/PostEffects/Shaders/finalize_hdr.glsl
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#version 330
|
||||
|
||||
in vec2 vTexture;
|
||||
|
||||
uniform sampler2D Scene;
|
||||
uniform float Exposure;
|
||||
uniform float Gamma;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
void main() {
|
||||
vec3 result = vec3(1) - exp(-texture(Scene, vTexture).rgb * Exposure);
|
||||
|
||||
color = vec4(pow(result, vec3(1 / Gamma)), 1);
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#version 330
|
||||
|
||||
in vec2 vTexture;
|
||||
|
||||
uniform sampler2D renderedTexture;
|
||||
|
||||
vec4 GetRenderColor() {
|
||||
return texture(renderedTexture, vTexture);
|
||||
}
|
||||
|
||||
vec4 GetRenderColorOffset(vec2 offset) {
|
||||
return texture(renderedTexture, vTexture + offset);
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
#version 330
|
||||
|
||||
layout(location = 0) in vec3 aPos;
|
||||
layout(location = 1) in vec2 aTex;
|
||||
|
||||
uniform mat4 MVP;
|
||||
|
||||
out vec2 vTexture;
|
||||
|
||||
void main() {
|
||||
vTexture = aTex;
|
||||
|
||||
gl_Position = MVP * vec4(aPos, 1);
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#version 330
|
||||
|
||||
layout(location = 0) in vec3 aPos;
|
||||
layout(location = 1) in vec2 aTex;
|
||||
|
||||
uniform mat4 MVP;
|
||||
|
||||
out vec2 vTexture;
|
||||
|
||||
void vertex();
|
||||
|
||||
void main() {
|
||||
vTexture = aTex;
|
||||
|
||||
gl_Position = MVP * vec4(aPos, 1);
|
||||
|
||||
vertex();
|
||||
}
|
||||
57
src/renderer/SM.Base/PostProcess/PostProcessEffect.cs
Normal file
57
src/renderer/SM.Base/PostProcess/PostProcessEffect.cs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#region usings
|
||||
|
||||
using OpenTK;
|
||||
using SM.Base.Scene;
|
||||
using SM.Base.Window;
|
||||
using SM.OGL.Framebuffer;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.PostProcess
|
||||
{
|
||||
/// <summary>
|
||||
/// Basis for a post process effect
|
||||
/// </summary>
|
||||
public abstract class PostProcessEffect
|
||||
{
|
||||
/// <summary>
|
||||
/// This contains the transformation matrix for post process effects.
|
||||
/// </summary>
|
||||
public static Matrix4 Mvp = Matrix4.Identity;
|
||||
|
||||
/// <summary>
|
||||
/// This contains the pipeline this instance is currently active.
|
||||
/// </summary>
|
||||
protected RenderPipeline Pipeline;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the effect.
|
||||
/// </summary>
|
||||
/// <param name="pipeline"></param>
|
||||
public void Initilize(RenderPipeline pipeline)
|
||||
{
|
||||
Pipeline = pipeline;
|
||||
InitProcess();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method, to initialize the shader.
|
||||
/// </summary>
|
||||
protected virtual void InitProcess()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Method to draw the actual effect.
|
||||
/// </summary>
|
||||
public abstract void Draw(ColorAttachment source, DrawContext context);
|
||||
|
||||
/// <summary>
|
||||
/// Event, when the scene changed.
|
||||
/// </summary>
|
||||
public virtual void SceneChanged(GenericScene scene)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
72
src/renderer/SM.Base/PostProcess/PostProcessShader.cs
Normal file
72
src/renderer/SM.Base/PostProcess/PostProcessShader.cs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using SM.Base.Objects.Static;
|
||||
using SM.Base.Utility;
|
||||
using SM.OGL.Shaders;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.PostProcess
|
||||
{
|
||||
/// <summary>
|
||||
/// Specific shader for post processing.
|
||||
/// </summary>
|
||||
public class PostProcessShader : GenericShader
|
||||
{
|
||||
private static readonly ShaderFile _fragExtensions =
|
||||
new ShaderFile(AssemblyUtility.ReadAssemblyFile("SM.Base.PostProcess.DefaultFiles.extensions.frag"));
|
||||
|
||||
private static readonly ShaderFile _normalVertex =
|
||||
new ShaderFile(AssemblyUtility.ReadAssemblyFile("SM.Base.PostProcess.DefaultFiles.vertexFile.vert"));
|
||||
|
||||
private static readonly string _normalVertexWithExt =
|
||||
AssemblyUtility.ReadAssemblyFile("SM.Base.PostProcess.DefaultFiles.vertexWithExt.vert");
|
||||
|
||||
/// <summary>
|
||||
/// Creates the shader with the default vertex shader and custom fragment.
|
||||
/// </summary>
|
||||
public PostProcessShader(string fragment) : this(_normalVertex,
|
||||
new ShaderFile(fragment))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the shader with an vertex extension and custom fragment.
|
||||
/// </summary>
|
||||
/// <param name="vertexExt"></param>
|
||||
/// <param name="fragment"></param>
|
||||
public PostProcessShader(string vertexExt, string fragment) : this(new ShaderFile(_normalVertexWithExt)
|
||||
{
|
||||
GLSLExtensions = new List<ShaderFile> {new ShaderFile(vertexExt)}
|
||||
}, new ShaderFile(fragment))
|
||||
{
|
||||
}
|
||||
|
||||
private PostProcessShader(ShaderFile vertex, ShaderFile fragment) : base(
|
||||
new ShaderFileCollection(vertex, fragment))
|
||||
{
|
||||
fragment.GLSLExtensions.Add(_fragExtensions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the shader with special uniforms.
|
||||
/// </summary>
|
||||
/// <param name="setUniformAction"></param>
|
||||
public void Draw(Action<UniformCollection> setUniformAction)
|
||||
{
|
||||
Activate();
|
||||
Plate.Object.Activate();
|
||||
|
||||
Uniforms["MVP"].SetMatrix4(PostProcessEffect.Mvp);
|
||||
|
||||
setUniformAction(Uniforms);
|
||||
|
||||
GL.DrawArrays(PrimitiveType.Quads, 0, 4);
|
||||
|
||||
CleanUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
39
src/renderer/SM.Base/Properties/AssemblyInfo.cs
Normal file
39
src/renderer/SM.Base/Properties/AssemblyInfo.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#region usings
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
#endregion
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Basis for every SMRenderer")]
|
||||
[assembly: AssemblyDescription("SMRenderer-Basis functions")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("iedSoftworks")]
|
||||
[assembly: AssemblyProduct("SM.Base")]
|
||||
[assembly: AssemblyCopyright("Copyright © iedSoftworks 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("8e733844-4204-43e7-b3dc-3913cddabb0d")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
171
src/renderer/SM.Base/SM.Base.csproj
Normal file
171
src/renderer/SM.Base/SM.Base.csproj
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\packages\SharpFont.4.0.1\build\SharpFont.props" Condition="Exists('..\..\..\packages\SharpFont.4.0.1\build\SharpFont.props')" />
|
||||
<Import Project="..\..\..\packages\SharpFont.Dependencies.2.6\build\SharpFont.Dependencies.props" Condition="Exists('..\..\..\packages\SharpFont.Dependencies.2.6\build\SharpFont.Dependencies.props')" />
|
||||
<Import Project="..\..\..\IAmTwo - Kopie\packages\SharpFont.4.0.1\build\SharpFont.props" Condition="Exists('..\..\..\IAmTwo - Kopie\packages\SharpFont.4.0.1\build\SharpFont.props')" />
|
||||
<Import Project="..\..\..\IAmTwo - Kopie\packages\SharpFont.Dependencies.2.6\build\SharpFont.Dependencies.props" Condition="Exists('..\..\..\IAmTwo - Kopie\packages\SharpFont.Dependencies.2.6\build\SharpFont.Dependencies.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{8E733844-4204-43E7-B3DC-3913CDDABB0D}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SM.Base</RootNamespace>
|
||||
<AssemblyName>SM.Base</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<DocumentationFile>bin\Debug\SM.Base.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Animation\AnimationCurves.cs" />
|
||||
<Compile Include="Animation\InterpolationProcess.cs" />
|
||||
<Compile Include="Controls\Keyboard.cs" />
|
||||
<Compile Include="Controls\Mouse.cs" />
|
||||
<Compile Include="Drawing\DrawingBasis.cs" />
|
||||
<Compile Include="Drawing\GenericTransformation.cs" />
|
||||
<Compile Include="Drawing\Instance.cs" />
|
||||
<Compile Include="Drawing\Particles\ParticleInstance.cs" />
|
||||
<Compile Include="Drawing\ShaderArguments.cs" />
|
||||
<Compile Include="Drawing\TextureTransformation.cs" />
|
||||
<Compile Include="Drawing\Text\Font.cs" />
|
||||
<Compile Include="PostEffects\PostProcessUtility.cs" />
|
||||
<Compile Include="Scene\ICollectionItem.cs" />
|
||||
<Compile Include="Scene\IFixedScriptable.cs" />
|
||||
<Compile Include="Shaders\MaterialShader.cs" />
|
||||
<Compile Include="Drawing\Particles\ParticleMovement.cs" />
|
||||
<Compile Include="Drawing\Particles\ParticleDrawingBasis.cs" />
|
||||
<Compile Include="Shaders\SimpleShader.cs" />
|
||||
<Compile Include="Types\CVector4.cs" />
|
||||
<Compile Include="Types\CVectorBase.cs" />
|
||||
<Compile Include="Utility\IInitializable.cs" />
|
||||
<Compile Include="Utility\Ray.cs" />
|
||||
<Compile Include="Utility\Util.cs" />
|
||||
<Compile Include="Window\Contexts\DrawContext.cs" />
|
||||
<Compile Include="Window\Contexts\FixedUpdateContext.cs" />
|
||||
<Compile Include="Window\Contexts\UpdateContext.cs" />
|
||||
<Compile Include="Window\GLWindow.cs" />
|
||||
<Compile Include="Log.cs" />
|
||||
<Compile Include="Objects\InstancedMesh.cs" />
|
||||
<Compile Include="Objects\Mesh.cs" />
|
||||
<Compile Include="Objects\Static\AxisHelper.cs" />
|
||||
<Compile Include="PostEffects\BloomEffect.cs" />
|
||||
<Compile Include="PostProcess\PostProcessEffect.cs" />
|
||||
<Compile Include="PostProcess\PostProcessShader.cs" />
|
||||
<Compile Include="Scene\IScriptable.cs" />
|
||||
<Compile Include="Scene\IShowCollection.cs" />
|
||||
<Compile Include="Scene\IShowItem.cs" />
|
||||
<Compile Include="Drawing\Material.cs" />
|
||||
<Compile Include="Scene\IBackgroundItem.cs" />
|
||||
<Compile Include="Scene\GenericItemCollection.cs" />
|
||||
<Compile Include="Shaders\Extensions\ExtensionManager.cs" />
|
||||
<Compile Include="SMRenderer.cs" />
|
||||
<Compile Include="Textures\Texture.cs" />
|
||||
<Compile Include="Drawing\Text\CharParameter.cs" />
|
||||
<Compile Include="Drawing\Text\FontCharStorage.cs" />
|
||||
<Compile Include="Drawing\Text\TextDrawingBasis.cs" />
|
||||
<Compile Include="Time\Interval.cs" />
|
||||
<Compile Include="Time\Stopwatch.cs" />
|
||||
<Compile Include="Time\Timer.cs" />
|
||||
<Compile Include="Types\CVector1.cs" />
|
||||
<Compile Include="Types\CVector2.cs" />
|
||||
<Compile Include="Types\CVector3.cs" />
|
||||
<Compile Include="Utility\Assembly.cs" />
|
||||
<Compile Include="Utility\Deltatime.cs" />
|
||||
<Compile Include="Utility\Randomize.cs" />
|
||||
<Compile Include="Utility\RotationUtility.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Scene\GenericCamera.cs" />
|
||||
<Compile Include="Scene\GenericScene.cs" />
|
||||
<Compile Include="Objects\Static\Plate.cs" />
|
||||
<Compile Include="Window\IGenericWindow.cs" />
|
||||
<Compile Include="Window\ISetup.cs" />
|
||||
<Compile Include="Window\RenderPipeline.cs" />
|
||||
<Compile Include="Window\WindowCode.cs" />
|
||||
<Compile Include="Window\WindowFlags.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Shaders\Extensions\vertex\basic.vert" />
|
||||
<EmbeddedResource Include="PostProcess\DefaultFiles\vertexFile.vert" />
|
||||
<EmbeddedResource Include="PostProcess\DefaultFiles\extensions.frag" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="PostProcess\DefaultFiles\vertexWithExt.vert" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="PostEffects\Shaders\bloom_blur.glsl" />
|
||||
<EmbeddedResource Include="PostEffects\Shaders\bloom_merge.glsl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Shaders\SimpleShaderPresets\basic_vertex.glsl" />
|
||||
<EmbeddedResource Include="Shaders\SimpleShaderPresets\instanced_vertex.glsl" />
|
||||
<EmbeddedResource Include="PostEffects\Shaders\bloom_merge_vert.glsl" />
|
||||
<EmbeddedResource Include="PostEffects\Shaders\finalize_hdr.glsl" />
|
||||
<EmbeddedResource Include="PostEffects\Shaders\finalize_gamma.glsl" />
|
||||
<EmbeddedResource Include="Shaders\Extensions\fragment\textureGamma.glsl" />
|
||||
<EmbeddedResource Include="Shaders\Extensions\fragment\noise.glsl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Window\winIcon.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SM.OGL\SM.OGL.csproj">
|
||||
<Project>{f604d684-bc1d-4819-88b5-8b5d03a17be0}</Project>
|
||||
<Name>SM.OGL</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="OpenTK, Version=3.3.1.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\OpenTK.3.3.1\lib\net20\OpenTK.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SharpFont, Version=4.0.1.200, Culture=neutral, PublicKeyToken=48add4c483071cdf, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\SharpFont.4.0.1\lib\net45\SharpFont.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.IO.Compression.FileSystem" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Windows" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.XML" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="OpenTK.dll.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
5
src/renderer/SM.Base/SM.Base.csproj.DotSettings
Normal file
5
src/renderer/SM.Base/SM.Base.csproj.DotSettings
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">Latest</s:String>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=windows/@EntryIndexedValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=windows_005Ccontexts/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=window_005Ccontexts/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
66
src/renderer/SM.Base/SMRenderer.cs
Normal file
66
src/renderer/SM.Base/SMRenderer.cs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#region usings
|
||||
|
||||
using SM.Base.Drawing.Text;
|
||||
using SM.Base.Objects.Static;
|
||||
using SM.Base.Shaders;
|
||||
using SM.Base.Utility;
|
||||
using SM.Base.Window;
|
||||
using SM.OGL.Mesh;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains different information about this renderer.
|
||||
/// </summary>
|
||||
public class SMRenderer
|
||||
{
|
||||
internal const string PostProcessPath = "SM.Base.PostEffects.Shaders";
|
||||
|
||||
/// <summary>
|
||||
/// Defines, how many instances the 'SM_base_vertex_basic'-extension can handle.
|
||||
/// </summary>
|
||||
public const int MaxInstances = 32;
|
||||
|
||||
/// <summary>
|
||||
/// The default mesh.
|
||||
/// </summary>
|
||||
public static GenericMesh DefaultMesh = Plate.Object;
|
||||
|
||||
/// <summary>
|
||||
/// The default font.
|
||||
/// </summary>
|
||||
public static Font DefaultFont;
|
||||
|
||||
/// <summary>
|
||||
/// The default deltatime helper.
|
||||
/// </summary>
|
||||
public static Deltatime DefaultDeltatime = new Deltatime();
|
||||
|
||||
/// <summary>
|
||||
/// The default material shader.
|
||||
/// </summary>
|
||||
public static MaterialShader DefaultMaterialShader;
|
||||
|
||||
/// <summary>
|
||||
/// The default render pipeline.
|
||||
/// </summary>
|
||||
public static RenderPipeline DefaultRenderPipeline;
|
||||
|
||||
/// <summary>
|
||||
/// Shows more information onto the log system.
|
||||
/// </summary>
|
||||
public static bool AdvancedDebugging = false;
|
||||
|
||||
/// <summary>
|
||||
/// Current Frame
|
||||
/// </summary>
|
||||
public static ulong CurrentFrame { get; internal set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the current active window.
|
||||
/// </summary>
|
||||
public static IGenericWindow CurrentWindow { get; internal set; }
|
||||
}
|
||||
}
|
||||
69
src/renderer/SM.Base/Scene/GenericCamera.cs
Normal file
69
src/renderer/SM.Base/Scene/GenericCamera.cs
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
#region usings
|
||||
|
||||
using OpenTK;
|
||||
using SM.Base.Window;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Scene
|
||||
{
|
||||
/// <summary>
|
||||
/// Controller for a camera
|
||||
/// </summary>
|
||||
public abstract class GenericCamera
|
||||
{
|
||||
/// <summary>
|
||||
/// Exposure defines the exposure to the Scene.
|
||||
/// </summary>
|
||||
public float Exposure = 1;
|
||||
|
||||
/// <summary>
|
||||
/// This defines what is up. (Normalized)
|
||||
/// <para>Default: <see cref="Vector3.UnitY" /></para>
|
||||
/// </summary>
|
||||
public Vector3 UpVector { get; set; } = Vector3.UnitY;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the world matrix that is connected to this camera.
|
||||
/// </summary>
|
||||
public Matrix4 World { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Contains the view matrix of this camera.
|
||||
/// <para>Default: <see cref="Matrix4.Identity" /></para>
|
||||
/// </summary>
|
||||
public Matrix4 View { get; protected set; } = Matrix4.Identity;
|
||||
|
||||
/// <summary>
|
||||
/// Represents if the camera is orthographic.
|
||||
/// </summary>
|
||||
public abstract bool Orthographic { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the view matrix.
|
||||
/// </summary>
|
||||
/// <returns>The calculated view matrix. Same as <see cref="View" /></returns>
|
||||
internal void CalculateViewMatrix(IGenericWindow window)
|
||||
{
|
||||
View = ViewCalculation(window);
|
||||
if (WorldCalculation(window, out Matrix4 world)) World = world;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This calculates the view matrix.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The new view matrix. This is the returns for <see cref="CalculateViewMatrix" /> and the next value for
|
||||
/// <see cref="View" />.
|
||||
/// </returns>
|
||||
protected abstract Matrix4 ViewCalculation(IGenericWindow window);
|
||||
|
||||
/// <summary>
|
||||
/// This calculates the world.
|
||||
/// </summary>
|
||||
/// <param name="window"></param>
|
||||
/// <param name="world"></param>
|
||||
/// <returns></returns>
|
||||
protected abstract bool WorldCalculation(IGenericWindow window, out Matrix4 world);
|
||||
}
|
||||
}
|
||||
320
src/renderer/SM.Base/Scene/GenericItemCollection.cs
Normal file
320
src/renderer/SM.Base/Scene/GenericItemCollection.cs
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using SM.Base.Drawing;
|
||||
using SM.Base.Window;
|
||||
using SM.Base.Window.Contexts;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Scene
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains a list of show items.
|
||||
/// </summary>
|
||||
public abstract class GenericItemCollection : List<IShowItem>, IShowItem, IShowCollection, IScriptable, IFixedScriptable
|
||||
{
|
||||
private readonly List<IScriptable> _scriptableObjects = new List<IScriptable>();
|
||||
private readonly List<IFixedScriptable> _fixedScriptables = new List<IFixedScriptable>();
|
||||
|
||||
/// <summary>
|
||||
/// Currently active script objects.
|
||||
/// </summary>
|
||||
public ReadOnlyCollection<IScriptable> ScriptableObjects =>
|
||||
new ReadOnlyCollection<IScriptable>(_scriptableObjects);
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool UpdateActive { get; set; } = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public List<IShowItem> Objects => this;
|
||||
|
||||
/// <inheritdoc />
|
||||
public object Parent { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name { get; set; } = "Unnamed Item Collection";
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICollection<string> Flags { get; set; } = new List<string> {"collection"};
|
||||
|
||||
/// <inheritdoc cref="IShowItem" />
|
||||
public bool Active { get; set; } = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool RenderActive { get; set; } = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void FixedUpdate(FixedUpdateContext context)
|
||||
{
|
||||
if (!Active || !UpdateActive) return;
|
||||
|
||||
for (int i = 0; i < _fixedScriptables.Count; i++)
|
||||
{
|
||||
_fixedScriptables[i].FixedUpdate(context);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IShowCollection.Draw" />
|
||||
public virtual void Draw(DrawContext context)
|
||||
{
|
||||
if (!Active || !RenderActive) return;
|
||||
|
||||
for (var i = 0; i < Objects.Count; i++)
|
||||
{
|
||||
if (!this[i].Active || !this[i].RenderActive) continue;
|
||||
this[i].Draw(context);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void Update(UpdateContext context)
|
||||
{
|
||||
if (!Active || !UpdateActive) return;
|
||||
|
||||
for (var i = 0; i < _scriptableObjects.Count; i++)
|
||||
{
|
||||
if (!_scriptableObjects[i].Active || !_scriptableObjects[i].UpdateActive) continue;
|
||||
_scriptableObjects[i].Update(context);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void OnAdded(object sender)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void OnRemoved(object sender)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds items to the draw and the script collection, when applicable.
|
||||
/// </summary>
|
||||
public void Add(params ICollectionItem[] items)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item is IShowItem show)
|
||||
addObject(show);
|
||||
|
||||
if (item is IScriptable scriptable)
|
||||
addScript(scriptable);
|
||||
|
||||
if (item is IFixedScriptable fixedScriptable)
|
||||
addScript(fixedScriptable);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds the object to the collection.
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
[Obsolete("Please use Add()")]
|
||||
public void AddObject(IShowItem item)
|
||||
{
|
||||
addObject(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the script to the collection.
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
[Obsolete("Please use Add()")]
|
||||
public void AddScript(IScriptable item)
|
||||
{
|
||||
addScript(item);
|
||||
}
|
||||
|
||||
|
||||
private void addObject(IShowItem item)
|
||||
{
|
||||
base.Add(item);
|
||||
item.Parent = this;
|
||||
item.OnAdded(this);
|
||||
}
|
||||
|
||||
private void addScript(IScriptable item)
|
||||
{
|
||||
_scriptableObjects.Add(item);
|
||||
}
|
||||
|
||||
private void addScript(IFixedScriptable item)
|
||||
{
|
||||
_fixedScriptables.Add(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an object from the drawing list.
|
||||
/// <para>If the object is a scriptable object, it will remove the object from that list as well.</para>
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
public void Remove(params ICollectionItem[] items)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item is IShowItem show)
|
||||
removeObject(show);
|
||||
|
||||
if (item is IScriptable scriptable)
|
||||
removeScript(scriptable);
|
||||
|
||||
if (item is IFixedScriptable fixedScriptable)
|
||||
removeScript(fixedScriptable);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the object from the draw collection.
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
[Obsolete("Please use Remove()")]
|
||||
public void RemoveObject(IShowItem item)
|
||||
{
|
||||
removeObject(item);
|
||||
}
|
||||
|
||||
private void removeObject(IShowItem item)
|
||||
{
|
||||
base.Remove(item);
|
||||
item.Parent = null;
|
||||
item.OnRemoved(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the object from the script collection.
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
[Obsolete("Please use Remove()")]
|
||||
public void RemoveScript(IScriptable item)
|
||||
{
|
||||
removeScript(item);
|
||||
}
|
||||
|
||||
private void removeScript(IScriptable item)
|
||||
{
|
||||
_scriptableObjects.Remove(item);
|
||||
}
|
||||
|
||||
private void removeScript(IFixedScriptable item)
|
||||
{
|
||||
_fixedScriptables.Remove(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the entire collection of everything.
|
||||
/// </summary>
|
||||
public new void Clear()
|
||||
{
|
||||
foreach (IShowItem item in this.ToArray()) removeObject(item);
|
||||
foreach (IScriptable scriptable in _scriptableObjects.ToArray()) removeScript(scriptable);
|
||||
foreach (IFixedScriptable scriptable in _fixedScriptables.ToArray()) removeScript(scriptable);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the entire collection of selected systems.
|
||||
/// <para>If f.E. a object is both visual and scriptable and you clear the visuals, the scriptable-entry will stay.</para>
|
||||
/// <param name="visuals">Clears visuals</param>
|
||||
/// <param name="scriptables">Clears scriptables</param>
|
||||
/// <param name="fixedScriptables">Clears fixed scriptables</param>
|
||||
/// </summary>
|
||||
public void Clear(bool visuals = false, bool scriptables = false, bool fixedScriptables = false)
|
||||
{
|
||||
if (visuals) foreach (IShowItem item in this.ToArray()) removeObject(item);
|
||||
if (scriptables) foreach (IScriptable scriptable in _scriptableObjects.ToArray()) removeScript(scriptable);
|
||||
if (fixedScriptables) foreach (IFixedScriptable scriptable in _fixedScriptables.ToArray()) removeScript(scriptable);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all objects in the drawing list.
|
||||
/// <para>Not reclusive.</para>
|
||||
/// </summary>
|
||||
/// <param name="includeCollections">If true, it will add collections as well.</param>
|
||||
/// <returns></returns>
|
||||
public ICollection<IShowItem> GetAllItems(bool includeCollections = false)
|
||||
{
|
||||
List<IShowItem> items = new List<IShowItem>();
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
if (!includeCollections && this[i] is IShowCollection) continue;
|
||||
items.Add(this[i]);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a object with this name or the default, if not available.
|
||||
/// <para>Not reclusive.</para>
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IShowItem GetItemByName(string name)
|
||||
{
|
||||
IShowItem obj = default;
|
||||
for (var i = 0; i < Count; i++)
|
||||
if (this[i].Name == name)
|
||||
{
|
||||
obj = this[i];
|
||||
break;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a object with this name or the default if not available.
|
||||
/// <para>Not reclusive.</para>
|
||||
/// </summary>
|
||||
/// <typeparam name="TGetItem">Type of return</typeparam>
|
||||
public TGetItem GetItemByName<TGetItem>(string name)
|
||||
where TGetItem : IShowItem
|
||||
{
|
||||
return (TGetItem) GetItemByName(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all object that have this flag.
|
||||
/// <para>Only in this list.</para>
|
||||
/// </summary>
|
||||
public ICollection<IShowItem> GetItemsWithFlag(string flag)
|
||||
{
|
||||
var list = new List<IShowItem>();
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
var obj = this[i];
|
||||
if (obj.Flags == null) continue;
|
||||
if (obj.Flags.Contains(flag)) list.Add(obj);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains a list of show items with transformation.
|
||||
/// </summary>
|
||||
/// <typeparam name="TTransformation">The type of transformation.</typeparam>
|
||||
public abstract class GenericItemCollection<TTransformation> : GenericItemCollection,
|
||||
IShowTransformItem<TTransformation>
|
||||
where TTransformation : GenericTransformation, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Transformation of the collection
|
||||
/// </summary>
|
||||
public TTransformation Transform { get; set; } = new TTransformation();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Draw(DrawContext context)
|
||||
{
|
||||
Transform.LastMaster = context.ModelMatrix;
|
||||
context.ModelMatrix = Transform.MergeMatrix(context.ModelMatrix);
|
||||
|
||||
base.Draw(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
272
src/renderer/SM.Base/Scene/GenericScene.cs
Normal file
272
src/renderer/SM.Base/Scene/GenericScene.cs
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SM.Base.Utility;
|
||||
using SM.Base.Window;
|
||||
using SM.Base.Window.Contexts;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Scene
|
||||
{
|
||||
/// <summary>
|
||||
/// A generic scene, that imports functions for scene control.
|
||||
/// </summary>
|
||||
public abstract class GenericScene : IInitializable
|
||||
{
|
||||
private IBackgroundItem _background;
|
||||
private readonly Dictionary<Type, object> _extensions = new Dictionary<Type, object>();
|
||||
|
||||
private GenericItemCollection _hud;
|
||||
private GenericItemCollection _objectCollection;
|
||||
|
||||
/// <summary>
|
||||
/// A collection for cameras to switch easier to different cameras.
|
||||
/// </summary>
|
||||
public Dictionary<string, GenericCamera> Cameras = new Dictionary<string, GenericCamera>();
|
||||
|
||||
/// <summary>
|
||||
/// This contains the background.
|
||||
/// </summary>
|
||||
protected IBackgroundItem _Background
|
||||
{
|
||||
get => _background;
|
||||
set
|
||||
{
|
||||
value.Parent = this;
|
||||
_background = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Objects inside the scene.
|
||||
/// </summary>
|
||||
public GenericItemCollection Objects
|
||||
{
|
||||
get => _objectCollection;
|
||||
set
|
||||
{
|
||||
value.Parent = this;
|
||||
_objectCollection = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This defines the HUD objects.
|
||||
/// </summary>
|
||||
public GenericItemCollection HUD
|
||||
{
|
||||
get => _hud;
|
||||
set
|
||||
{
|
||||
value.Parent = this;
|
||||
_hud = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If true, shows a axis helper at (0,0,0)
|
||||
/// </summary>
|
||||
public bool ShowAxisHelper { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// The active camera, that is used if the context doesn't force the viewport camera.
|
||||
/// <para>If none set, it automaticly uses the viewport camera.</para>
|
||||
/// </summary>
|
||||
public GenericCamera Camera { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A camera to control the background.
|
||||
/// </summary>
|
||||
public GenericCamera BackgroundCamera { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A camera to control the HUD.
|
||||
/// </summary>
|
||||
public GenericCamera HUDCamera { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, the scene was already initialized.
|
||||
/// </summary>
|
||||
public bool IsInitialized { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual void Activate()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual void Initialization()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates this scene.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public virtual void Update(UpdateContext context)
|
||||
{
|
||||
_objectCollection?.Update(context);
|
||||
_hud?.Update(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes a fixed update for this scene.
|
||||
/// </summary>
|
||||
public virtual void FixedUpdate(FixedUpdateContext context)
|
||||
{
|
||||
_objectCollection?.FixedUpdate(context);
|
||||
_hud?.FixedUpdate(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws this scene.
|
||||
/// </summary>
|
||||
public virtual void Draw(DrawContext context)
|
||||
{
|
||||
DrawBackground(context);
|
||||
|
||||
DrawMainObjects(context);
|
||||
|
||||
DrawHUD(context);
|
||||
DrawDebug(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws only the background.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public virtual void DrawBackground(DrawContext context)
|
||||
{
|
||||
var backgroundDrawContext = context;
|
||||
backgroundDrawContext.SetCamera(BackgroundCamera);
|
||||
_Background?.Draw(backgroundDrawContext);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws only the main objects
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public virtual void DrawMainObjects(DrawContext context)
|
||||
{
|
||||
if (!context.Window.ForceViewportCamera && Camera != null) context.SetCamera(Camera);
|
||||
_objectCollection.Draw(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws only the HUD
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public virtual void DrawHUD(DrawContext context)
|
||||
{
|
||||
context.SetCamera(HUDCamera);
|
||||
_hud?.Draw(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw the debug informations.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
public virtual void DrawDebug(DrawContext context)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a extension to the scene.
|
||||
/// </summary>
|
||||
/// <param name="extension"></param>
|
||||
public virtual void SetExtension(object extension)
|
||||
{
|
||||
_extensions[extension.GetType()] = extension;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a extension with the type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public virtual T GetExtension<T>() where T : class
|
||||
{
|
||||
object ext = _extensions[typeof(T)];
|
||||
if (ext == null)
|
||||
{
|
||||
Log.Write(LogType.Warning,
|
||||
$"Tried to get the extension '{typeof(T).Name}', that doesn't exist in the scene.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return (T) ext;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is triggered when the scene gets deactivated.
|
||||
/// </summary>
|
||||
public virtual void Deactivate()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A generic scene that imports different functions.
|
||||
/// </summary>
|
||||
/// <typeparam name="TCamera">The type of cameras.</typeparam>
|
||||
/// <typeparam name="TCollection">The type for collections</typeparam>
|
||||
public abstract class GenericScene<TCamera, TCollection> : GenericScene
|
||||
where TCamera : GenericCamera, new()
|
||||
where TCollection : GenericItemCollection, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Objects inside the scene, but as the collection type.
|
||||
/// </summary>
|
||||
public new TCollection Objects
|
||||
{
|
||||
get => (TCollection) base.Objects;
|
||||
set => base.Objects = value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// HUD-Objects inside the scene, but as the collection type.
|
||||
/// </summary>
|
||||
public new TCollection HUD
|
||||
{
|
||||
get
|
||||
{
|
||||
base.HUD ??= new TCollection();
|
||||
return (TCollection) base.HUD;
|
||||
}
|
||||
set => base.HUD = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The active camera, that is used if the context doesn't force the viewport camera.
|
||||
/// <para>If none set, it automaticly uses the viewport camera.</para>
|
||||
/// </summary>
|
||||
public new TCamera Camera
|
||||
{
|
||||
get => (TCamera) base.Camera;
|
||||
set => base.Camera = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A camera to control the HUD.
|
||||
/// </summary>
|
||||
public new TCamera HUDCamera
|
||||
{
|
||||
get => (TCamera) base.HUDCamera;
|
||||
set => base.HUDCamera = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A camera to control the background.
|
||||
/// </summary>
|
||||
public new TCamera BackgroundCamera
|
||||
{
|
||||
get => (TCamera) base.BackgroundCamera;
|
||||
set => base.BackgroundCamera = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
9
src/renderer/SM.Base/Scene/IBackgroundItem.cs
Normal file
9
src/renderer/SM.Base/Scene/IBackgroundItem.cs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
namespace SM.Base.Scene
|
||||
{
|
||||
/// <summary>
|
||||
/// A iteration of <see cref="IShowItem" /> to reduce clutter.
|
||||
/// </summary>
|
||||
public interface IBackgroundItem : IShowItem
|
||||
{
|
||||
}
|
||||
}
|
||||
10
src/renderer/SM.Base/Scene/ICollectionItem.cs
Normal file
10
src/renderer/SM.Base/Scene/ICollectionItem.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
namespace SM.Base.Scene
|
||||
{
|
||||
/// <summary>
|
||||
/// Dummy interface for adding items.
|
||||
/// </summary>
|
||||
public interface ICollectionItem
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
22
src/renderer/SM.Base/Scene/IFixedScriptable.cs
Normal file
22
src/renderer/SM.Base/Scene/IFixedScriptable.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
using SM.Base.Window.Contexts;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SM.Base.Scene
|
||||
{
|
||||
/// <summary>
|
||||
/// This interface allows for a object to implerment a fixed update.
|
||||
/// </summary>
|
||||
public interface IFixedScriptable : ICollectionItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes a fixed update.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
void FixedUpdate(FixedUpdateContext context);
|
||||
|
||||
}
|
||||
}
|
||||
29
src/renderer/SM.Base/Scene/IScriptable.cs
Normal file
29
src/renderer/SM.Base/Scene/IScriptable.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#region usings
|
||||
|
||||
using SM.Base.Window;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Scene
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a object as script.
|
||||
/// </summary>
|
||||
public interface IScriptable : ICollectionItem
|
||||
{
|
||||
/// <summary>
|
||||
/// If not active, ItemCollections will ignore them.
|
||||
/// </summary>
|
||||
bool Active { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If not active, ItemCollections will ignore them.
|
||||
/// </summary>
|
||||
bool UpdateActive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Updates the object.
|
||||
/// </summary>
|
||||
void Update(UpdateContext context);
|
||||
}
|
||||
}
|
||||
26
src/renderer/SM.Base/Scene/IShowCollection.cs
Normal file
26
src/renderer/SM.Base/Scene/IShowCollection.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#region usings
|
||||
|
||||
using System.Collections.Generic;
|
||||
using SM.Base.Window;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Scene
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds functions, that is required for a collection.
|
||||
/// </summary>
|
||||
public interface IShowCollection
|
||||
{
|
||||
/// <summary>
|
||||
/// The object collection.
|
||||
/// </summary>
|
||||
List<IShowItem> Objects { get; }
|
||||
|
||||
/// <summary>
|
||||
/// This draws the objects in the <see cref="Objects" /> list.
|
||||
/// </summary>
|
||||
/// <param name="context">The context how the objects need to be drawn.</param>
|
||||
void Draw(DrawContext context);
|
||||
}
|
||||
}
|
||||
90
src/renderer/SM.Base/Scene/IShowItem.cs
Normal file
90
src/renderer/SM.Base/Scene/IShowItem.cs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
#region usings
|
||||
|
||||
using System.Collections.Generic;
|
||||
using SM.Base.Drawing;
|
||||
using SM.Base.Window;
|
||||
using SM.OGL.Mesh;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Scene
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds requirements to object, to be properly used as a update and/or draw item.
|
||||
/// </summary>
|
||||
public interface IShowItem : ICollectionItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Parent of the object.
|
||||
/// </summary>
|
||||
object Parent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Contains the name for the object.
|
||||
/// </summary>
|
||||
string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Contains specific flags for the object.
|
||||
/// </summary>
|
||||
ICollection<string> Flags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true it will ignore the object.
|
||||
/// </summary>
|
||||
bool Active { get; set; }
|
||||
/// <summary>
|
||||
/// Íf true it will ignore the object when rendering.
|
||||
/// </summary>
|
||||
bool RenderActive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Tells the object to draw its object.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
void Draw(DrawContext context);
|
||||
|
||||
/// <summary>
|
||||
/// Action, that is called, when the object was added to a GenericItemCollection.
|
||||
/// </summary>
|
||||
void OnAdded(object sender);
|
||||
|
||||
/// <summary>
|
||||
/// Action, that is called, when the object was removed from a GenericItemCollection.
|
||||
/// </summary>
|
||||
void OnRemoved(object sender);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement transformation.
|
||||
/// </summary>
|
||||
/// <typeparam name="TTransform"></typeparam>
|
||||
public interface ITransformItem<TTransform>
|
||||
where TTransform : GenericTransformation
|
||||
{
|
||||
/// <summary>
|
||||
/// Controls the transformation of the object.
|
||||
/// </summary>
|
||||
TTransform Transform { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merges <see cref="IShowItem"/> and <see cref="ITransformItem{TTransform}"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TTransform"></typeparam>
|
||||
public interface IShowTransformItem<TTransform> : IShowItem, ITransformItem<TTransform>
|
||||
where TTransform : GenericTransformation
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface to implement models in the object.
|
||||
/// </summary>
|
||||
public interface IModelItem
|
||||
{
|
||||
/// <summary>
|
||||
/// The mesh the rendering should use.
|
||||
/// </summary>
|
||||
GenericMesh Mesh { get; set; }
|
||||
}
|
||||
}
|
||||
19
src/renderer/SM.Base/Shaders/Extensions/ExtensionManager.cs
Normal file
19
src/renderer/SM.Base/Shaders/Extensions/ExtensionManager.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#region usings
|
||||
|
||||
using SM.OGL.Shaders;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Shaders.Extensions
|
||||
{
|
||||
internal class ExtensionManager
|
||||
{
|
||||
internal static void InitExtensions()
|
||||
{
|
||||
ShaderExtensions.AddAssemblyExtensions("SM_base", "SM.Base.Shaders.Extensions");
|
||||
|
||||
ShaderExtensions.Extensions["SM_base_vertex_basic"].StringOverrides["instanceMax"] =
|
||||
SMRenderer.MaxInstances.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
71
src/renderer/SM.Base/Shaders/Extensions/fragment/noise.glsl
Normal file
71
src/renderer/SM.Base/Shaders/Extensions/fragment/noise.glsl
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#version 330
|
||||
|
||||
// Permute
|
||||
vec3 permute(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); }
|
||||
vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);}
|
||||
|
||||
// Classic Perlin 2D Noise
|
||||
// by Stefan Gustavson
|
||||
vec2 fade(vec2 t) {return t*t*t*(t*(t*6.0-15.0)+10.0);}
|
||||
|
||||
float ClassicPerlinNoise(vec2 P){
|
||||
vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0);
|
||||
vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0);
|
||||
Pi = mod(Pi, 289.0); // To avoid truncation effects in permutation
|
||||
vec4 ix = Pi.xzxz;
|
||||
vec4 iy = Pi.yyww;
|
||||
vec4 fx = Pf.xzxz;
|
||||
vec4 fy = Pf.yyww;
|
||||
vec4 i = permute(permute(ix) + iy);
|
||||
vec4 gx = 2.0 * fract(i * 0.0243902439) - 1.0; // 1/41 = 0.024...
|
||||
vec4 gy = abs(gx) - 0.5;
|
||||
vec4 tx = floor(gx + 0.5);
|
||||
gx = gx - tx;
|
||||
vec2 g00 = vec2(gx.x,gy.x);
|
||||
vec2 g10 = vec2(gx.y,gy.y);
|
||||
vec2 g01 = vec2(gx.z,gy.z);
|
||||
vec2 g11 = vec2(gx.w,gy.w);
|
||||
vec4 norm = 1.79284291400159 - 0.85373472095314 *
|
||||
vec4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11));
|
||||
g00 *= norm.x;
|
||||
g01 *= norm.y;
|
||||
g10 *= norm.z;
|
||||
g11 *= norm.w;
|
||||
float n00 = dot(g00, vec2(fx.x, fy.x));
|
||||
float n10 = dot(g10, vec2(fx.y, fy.y));
|
||||
float n01 = dot(g01, vec2(fx.z, fy.z));
|
||||
float n11 = dot(g11, vec2(fx.w, fy.w));
|
||||
vec2 fade_xy = fade(Pf.xy);
|
||||
vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x);
|
||||
float n_xy = mix(n_x.x, n_x.y, fade_xy.y);
|
||||
return 2.3 * n_xy;
|
||||
}
|
||||
|
||||
// Simplex 2D noise
|
||||
|
||||
float SimplexNoise(vec2 v){
|
||||
const vec4 C = vec4(0.211324865405187, 0.366025403784439,
|
||||
-0.577350269189626, 0.024390243902439);
|
||||
vec2 i = floor(v + dot(v, C.yy) );
|
||||
vec2 x0 = v - i + dot(i, C.xx);
|
||||
vec2 i1;
|
||||
i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
|
||||
vec4 x12 = x0.xyxy + C.xxzz;
|
||||
x12.xy -= i1;
|
||||
i = mod(i, 289.0);
|
||||
vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ))
|
||||
+ i.x + vec3(0.0, i1.x, 1.0 ));
|
||||
vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy),
|
||||
dot(x12.zw,x12.zw)), 0.0);
|
||||
m = m*m ;
|
||||
m = m*m ;
|
||||
vec3 x = 2.0 * fract(p * C.www) - 1.0;
|
||||
vec3 h = abs(x) - 0.5;
|
||||
vec3 ox = floor(x + 0.5);
|
||||
vec3 a0 = x - ox;
|
||||
m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
|
||||
vec3 g;
|
||||
g.x = a0.x * x0.x + h.x * x0.y;
|
||||
g.yz = a0.yz * x12.xz + h.yz * x12.yw;
|
||||
return 130.0 * dot(m, g);
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#version 330
|
||||
|
||||
uniform float Gamma;
|
||||
|
||||
vec4 texture2DGamma(sampler2D s, vec2 P) {
|
||||
vec4 tex = texture2D(s, P);
|
||||
return vec4(pow(tex.rgb, vec3(Gamma)), tex.a);
|
||||
}
|
||||
35
src/renderer/SM.Base/Shaders/Extensions/vertex/basic.vert
Normal file
35
src/renderer/SM.Base/Shaders/Extensions/vertex/basic.vert
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#version 330
|
||||
#define maxInstances //!instanceMax
|
||||
|
||||
struct Instance {
|
||||
mat4 ModelMatrix;
|
||||
vec2 TextureOffset;
|
||||
vec2 TextureScale;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec3 aPos;
|
||||
layout(location = 1) in vec2 aTex;
|
||||
layout(location = 3) in vec4 aColor;
|
||||
|
||||
uniform mat4 MVP;
|
||||
uniform Instance[maxInstances] Instances;
|
||||
uniform bool HasVColor;
|
||||
|
||||
out vec2 vTexture;
|
||||
out vec4 vColor;
|
||||
out vec3 FragPos;
|
||||
|
||||
void ApplyTexModifier() {
|
||||
vTexture = aTex * Instances[gl_InstanceID].TextureScale + Instances[gl_InstanceID].TextureOffset;
|
||||
}
|
||||
|
||||
void CheckVertexColor() {
|
||||
if (HasVColor) vColor = aColor;
|
||||
else vColor = vec4(1);
|
||||
}
|
||||
|
||||
void ApplyModelTransformation() {
|
||||
gl_Position = MVP * Instances[gl_InstanceID].ModelMatrix * vec4(aPos, 1);
|
||||
|
||||
FragPos = vec3(vec4(aPos, 1));
|
||||
}
|
||||
78
src/renderer/SM.Base/Shaders/MaterialShader.cs
Normal file
78
src/renderer/SM.Base/Shaders/MaterialShader.cs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#region usings
|
||||
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using SM.Base.Window;
|
||||
using SM.OGL.Mesh;
|
||||
using SM.OGL.Shaders;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Shaders
|
||||
{
|
||||
/// <summary>
|
||||
/// A general class to work with material shaders properly.
|
||||
/// </summary>
|
||||
public abstract class MaterialShader : GenericShader
|
||||
{
|
||||
static bool _canLineWidth = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected MaterialShader(string combinedData) : base(combinedData)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected MaterialShader(string vertex, string fragment) : base(vertex, fragment)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected MaterialShader(ShaderFileCollection shaderFileFiles) : base(shaderFileFiles)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prepares the context for the drawing.
|
||||
/// </summary>
|
||||
/// <param name="context">The context</param>
|
||||
public virtual void Draw(DrawContext context)
|
||||
{
|
||||
context.Shader.Activate();
|
||||
|
||||
context.Mesh.Activate();
|
||||
|
||||
if (_canLineWidth)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (context.Material.ShaderArguments.ContainsKey("LineWidth"))
|
||||
GL.LineWidth((float)context.Material.ShaderArguments["LineWidth"]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
_canLineWidth = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (context.Material.Blending)
|
||||
{
|
||||
GL.Enable(EnableCap.Blend);
|
||||
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL.Disable(EnableCap.Blend);
|
||||
}
|
||||
|
||||
DrawProcess(context);
|
||||
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws the context.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
protected abstract void DrawProcess(DrawContext context);
|
||||
}
|
||||
}
|
||||
147
src/renderer/SM.Base/Shaders/SimpleShader.cs
Normal file
147
src/renderer/SM.Base/Shaders/SimpleShader.cs
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SM.Base.Utility;
|
||||
using SM.Base.Window;
|
||||
using SM.OGL.Shaders;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Shaders
|
||||
{
|
||||
/// <summary>
|
||||
/// Allows for simple creation of shaders.
|
||||
/// </summary>
|
||||
public class SimpleShader : MaterialShader
|
||||
{
|
||||
/// <summary>
|
||||
/// Vertex files that are stored in this dictionary can be used as vertex presets.
|
||||
/// </summary>
|
||||
public static Dictionary<string, Tuple<ShaderFile, Action<UniformCollection, DrawContext>>> VertexFiles =
|
||||
new Dictionary<string, Tuple<ShaderFile, Action<UniformCollection, DrawContext>>>();
|
||||
|
||||
private readonly string _vertexPreset;
|
||||
|
||||
/// <summary>
|
||||
/// Stores the function that sets the uniforms.
|
||||
/// </summary>
|
||||
public Action<UniformCollection, DrawContext> SetUniform;
|
||||
|
||||
static SimpleShader()
|
||||
{
|
||||
VertexFiles.Add("basic", new Tuple<ShaderFile, Action<UniformCollection, DrawContext>>(
|
||||
new ShaderFile(
|
||||
AssemblyUtility.ReadAssemblyFile("SM.Base.Shaders.SimpleShaderPresets.basic_vertex.glsl"))
|
||||
{
|
||||
StringOverrides = {["extension"] = "0"}
|
||||
},
|
||||
BasicSetUniforms
|
||||
));
|
||||
VertexFiles.Add("E_basic", new Tuple<ShaderFile, Action<UniformCollection, DrawContext>>(
|
||||
new ShaderFile(
|
||||
AssemblyUtility.ReadAssemblyFile("SM.Base.Shaders.SimpleShaderPresets.basic_vertex.glsl"))
|
||||
{
|
||||
StringOverrides = {["extension"] = "1"}
|
||||
},
|
||||
BasicSetUniforms
|
||||
));
|
||||
|
||||
VertexFiles.Add("instanced", new Tuple<ShaderFile, Action<UniformCollection, DrawContext>>(
|
||||
new ShaderFile(
|
||||
AssemblyUtility.ReadAssemblyFile("SM.Base.Shaders.SimpleShaderPresets.instanced_vertex.glsl"))
|
||||
{
|
||||
StringOverrides = {["instanceMax"] = SMRenderer.MaxInstances.ToString(), ["extension"] = "0"}
|
||||
},
|
||||
InstancedSetUniforms
|
||||
));
|
||||
VertexFiles.Add("E_instanced", new Tuple<ShaderFile, Action<UniformCollection, DrawContext>>(
|
||||
new ShaderFile(
|
||||
AssemblyUtility.ReadAssemblyFile("SM.Base.Shaders.SimpleShaderPresets.instanced_vertex.glsl"))
|
||||
{
|
||||
StringOverrides = {["instanceMax"] = SMRenderer.MaxInstances.ToString(), ["extension"] = "0"}
|
||||
},
|
||||
InstancedSetUniforms
|
||||
));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a simple shader.
|
||||
/// </summary>
|
||||
/// <param name="vertexPreset">The vertex preset.</param>
|
||||
/// <param name="fragment">The fragment shader</param>
|
||||
/// <param name="setUniform">The uniform function.</param>
|
||||
public SimpleShader(string vertexPreset, string fragment, Action<UniformCollection, DrawContext> setUniform) :
|
||||
base(new ShaderFileCollection(VertexFiles[vertexPreset].Item1, new ShaderFile(fragment)))
|
||||
{
|
||||
_vertexPreset = vertexPreset;
|
||||
SetUniform = setUniform;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a simple shader with a extension.
|
||||
/// </summary>
|
||||
/// <param name="vertexPreset">The vertex preset.</param>
|
||||
/// <param name="vertexExtension">The vertex extension shader</param>
|
||||
/// <param name="fragment">The fragment shader</param>
|
||||
/// <param name="setUniform">The uniform function.</param>
|
||||
public SimpleShader(string vertexPreset, string vertexExtension, string fragment,
|
||||
Action<UniformCollection, DrawContext> setUniform) : base(new ShaderFileCollection(
|
||||
new[] {VertexFiles["E_" + vertexPreset].Item1, new ShaderFile(vertexExtension)},
|
||||
new[] {new ShaderFile(fragment)}))
|
||||
{
|
||||
_vertexPreset = vertexPreset;
|
||||
SetUniform = setUniform;
|
||||
}
|
||||
|
||||
private static void BasicSetUniforms(UniformCollection uniforms, DrawContext context)
|
||||
{
|
||||
// Vertex Uniforms
|
||||
uniforms["MVP"]
|
||||
.SetMatrix4(context.Instances[0].ModelMatrix * context.ModelMatrix * context.View * context.World);
|
||||
uniforms["MasterTextureMatrix"].SetMatrix3(context.Instances[0].TextureMatrix * context.TextureMatrix);
|
||||
uniforms["HasVColor"]
|
||||
.SetUniform1(context.Mesh.Attributes.Has("color"));
|
||||
|
||||
DrawObject(context.ForcedType.GetValueOrDefault(context.Mesh.PrimitiveType), context.Mesh);
|
||||
}
|
||||
|
||||
private static void InstancedSetUniforms(UniformCollection uniforms, DrawContext context)
|
||||
{
|
||||
uniforms["MVP"].SetMatrix4(context.ModelMatrix * context.View * context.World);
|
||||
uniforms["MasterTextureMatrix"].SetMatrix3(context.TextureMatrix);
|
||||
uniforms["HasVColor"]
|
||||
.SetUniform1(context.Mesh.Attributes.Has("color"));
|
||||
|
||||
UniformArray instances = uniforms.GetArray("Instances");
|
||||
|
||||
int shaderInstanceI = 0;
|
||||
for (int i = 0; i < context.Instances.Count; i++)
|
||||
{
|
||||
if (shaderInstanceI > instances.Length - 1)
|
||||
{
|
||||
DrawObject(context.Mesh, instances.Length);
|
||||
shaderInstanceI = 0;
|
||||
}
|
||||
|
||||
var shaderInstance = instances[shaderInstanceI];
|
||||
var instance = context.Instances[i];
|
||||
if (instance == null) continue;
|
||||
shaderInstance["ModelMatrix"].SetMatrix4(instance.ModelMatrix);
|
||||
shaderInstance["TextureMatrix"].SetMatrix3(instance.TextureMatrix);
|
||||
|
||||
shaderInstanceI++;
|
||||
}
|
||||
|
||||
DrawObject(context.ForcedType.GetValueOrDefault(context.Mesh.PrimitiveType), context.Mesh, shaderInstanceI);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void DrawProcess(DrawContext context)
|
||||
{
|
||||
SetUniform?.Invoke(Uniforms, context);
|
||||
|
||||
VertexFiles[_vertexPreset].Item2(Uniforms, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#version 330
|
||||
#define SM_SIMPLE_EXTENSION //!extension
|
||||
|
||||
layout(location = 0) in vec3 a_Position;
|
||||
layout(location = 1) in vec2 a_Texture;
|
||||
layout(location = 3) in vec4 a_Color;
|
||||
|
||||
uniform bool HasVColor;
|
||||
uniform mat4 MVP;
|
||||
uniform mat3 MasterTextureMatrix;
|
||||
|
||||
out vec3 v_VertexPosition;
|
||||
out vec2 v_TexCoords;
|
||||
out vec4 v_Color;
|
||||
|
||||
#if (SM_SIMPLE_EXTENSION == 1)
|
||||
void v_Extension();
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
v_Color = vec4(1);
|
||||
if (HasVColor) v_Color = a_Color;
|
||||
|
||||
v_TexCoords = vec2(MasterTextureMatrix * vec3(a_Texture, 1));
|
||||
|
||||
v_VertexPosition = a_Position;
|
||||
gl_Position = MVP * vec4(a_Position, 1);
|
||||
|
||||
#if (SM_SIMPLE_EXTENSION == 1)
|
||||
v_Extension();
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
#version 330
|
||||
#define maxInstances //!instanceMax
|
||||
#define SM_SIMPLE_EXTENSION //!extension
|
||||
|
||||
struct Instance {
|
||||
mat4 ModelMatrix;
|
||||
mat3 TextureMatrix;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec3 a_Position;
|
||||
layout(location = 1) in vec2 a_Texture;
|
||||
layout(location = 3) in vec4 a_Color;
|
||||
|
||||
uniform mat4 MVP;
|
||||
uniform mat3 MasterTextureMatrix;
|
||||
uniform Instance[maxInstances] Instances;
|
||||
uniform bool HasVColor;
|
||||
|
||||
out vec3 v_VertexPosition;
|
||||
out vec2 v_TexCoords;
|
||||
out vec4 v_Color;
|
||||
|
||||
#if (SM_SIMPLE_EXTENSION == 1)
|
||||
void v_Extension();
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
v_Color = vec4(1);
|
||||
if (HasVColor) v_Color = a_Color;
|
||||
|
||||
v_TexCoords = vec2(MasterTextureMatrix * Instances[gl_InstanceID].TextureMatrix * vec3(a_Texture, 1));
|
||||
|
||||
v_VertexPosition = a_Position;
|
||||
gl_Position = MVP * Instances[gl_InstanceID].ModelMatrix * vec4(a_Position, 1);
|
||||
|
||||
#if (SM_SIMPLE_EXTENSION == 1)
|
||||
v_Extension();
|
||||
#endif
|
||||
}
|
||||
170
src/renderer/SM.Base/Textures/Texture.cs
Normal file
170
src/renderer/SM.Base/Textures/Texture.cs
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
#region usings
|
||||
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using SM.OGL.Texture;
|
||||
using PixelFormat = System.Drawing.Imaging.PixelFormat;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Textures
|
||||
{
|
||||
/// <summary>
|
||||
/// Texture that can be drawn to an object.
|
||||
/// </summary>
|
||||
public class Texture : TextureBase
|
||||
{
|
||||
static HintMode _hintMode;
|
||||
/// <summary>
|
||||
/// Defines the texture quailty.
|
||||
/// <para>It won't change already compiled textures!</para>
|
||||
/// </summary>
|
||||
public static HintMode TextureQuality
|
||||
{
|
||||
get => _hintMode;
|
||||
set
|
||||
{
|
||||
_hintMode = value;
|
||||
GL.Hint(HintTarget.TextureCompressionHint, value);
|
||||
}
|
||||
}
|
||||
|
||||
private int? _height;
|
||||
private int? _width;
|
||||
|
||||
/// <summary>
|
||||
/// The unpack alignment for this texture.
|
||||
/// </summary>
|
||||
public int UnpackAlignment = 4;
|
||||
|
||||
/// <summary>
|
||||
/// Decides if the bitmap will automatically dispose itself.
|
||||
/// </summary>
|
||||
public bool AutoDispose = false;
|
||||
|
||||
/// <summary>
|
||||
/// The texture as bitmap.
|
||||
/// </summary>
|
||||
public Bitmap Map;
|
||||
|
||||
/// <summary>
|
||||
/// Empty constructor
|
||||
/// </summary>
|
||||
protected Texture()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a texture with only the map.
|
||||
/// <para>Sets the filter to Linear and WrapMode to Repeat.</para>
|
||||
/// </summary>
|
||||
/// <param name="map">The map</param>
|
||||
public Texture(Bitmap map) : this(map, TextureMinFilter.Linear, TextureWrapMode.Repeat)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the texture.
|
||||
/// </summary>
|
||||
/// <param name="map">The texture map</param>
|
||||
/// <param name="filter">The filter</param>
|
||||
/// <param name="wrapMode">The wrap mode</param>
|
||||
public Texture(Bitmap map, TextureMinFilter filter, TextureWrapMode wrapMode)
|
||||
{
|
||||
Map = map;
|
||||
|
||||
Aspect = (float) map.Width / map.Height;
|
||||
|
||||
Filter = filter;
|
||||
WrapMode = wrapMode;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int Width
|
||||
{
|
||||
get => _width ?? Map.Width;
|
||||
protected set => _width = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int Height
|
||||
{
|
||||
get => _height ?? Map.Height;
|
||||
protected set => _height = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aspect ratio of Width and Height of the texture
|
||||
/// </summary>
|
||||
public float Aspect { get; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Compile()
|
||||
{
|
||||
base.Compile();
|
||||
|
||||
_id = GenerateTexture(Map, Filter, WrapMode, AutoDispose, UnpackAlignment);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
|
||||
GL.DeleteTexture(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a OpenGL-texture.
|
||||
/// </summary>
|
||||
/// <param name="map">The texture as bitmap</param>
|
||||
/// <param name="filter">The filter</param>
|
||||
/// <param name="wrapMode">The wrap mode</param>
|
||||
/// <param name="dispose">Auto dispose of the bitmap? Default: false</param>
|
||||
/// <param name="unpackAlignment">The unpack alignment for this texture.</param>
|
||||
/// <returns></returns>
|
||||
public static int GenerateTexture(Bitmap map, TextureMinFilter filter, TextureWrapMode wrapMode,
|
||||
bool dispose = false, int unpackAlignment = 4)
|
||||
{
|
||||
var id = GL.GenTexture();
|
||||
GL.BindTexture(TextureTarget.Texture2D, id);
|
||||
|
||||
GL.PixelStore(PixelStoreParameter.UnpackAlignment, unpackAlignment);
|
||||
|
||||
var data = map.LockBits(new Rectangle(0, 0, map.Width, map.Height), ImageLockMode.ReadOnly,
|
||||
map.PixelFormat);
|
||||
|
||||
var transparenz = map.PixelFormat == PixelFormat.Format32bppArgb;
|
||||
|
||||
GL.TexImage2D(TextureTarget.Texture2D, 0,
|
||||
transparenz ? PixelInternalFormat.CompressedRgba : PixelInternalFormat.CompressedRgb,
|
||||
data.Width, data.Height, 0,
|
||||
transparenz ? OpenTK.Graphics.OpenGL4.PixelFormat.Bgra : OpenTK.Graphics.OpenGL4.PixelFormat.Bgr,
|
||||
PixelType.UnsignedByte, data.Scan0);
|
||||
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) filter);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) filter);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int) wrapMode);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) wrapMode);
|
||||
|
||||
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
|
||||
|
||||
GL.BindTexture(TextureTarget.Texture2D, 0);
|
||||
map.UnlockBits(data);
|
||||
|
||||
if (dispose) map.Dispose();
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a bitmap to a texture.
|
||||
/// </summary>
|
||||
public static implicit operator Texture(Bitmap map)
|
||||
{
|
||||
return new Texture(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
32
src/renderer/SM.Base/Time/Interval.cs
Normal file
32
src/renderer/SM.Base/Time/Interval.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using SM.Base.Window;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Time
|
||||
{
|
||||
/// <summary>
|
||||
/// Performs intervals.
|
||||
/// </summary>
|
||||
public class Interval : Timer
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Interval(float seconds) : base(seconds)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Interval(TimeSpan timeSpan) : base(timeSpan)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Stopping(UpdateContext context)
|
||||
{
|
||||
TriggerEndAction(context);
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
128
src/renderer/SM.Base/Time/Stopwatch.cs
Normal file
128
src/renderer/SM.Base/Time/Stopwatch.cs
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SM.Base.Window;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Time
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a stopwatch.
|
||||
/// </summary>
|
||||
public class Stopwatch
|
||||
{
|
||||
private static readonly List<Stopwatch> _activeStopwatches = new List<Stopwatch>();
|
||||
private bool _paused;
|
||||
|
||||
/// <summary>
|
||||
/// If true, the stopwatch was started.
|
||||
/// <para>This doesn't changed when paused.</para>
|
||||
/// </summary>
|
||||
public bool Active { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets/Sets if the stopwatch is paused.
|
||||
/// </summary>
|
||||
public bool Paused
|
||||
{
|
||||
get => _paused;
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
Pause();
|
||||
else
|
||||
Resume();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If true, the stopwatch is active and not paused... (who would have guessed...)
|
||||
/// </summary>
|
||||
public bool Running => Active && !Paused;
|
||||
|
||||
/// <summary>
|
||||
/// Contains how much time already has passed. (in seconds)
|
||||
/// </summary>
|
||||
public float Elapsed { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Contains the TimeSpan of how much time already passed.
|
||||
/// </summary>
|
||||
public TimeSpan ElapsedSpan { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// This event gets triggered every tick.
|
||||
/// </summary>
|
||||
public event Action<Stopwatch, UpdateContext> Tick;
|
||||
|
||||
/// <summary>
|
||||
/// Starts the stopwatch.
|
||||
/// </summary>
|
||||
public virtual void Start()
|
||||
{
|
||||
if (Active) return;
|
||||
|
||||
_activeStopwatches.Add(this);
|
||||
Active = true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Performs a tick.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
private protected virtual void Ticking(UpdateContext context)
|
||||
{
|
||||
Elapsed += context.Deltatime;
|
||||
ElapsedSpan = TimeSpan.FromSeconds(Elapsed);
|
||||
|
||||
Tick?.Invoke(this, context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resumes the timer.
|
||||
/// </summary>
|
||||
protected virtual void Resume()
|
||||
{
|
||||
_paused = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pauses the timer.
|
||||
/// </summary>
|
||||
protected virtual void Pause()
|
||||
{
|
||||
_paused = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the stopwatch.
|
||||
/// </summary>
|
||||
public virtual void Stop()
|
||||
{
|
||||
if (!Active) return;
|
||||
|
||||
Active = false;
|
||||
_activeStopwatches.Remove(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the stopwatch.
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
Elapsed = 0;
|
||||
}
|
||||
|
||||
internal static void PerformTicks(UpdateContext context)
|
||||
{
|
||||
for (var i = 0; i < _activeStopwatches.Count; i++)
|
||||
{
|
||||
if (_activeStopwatches[i].Paused) continue;
|
||||
_activeStopwatches[i].Ticking(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
81
src/renderer/SM.Base/Time/Timer.cs
Normal file
81
src/renderer/SM.Base/Time/Timer.cs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using SM.Base.Window;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Time
|
||||
{
|
||||
/// <summary>
|
||||
/// Timer-System
|
||||
/// </summary>
|
||||
public class Timer : Stopwatch
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a timer with specified seconds.
|
||||
/// </summary>
|
||||
/// <param name="seconds"></param>
|
||||
public Timer(float seconds)
|
||||
{
|
||||
Target = seconds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a timer with a time span.
|
||||
/// </summary>
|
||||
/// <param name="timeSpan"></param>
|
||||
public Timer(TimeSpan timeSpan)
|
||||
{
|
||||
Target = (float) timeSpan.TotalSeconds;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The target time in seconds.
|
||||
/// </summary>
|
||||
public float Target { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The already elapsed time but normalized to the target.
|
||||
/// </summary>
|
||||
public float ElapsedNormalized { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The event, that is triggered when the timer stops.
|
||||
/// </summary>
|
||||
public event Action<Timer, UpdateContext> End;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Start()
|
||||
{
|
||||
base.Start();
|
||||
Reset();
|
||||
}
|
||||
|
||||
private protected override void Ticking(UpdateContext context)
|
||||
{
|
||||
base.Ticking(context);
|
||||
|
||||
ElapsedNormalized = Math.Min(Elapsed / Target, 1);
|
||||
if (ElapsedNormalized >= 1) Stopping(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs, when the timer tries to stop.
|
||||
/// </summary>
|
||||
protected virtual void Stopping(UpdateContext context)
|
||||
{
|
||||
TriggerEndAction(context);
|
||||
Stop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will trigger <see cref="End" />
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
protected void TriggerEndAction(UpdateContext context)
|
||||
{
|
||||
End?.Invoke(this, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
109
src/renderer/SM.Base/Types/CVector1.cs
Normal file
109
src/renderer/SM.Base/Types/CVector1.cs
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using OpenTK;
|
||||
using SM.Base.Animation;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A One-dimensional Vector (also known as <see cref="float" />), in a class.
|
||||
/// </summary>
|
||||
public class CVector1 : CVectorBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a class vector
|
||||
/// </summary>
|
||||
/// <param name="x">X-Component</param>
|
||||
public CVector1(float x)
|
||||
{
|
||||
X = x;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// X - Component
|
||||
/// </summary>
|
||||
public float X { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Interpolates the motion to the target.
|
||||
/// </summary>
|
||||
/// <param name="duration">How long the interpolation should take.</param>
|
||||
/// <param name="to">The value it should interpolate.</param>
|
||||
/// <param name="interpolationCurve">The curve how he interpolates. Preset values can be found under <see cref="AnimationCurves"/>. Default: <see cref="AnimationCurves.Linear"/></param>
|
||||
/// <returns>A handle to control the interpolation process.</returns>
|
||||
public InterpolationProcess Interpolate(TimeSpan duration, float to, BezierCurve? interpolationCurve = null)
|
||||
{
|
||||
InterpolationProcess process = new InterpolationProcess(this, duration, ConvertToVector4(), new Vector4(to, 0, 0, 0), interpolationCurve.GetValueOrDefault(AnimationCurves.Linear));
|
||||
process.Start();
|
||||
|
||||
return process;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the X-Component.
|
||||
/// </summary>
|
||||
public virtual void Set(float uniform, bool triggerChanged = true)
|
||||
{
|
||||
X = uniform;
|
||||
if (triggerChanged) TriggerChanged();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void SetRaw(params float[] parameters)
|
||||
{
|
||||
X = parameters[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the value to the components.
|
||||
/// </summary>
|
||||
public virtual void Add(float uniform, bool triggerChanged = true)
|
||||
{
|
||||
X += uniform;
|
||||
if (triggerChanged) TriggerChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Conversion from <see cref="float" /> to One-dimensional Vector.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override float GetLengthProcess()
|
||||
{
|
||||
return X * X;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes the vector.
|
||||
/// </summary>
|
||||
/// <param name="length"></param>
|
||||
protected override void NormalizationProcess(float length)
|
||||
{
|
||||
X *= length;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Vector4 ConvertToVector4()
|
||||
{
|
||||
return new Vector4(X, 0, 0, 0);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return X.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Conversion into <see cref="float" />
|
||||
/// </summary>
|
||||
public static implicit operator float(CVector1 vector1)
|
||||
{
|
||||
return vector1.X;
|
||||
}
|
||||
}
|
||||
}
|
||||
160
src/renderer/SM.Base/Types/CVector2.cs
Normal file
160
src/renderer/SM.Base/Types/CVector2.cs
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using OpenTK;
|
||||
using SM.Base.Animation;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A two-dimensional vector.
|
||||
/// </summary>
|
||||
public class CVector2 : CVector1
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a vector, where each component is the same value.
|
||||
/// </summary>
|
||||
/// <param name="uniform">The Value</param>
|
||||
public CVector2(float uniform) : base(uniform)
|
||||
{
|
||||
Y = uniform;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a vector
|
||||
/// </summary>
|
||||
public CVector2(float x, float y) : base(x)
|
||||
{
|
||||
Y = y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Y-component
|
||||
/// </summary>
|
||||
public float Y { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Interpolates the motion to the target.
|
||||
/// </summary>
|
||||
/// <param name="duration">How long the interpolation should take.</param>
|
||||
/// <param name="to">The value it should interpolate.</param>
|
||||
/// <param name="interpolationCurve">The curve how he interpolates.
|
||||
/// <para>When creating a curve, its recommended the Y-component is always between 0 -> 1. But it could make cool effects if not...</para>
|
||||
/// <para>Preset curves can be found under <see cref="AnimationCurves"/>.</para>
|
||||
/// <para>Default: <see cref="AnimationCurves.Linear"/></para>
|
||||
/// </param>
|
||||
/// <returns>A handle to control the interpolation process.</returns>
|
||||
public InterpolationProcess Interpolate(TimeSpan duration, Vector2 to, BezierCurve? interpolationCurve = null)
|
||||
{
|
||||
InterpolationProcess process = new InterpolationProcess(this, duration, ConvertToVector4(), new Vector4(to), interpolationCurve.GetValueOrDefault(AnimationCurves.Linear));
|
||||
process.Start();
|
||||
|
||||
return process;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return "{"+X+"; "+Y+"}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets each component to the same value
|
||||
/// </summary>
|
||||
public override void Set(float uniform, bool triggerChanged = true)
|
||||
{
|
||||
Y = uniform;
|
||||
base.Set(uniform, triggerChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets each component to the <see cref="Vector2" /> counter-part.
|
||||
/// </summary>
|
||||
public void Set(Vector2 vector, bool triggerChanged = true)
|
||||
{
|
||||
Set(vector.X, vector.Y, triggerChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the a own value to each component.
|
||||
/// </summary>
|
||||
public void Set(float x, float y, bool triggerChanged = true)
|
||||
{
|
||||
Y = y;
|
||||
base.Set(x, triggerChanged);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void SetRaw(params float[] parameters)
|
||||
{
|
||||
base.SetRaw(parameters);
|
||||
Y = parameters[1];
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Add(float uniform, bool triggerChanged = true)
|
||||
{
|
||||
Y += uniform;
|
||||
base.Add(uniform, triggerChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds <see cref="Vector2"/> to the CVector.
|
||||
/// </summary>
|
||||
/// <param name="vector"></param>
|
||||
/// <param name="triggerChanged">If false, the event Changed doesn't gets triggered </param>
|
||||
public void Add(Vector2 vector, bool triggerChanged = true)
|
||||
{
|
||||
Add(vector.X, vector.Y, triggerChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the values to the CVector.
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <param name="triggerChanged">If false, the event Changed doesn't gets triggered </param>
|
||||
public void Add(float x, float y, bool triggerChanged = true)
|
||||
{
|
||||
Y += y;
|
||||
base.Add(x, triggerChanged);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override float GetLengthProcess()
|
||||
{
|
||||
return base.GetLengthProcess() + Y * Y;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void NormalizationProcess(float length)
|
||||
{
|
||||
base.NormalizationProcess(length);
|
||||
Y *= length;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Vector4 ConvertToVector4()
|
||||
{
|
||||
return new Vector4(X,Y, 0, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts to <see cref="Vector2" />
|
||||
/// </summary>
|
||||
public static implicit operator Vector2(CVector2 vector2)
|
||||
{
|
||||
return new Vector2(vector2.X, vector2.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts from <see cref="Vector2" /> to <see cref="CVector2" />.
|
||||
/// </summary>
|
||||
public static implicit operator CVector2(Vector2 vector2)
|
||||
{
|
||||
return new CVector2(vector2.X, vector2.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
155
src/renderer/SM.Base/Types/CVector3.cs
Normal file
155
src/renderer/SM.Base/Types/CVector3.cs
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using OpenTK;
|
||||
using SM.Base.Animation;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A three-dimensional vector.
|
||||
/// </summary>
|
||||
public class CVector3 : CVector2
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a vector, where each component is the same value.
|
||||
/// </summary>
|
||||
/// <param name="uniform">The Value</param>
|
||||
public CVector3(float uniform) : base(uniform)
|
||||
{
|
||||
Z = uniform;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a vector
|
||||
/// </summary>
|
||||
public CVector3(float x, float y, float z) : base(x, y)
|
||||
{
|
||||
Z = z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Z-component
|
||||
/// </summary>
|
||||
public float Z { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Interpolates the motion to the target.
|
||||
/// </summary>
|
||||
/// <param name="duration">How long the interpolation should take.</param>
|
||||
/// <param name="to">The value it should interpolate.</param>
|
||||
/// <param name="interpolationCurve">The curve how he interpolates. Preset values can be found under <see cref="AnimationCurves"/>. Default: <see cref="AnimationCurves.Linear"/></param>
|
||||
/// <returns>A handle to control the interpolation process.</returns>
|
||||
public InterpolationProcess Interpolate(TimeSpan duration, Vector3 to, BezierCurve? interpolationCurve = null)
|
||||
{
|
||||
InterpolationProcess process = new InterpolationProcess(this, duration, ConvertToVector4(), new Vector4(to, 0), interpolationCurve.GetValueOrDefault(AnimationCurves.Linear));
|
||||
process.Start();
|
||||
|
||||
return process;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return "{" + X + "; " + Y + "; "+Z+"}";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Set(float uniform, bool triggerChanged = true)
|
||||
{
|
||||
Z = uniform;
|
||||
base.Set(uniform, triggerChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the a own value to each component.
|
||||
/// </summary>
|
||||
public void Set(float x, float y, float z, bool triggerChanged = true)
|
||||
{
|
||||
Z = z;
|
||||
base.Set(x, y, triggerChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets each component to the <see cref="Vector3" /> counter-part.
|
||||
/// </summary>
|
||||
public void Set(Vector3 vector, bool triggerChanged = true)
|
||||
{
|
||||
Set(vector.X, vector.Y, vector.Z, triggerChanged);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void SetRaw(params float[] parameters)
|
||||
{
|
||||
base.SetRaw(parameters);
|
||||
Z = parameters[2];
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Add(float uniform, bool triggerChanged = true)
|
||||
{
|
||||
Z += uniform;
|
||||
base.Add(uniform, triggerChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="Vector3"/> to the CVector.
|
||||
/// </summary>
|
||||
/// <param name="vector"></param>
|
||||
/// <param name="triggerChanged">If false, the event Changed doesn't gets triggered </param>
|
||||
public void Add(Vector3 vector, bool triggerChanged = true)
|
||||
{
|
||||
Add(vector.X, vector.Y, vector.Z, triggerChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the values to the CVector.
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <param name="z"></param>
|
||||
/// <param name="triggerChanged">If false, the event Changed doesn't gets triggered </param>
|
||||
public void Add(float x, float y, float z, bool triggerChanged = true)
|
||||
{
|
||||
Z += z;
|
||||
base.Add(x, y, triggerChanged);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override float GetLengthProcess()
|
||||
{
|
||||
return base.GetLengthProcess() + Z * Z;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void NormalizationProcess(float length)
|
||||
{
|
||||
base.NormalizationProcess(length);
|
||||
Z *= length;
|
||||
}
|
||||
/// <inheritdoc />
|
||||
protected override Vector4 ConvertToVector4()
|
||||
{
|
||||
return new Vector4(X, Y, Z, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts to <see cref="Vector3" />
|
||||
/// </summary>
|
||||
public static implicit operator Vector3(CVector3 vector)
|
||||
{
|
||||
return new Vector3(vector.X, vector.Y, vector.Z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts from <see cref="Vector3" /> to <see cref="CVector3" />.
|
||||
/// </summary>
|
||||
public static implicit operator CVector3(Vector3 vector)
|
||||
{
|
||||
return new CVector3(vector.X, vector.Y, vector.Z);
|
||||
}
|
||||
}
|
||||
}
|
||||
138
src/renderer/SM.Base/Types/CVector4.cs
Normal file
138
src/renderer/SM.Base/Types/CVector4.cs
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
using System;
|
||||
using OpenTK;
|
||||
using SM.Base.Animation;
|
||||
|
||||
namespace SM.Base.Types
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public class CVector4 : CVector3
|
||||
{
|
||||
/// <summary>
|
||||
/// The W-component.
|
||||
/// </summary>
|
||||
public float W { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public CVector4(float uniform) : base(uniform)
|
||||
{
|
||||
W = uniform;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public CVector4(float x, float y, float z, float w) : base(x, y, z)
|
||||
{
|
||||
W = w;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interpolates the motion to the target.
|
||||
/// </summary>
|
||||
/// <param name="duration">How long the interpolation should take.</param>
|
||||
/// <param name="to">The value it should interpolate.</param>
|
||||
/// <param name="interpolationCurve">The curve how he interpolates. Preset values can be found under <see cref="AnimationCurves"/>. Default: <see cref="AnimationCurves.Linear"/></param>
|
||||
/// <returns>A handle to control the interpolation process.</returns>
|
||||
public InterpolationProcess Interpolate(TimeSpan duration, Vector4 to, BezierCurve? interpolationCurve = null)
|
||||
{
|
||||
InterpolationProcess process = new InterpolationProcess(this, duration, ConvertToVector4(), to, interpolationCurve.GetValueOrDefault(AnimationCurves.Linear));
|
||||
process.Start();
|
||||
|
||||
return process;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Set(float uniform, bool triggerChanged = true)
|
||||
{
|
||||
W = uniform;
|
||||
base.Set(uniform, triggerChanged);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets the a own value to each component.
|
||||
/// </summary>
|
||||
public void Set(float x, float y, float z, float w, bool triggerChanged = true)
|
||||
{
|
||||
W = w;
|
||||
base.Set(x, y, z, triggerChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets each component to the <see cref="Vector4" /> counter-part.
|
||||
/// </summary>
|
||||
public void Set(Vector4 vector, bool triggerChanged = true)
|
||||
{
|
||||
Set(vector.X, vector.Y, vector.Z, vector.W, triggerChanged);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void SetRaw(params float[] parameters)
|
||||
{
|
||||
base.SetRaw(parameters);
|
||||
W = parameters[3];
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Add(float uniform, bool triggerChanged = true)
|
||||
{
|
||||
W += uniform;
|
||||
base.Add(uniform, triggerChanged);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds a <see cref="Vector4"/> to the CVector.
|
||||
/// </summary>
|
||||
/// <param name="vector"></param>
|
||||
/// <param name="triggerChanged">If false, the event Changed doesn't gets triggered </param>
|
||||
public void Add(Vector4 vector, bool triggerChanged = true)
|
||||
{
|
||||
Add(vector.X, vector.Y, vector.Z, vector.W, triggerChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the values to the CVector.
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <param name="z"></param>
|
||||
/// <param name="w"></param>
|
||||
/// <param name="triggerChanged">If false, the event Changed doesn't gets triggered </param>
|
||||
public void Add(float x, float y, float z, float w, bool triggerChanged = true)
|
||||
{
|
||||
W = w;
|
||||
base.Add(x, y, z, triggerChanged);
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return "{" + X + "; " + Y + "; " + Z + "; " + W + "}";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override float GetLengthProcess()
|
||||
{
|
||||
return base.GetLengthProcess() + W * W;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void NormalizationProcess(float length)
|
||||
{
|
||||
base.NormalizationProcess(length);
|
||||
W *= length;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Vector4 ConvertToVector4()
|
||||
{
|
||||
return new Vector4(X, Y, Z, W);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="CVector4"/> into a <see cref="Vector4"/>.
|
||||
/// </summary>
|
||||
public static implicit operator Vector4(CVector4 vector) => new Vector4(vector.X, vector.Y, vector.Z, vector.W);
|
||||
/// <summary>
|
||||
/// Converts a <see cref="Vector4"/> into a <see cref="CVector4"/>.
|
||||
/// </summary>
|
||||
|
||||
public static implicit operator CVector4(Vector4 vector) => new CVector4(vector.X, vector.Y, vector.Z, vector.W);
|
||||
}
|
||||
}
|
||||
83
src/renderer/SM.Base/Types/CVectorBase.cs
Normal file
83
src/renderer/SM.Base/Types/CVectorBase.cs
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
using System;
|
||||
using OpenTK;
|
||||
|
||||
namespace SM.Base.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// Basis for the CVector classes
|
||||
/// </summary>
|
||||
public abstract class CVectorBase
|
||||
{
|
||||
/// <summary>
|
||||
/// This event triggers when a component changed.
|
||||
/// </summary>
|
||||
public event Action Changed;
|
||||
|
||||
/// <summary>
|
||||
/// The length/magnitute of the vector.
|
||||
/// </summary>
|
||||
public float Length => GetLength();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the square of the vector length (magnitude).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This property avoids the costly square root operation required by the Length property. This makes it more suitable
|
||||
/// for comparisons.
|
||||
/// </remarks>
|
||||
public float LengthSquared => GetLength(true);
|
||||
|
||||
/// <summary>
|
||||
/// Get the length of the vector.
|
||||
/// </summary>
|
||||
/// <param name="squared">If true, it will return the squared product.</param>
|
||||
/// <returns></returns>
|
||||
public float GetLength(bool squared = false)
|
||||
{
|
||||
float length = GetLengthProcess();
|
||||
if (squared) return length;
|
||||
return (float)Math.Sqrt(length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes the vector.
|
||||
/// </summary>
|
||||
public void Normalize()
|
||||
{
|
||||
float length = GetLength();
|
||||
NormalizationProcess(length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the values of the vector, by providing the values over an array.
|
||||
/// </summary>
|
||||
/// <param name="parameters"></param>
|
||||
public abstract void SetRaw(params float[] parameters);
|
||||
|
||||
/// <summary>
|
||||
/// This triggers the <see cref="Changed"/> event.
|
||||
/// </summary>
|
||||
protected void TriggerChanged()
|
||||
{
|
||||
Changed?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Conversion from <see cref="float" /> to One-dimensional Vector.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected abstract float GetLengthProcess();
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes the vector.
|
||||
/// </summary>
|
||||
/// <param name="length"></param>
|
||||
protected abstract void NormalizationProcess(float length);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the vector to a <see cref="Vector4"/>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected abstract Vector4 ConvertToVector4();
|
||||
}
|
||||
}
|
||||
60
src/renderer/SM.Base/Utility/Assembly.cs
Normal file
60
src/renderer/SM.Base/Utility/Assembly.cs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains utility functions for handling with assemblies.
|
||||
/// </summary>
|
||||
public class AssemblyUtility
|
||||
{
|
||||
/// <summary>
|
||||
/// Read a file that is saved in a assembly
|
||||
/// </summary>
|
||||
/// <param name="ass">The assembly that contains the file</param>
|
||||
/// <param name="path">The path to the file inside the assembly</param>
|
||||
/// <returns></returns>
|
||||
public static string ReadAssemblyFile(Assembly ass, string path)
|
||||
{
|
||||
return new StreamReader(GetAssemblyStream(ass, path)).ReadToEnd();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a file that is saved in the calling assembly
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the file inside the assembly</param>
|
||||
/// <returns></returns>
|
||||
public static string ReadAssemblyFile(string path)
|
||||
{
|
||||
return ReadAssemblyFile(Assembly.GetCallingAssembly(), path);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a stream of a requested resource.
|
||||
/// </summary>
|
||||
/// <param name="ass">The assembly the resource is in.</param>
|
||||
/// <param name="path">The path to the resource.</param>
|
||||
/// <returns>The stream</returns>
|
||||
public static Stream GetAssemblyStream(Assembly ass, string path)
|
||||
{
|
||||
return ass.GetManifestResourceStream(path) ??
|
||||
throw new InvalidOperationException("Assembly couldn't find resource at path '" + path + "'.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a stream of a requested resource in the calling assembly.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the resource</param>
|
||||
/// <returns>The stream</returns>
|
||||
public static Stream GetAssemblyStream(string path)
|
||||
{
|
||||
return GetAssemblyStream(Assembly.GetCallingAssembly(), path);
|
||||
}
|
||||
}
|
||||
}
|
||||
55
src/renderer/SM.Base/Utility/Deltatime.cs
Normal file
55
src/renderer/SM.Base/Utility/Deltatime.cs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
namespace SM.Base.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// A assistant to control the delta time.
|
||||
/// </summary>
|
||||
public class Deltatime
|
||||
{
|
||||
/// <summary>
|
||||
/// Scaling of the delta time.
|
||||
/// <para>Default: 1</para>
|
||||
/// </summary>
|
||||
public float Scale;
|
||||
|
||||
/// <summary>
|
||||
/// If true, it uses <see cref="RenderDelta" />, otherwise <see cref="UpdateDelta" />.
|
||||
/// <para>Default: false</para>
|
||||
/// </summary>
|
||||
public bool UseRender;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The current update delta time.
|
||||
/// </summary>
|
||||
public static float UpdateDelta { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current fixed update delta time.
|
||||
/// </summary>
|
||||
public static float FixedUpdateDelta { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current render delta time.
|
||||
/// </summary>
|
||||
public static float RenderDelta { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The calculated delta time.
|
||||
/// </summary>
|
||||
public float DeltaTime => (UseRender ? RenderDelta : UpdateDelta) * Scale;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a delta time assistant.
|
||||
/// </summary>
|
||||
/// <param name="scale">The start scale for the delta time. Default: 1</param>
|
||||
/// <param name="useRender">
|
||||
/// If true, it uses <see cref="RenderDelta" />, otherwise <see cref="UpdateDelta" />. Default:
|
||||
/// false
|
||||
/// </param>
|
||||
public Deltatime(float scale = 1, bool useRender = false)
|
||||
{
|
||||
UseRender = useRender;
|
||||
Scale = scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
22
src/renderer/SM.Base/Utility/IInitializable.cs
Normal file
22
src/renderer/SM.Base/Utility/IInitializable.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
namespace SM.Base.Utility
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public interface IInitializable
|
||||
{
|
||||
/// <summary>
|
||||
/// If true, its already initialized.
|
||||
/// </summary>
|
||||
bool IsInitialized { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A event when the object was activated.
|
||||
/// </summary>
|
||||
void Activate();
|
||||
/// <summary>
|
||||
/// A event, when the object was first initialized.
|
||||
/// </summary>
|
||||
void Initialization();
|
||||
}
|
||||
}
|
||||
93
src/renderer/SM.Base/Utility/Randomize.cs
Normal file
93
src/renderer/SM.Base/Utility/Randomize.cs
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// A global helper class for randomization.
|
||||
/// </summary>
|
||||
public static class Randomize
|
||||
{
|
||||
/// <summary>
|
||||
/// The randomizer.
|
||||
/// </summary>
|
||||
public static Random Randomizer = new Random();
|
||||
|
||||
/// <summary>
|
||||
/// Sets the seed for the randomizer.
|
||||
/// </summary>
|
||||
/// <param name="seed">The specified seed.</param>
|
||||
public static void SetSeed(int seed)
|
||||
{
|
||||
Randomizer = new Random(seed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a double and checks if its under the tolerance.
|
||||
/// </summary>
|
||||
public static bool GetBool(float tolerance)
|
||||
{
|
||||
return Randomizer.NextDouble() < tolerance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a integer.
|
||||
/// </summary>
|
||||
public static int GetInt()
|
||||
{
|
||||
return Randomizer.Next();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a integer with a maximum.
|
||||
/// </summary>
|
||||
public static int GetInt(int max)
|
||||
{
|
||||
return Randomizer.Next(max);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a integer with a minimum and maximum
|
||||
/// </summary>
|
||||
public static int GetInt(int min, int max)
|
||||
{
|
||||
return Randomizer.Next(min, max);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a float between 0 and 1.
|
||||
/// </summary>
|
||||
public static float GetFloat()
|
||||
{
|
||||
return (float) Randomizer.NextDouble();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a float between 0 and the specified maximum.
|
||||
/// </summary>
|
||||
public static float GetFloat(float max)
|
||||
{
|
||||
return (float) Randomizer.NextDouble() * max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a float between the specified minimum and the specified maximum.
|
||||
/// </summary>
|
||||
public static float GetFloat(float min, float max)
|
||||
{
|
||||
return (float) Randomizer.NextDouble() * (max - min) + min;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random item from the provided list.
|
||||
/// </summary>
|
||||
public static TSource GetRandomItem<TSource>(this IList<TSource> list)
|
||||
{
|
||||
return list[GetInt(0, list.Count - 1)];
|
||||
}
|
||||
}
|
||||
}
|
||||
87
src/renderer/SM.Base/Utility/Ray.cs
Normal file
87
src/renderer/SM.Base/Utility/Ray.cs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using OpenTK;
|
||||
using SM.OGL.Mesh;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// A utility class to calculate rays.
|
||||
/// </summary>
|
||||
public struct Ray
|
||||
{
|
||||
/// <summary>
|
||||
/// The position of the ray.
|
||||
/// </summary>
|
||||
public Vector3 Position;
|
||||
/// <summary>
|
||||
/// The direction of the ray.
|
||||
/// </summary>
|
||||
public Vector3 Direction;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a ray.
|
||||
/// </summary>
|
||||
/// <param name="position">The position of the ray</param>
|
||||
/// <param name="direction">The direction of the ray.</param>
|
||||
public Ray(Vector3 position, Vector3 direction)
|
||||
{
|
||||
Position = position;
|
||||
Direction = direction.Normalized();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates a object intersection with OBB.
|
||||
/// </summary>
|
||||
/// <param name="box">The bounding box of the object</param>
|
||||
/// <param name="modelMatrix">The model matrix of the object</param>
|
||||
/// <param name="distance">Distance to the object.</param>
|
||||
/// <returns>If true, it intersects with the object.</returns>
|
||||
public bool ObjectIntersection(BoundingBox box, Matrix4 modelMatrix, out float distance)
|
||||
{
|
||||
distance = 0.0f;
|
||||
float tMin = 0.0f;
|
||||
float tMax = 100000.0f;
|
||||
|
||||
Vector3 delta = modelMatrix.Row3.Xyz - Position;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
Vector3 axis = new Vector3(modelMatrix[i, 0], modelMatrix[i, 1], modelMatrix[i, 2]);
|
||||
|
||||
float e = Vector3.Dot(axis, delta);
|
||||
float f = Vector3.Dot(Direction, axis);
|
||||
|
||||
if (Math.Abs(f) > 0.001f)
|
||||
{
|
||||
float t1 = (e + box.Min[i]) / f;
|
||||
float t2 = (e + box.Max[i]) / f;
|
||||
|
||||
if (t1 > t2)
|
||||
{
|
||||
float w = t1;
|
||||
t1 = t2;
|
||||
t2 = w;
|
||||
}
|
||||
|
||||
if (t2 < tMax) tMax = t2;
|
||||
if (t1 > tMin) tMin = t1;
|
||||
|
||||
if (tMax < tMin)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (-e + box.Min[i] > 0.0f || -e + box.Max[i] < 0.0f)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
distance = tMin;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
src/renderer/SM.Base/Utility/RotationUtility.cs
Normal file
24
src/renderer/SM.Base/Utility/RotationUtility.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using OpenTK;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// Utilitys for rotations
|
||||
/// </summary>
|
||||
public class RotationUtility
|
||||
{
|
||||
/// <summary>
|
||||
/// Angle towards an coordinate.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static float TurnTowards(Vector2 origin, Vector2 target)
|
||||
{
|
||||
return MathHelper.RadiansToDegrees((float) Math.Atan2(origin.X - target.X, target.Y - origin.Y));
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/renderer/SM.Base/Utility/Util.cs
Normal file
38
src/renderer/SM.Base/Utility/Util.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// Utility-Functions that are too small for a own class.
|
||||
/// </summary>
|
||||
public class Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Activates a <see cref="IInitializable"/>
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
public static void Activate(IInitializable obj)
|
||||
{
|
||||
if (!obj.IsInitialized)
|
||||
{
|
||||
obj.Initialization();
|
||||
obj.IsInitialized = true;
|
||||
}
|
||||
|
||||
obj.Activate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls a garbage collector.
|
||||
/// </summary>
|
||||
public static void CallGarbageCollector()
|
||||
{
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
}
|
||||
}
|
||||
}
|
||||
91
src/renderer/SM.Base/Window/Contexts/DrawContext.cs
Normal file
91
src/renderer/SM.Base/Window/Contexts/DrawContext.cs
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
#region usings
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using SM.Base.Drawing;
|
||||
using SM.Base.Scene;
|
||||
using SM.Base.Shaders;
|
||||
using SM.OGL.Mesh;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Window
|
||||
{
|
||||
/// <summary>
|
||||
/// The draw context contains (more or less) important information for drawing a object.
|
||||
/// </summary>
|
||||
public struct DrawContext
|
||||
{
|
||||
/// <summary>
|
||||
/// The window, the context came origionally.
|
||||
/// </summary>
|
||||
public IGenericWindow Window { get; internal set; }
|
||||
/// <summary>
|
||||
/// The scene, the context was send to.
|
||||
/// </summary>
|
||||
public GenericScene Scene { get; internal set; }
|
||||
/// <summary>
|
||||
/// The render pipeline, the context is using.
|
||||
/// </summary>
|
||||
public RenderPipeline RenderPipeline { get; internal set; }
|
||||
/// <summary>
|
||||
/// The last object it came though.
|
||||
/// <para>Debugging pourpose.</para>
|
||||
/// </summary>
|
||||
public object LastObject { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The camera the context is using.
|
||||
/// </summary>
|
||||
public GenericCamera UseCamera { get; internal set; }
|
||||
/// <summary>
|
||||
/// The world matrix.
|
||||
/// </summary>
|
||||
public Matrix4 World => UseCamera.World;
|
||||
/// <summary>
|
||||
/// The view matrix.
|
||||
/// </summary>
|
||||
public Matrix4 View => UseCamera.View;
|
||||
|
||||
/// <summary>
|
||||
/// The mesh, that is rendered.
|
||||
/// </summary>
|
||||
public GenericMesh Mesh { get; set; }
|
||||
/// <summary>
|
||||
/// If set, it will force the mesh to render with that primitive type.
|
||||
/// </summary>
|
||||
public PrimitiveType? ForcedType { get; set; }
|
||||
/// <summary>
|
||||
/// The material the mesh is going to use.
|
||||
/// </summary>
|
||||
public Material Material { get; set; }
|
||||
/// <summary>
|
||||
/// The shader the mesh is going to use.
|
||||
/// </summary>
|
||||
public MaterialShader Shader => Material.CustomShader ?? RenderPipeline.DefaultShader;
|
||||
|
||||
/// <summary>
|
||||
/// The master model matrix.
|
||||
/// </summary>
|
||||
public Matrix4 ModelMatrix;
|
||||
/// <summary>
|
||||
/// The master texture matrix.
|
||||
/// </summary>
|
||||
public Matrix3 TextureMatrix;
|
||||
/// <summary>
|
||||
/// Instances
|
||||
/// </summary>
|
||||
public IList<Instance> Instances;
|
||||
|
||||
/// <summary>
|
||||
/// This sets the camera of the context.
|
||||
/// </summary>
|
||||
/// <param name="camera"></param>
|
||||
public void SetCamera(GenericCamera camera)
|
||||
{
|
||||
UseCamera = camera;
|
||||
camera.CalculateViewMatrix(Window);
|
||||
}
|
||||
}
|
||||
}
|
||||
16
src/renderer/SM.Base/Window/Contexts/FixedUpdateContext.cs
Normal file
16
src/renderer/SM.Base/Window/Contexts/FixedUpdateContext.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SM.Base.Window.Contexts
|
||||
{
|
||||
/// <summary>
|
||||
/// A context for the fixed update.
|
||||
/// </summary>
|
||||
public struct FixedUpdateContext
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
29
src/renderer/SM.Base/Window/Contexts/UpdateContext.cs
Normal file
29
src/renderer/SM.Base/Window/Contexts/UpdateContext.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#region usings
|
||||
|
||||
using SM.Base.Scene;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Window
|
||||
{
|
||||
/// <summary>
|
||||
/// A context that gets send when a window want to update the scene.
|
||||
/// </summary>
|
||||
public struct UpdateContext
|
||||
{
|
||||
/// <summary>
|
||||
/// The window what triggered the updated.
|
||||
/// </summary>
|
||||
public IGenericWindow Window;
|
||||
|
||||
/// <summary>
|
||||
/// A current update delta time. Equivalent to <see cref="SMRenderer.DefaultDeltatime"/>.
|
||||
/// </summary>
|
||||
public float Deltatime => SMRenderer.DefaultDeltatime.DeltaTime;
|
||||
|
||||
/// <summary>
|
||||
/// The scene that gets updated.
|
||||
/// </summary>
|
||||
public GenericScene Scene;
|
||||
}
|
||||
}
|
||||
349
src/renderer/SM.Base/Window/GLWindow.cs
Normal file
349
src/renderer/SM.Base/Window/GLWindow.cs
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
#region usings
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Text;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
using SM.Base.Scene;
|
||||
using SM.Base.Utility;
|
||||
using SM.Base.Window.Contexts;
|
||||
using SM.OGL;
|
||||
using Mouse = SM.Base.Controls.Mouse;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.Window
|
||||
{
|
||||
/// <summary>
|
||||
/// This provides the main entry, by executing the window.
|
||||
/// </summary>
|
||||
public class GLWindow : GameWindow, IGenericWindow
|
||||
{
|
||||
private Vector2 _flagWindowPos;
|
||||
private Vector2 _flagWindowSize;
|
||||
|
||||
private Thread _fixedUpdateThread;
|
||||
private WindowFlags _windowFlags;
|
||||
|
||||
private DisplayResolution _normalResolution;
|
||||
private DisplayResolution _fullscreenResolution;
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Loading { get; private set; } = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public float AspectRatio { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public GenericCamera ViewportCamera { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool ForceViewportCamera { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool DrawWhileUnfocused { get; set; } = true;
|
||||
/// <inheritdoc />
|
||||
public bool UpdateWhileUnfocused { get; set; } = false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Vector2 WindowSize { get; set; }
|
||||
/// <inheritdoc />
|
||||
public ISetup AppliedSetup { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public new event Action<IGenericWindow> Resize;
|
||||
/// <inheritdoc />
|
||||
public new event Action<IGenericWindow> Load;
|
||||
|
||||
/// <inheritdoc />
|
||||
public GenericScene CurrentScene { get; private set; }
|
||||
/// <inheritdoc />
|
||||
public RenderPipeline CurrentRenderPipeline { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets/Sets the current window flag.
|
||||
/// </summary>
|
||||
public WindowFlags WindowFlags
|
||||
{
|
||||
get => _windowFlags;
|
||||
set
|
||||
{
|
||||
if (_windowFlags != value)
|
||||
{
|
||||
WindowFlags oldV = _windowFlags;
|
||||
_windowFlags = value;
|
||||
ChangeWindowFlag(value, oldV);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the window with default values.
|
||||
/// <para>Width: 1280px; Height: 720px; Title: Generic OpenGL Title; WindowFlag: Window</para>
|
||||
/// </summary>
|
||||
public GLWindow() : this(1280, 720, "Generic OpenGL Title", WindowFlags.Window)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the window with custom values.
|
||||
/// </summary>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="flags"></param>
|
||||
/// <param name="vSync"></param>
|
||||
public GLWindow(int width, int height, string title, WindowFlags flags, VSyncMode vSync = VSyncMode.On) :
|
||||
base(width, height, default, title, GameWindowFlags.Default, DisplayDevice.Default,
|
||||
GLSettings.ForcedVersion.MajorVersion, GLSettings.ForcedVersion.MinorVersion,
|
||||
GraphicsContextFlags.Default)
|
||||
{
|
||||
VSync = vSync;
|
||||
WindowFlags = flags;
|
||||
|
||||
FocusedChanged += GLWindow_FocusedChanged;
|
||||
_normalResolution = _fullscreenResolution = DisplayDevice.Default.SelectResolution(DisplayDevice.Default.Width, DisplayDevice.Default.Height, DisplayDevice.Default.BitsPerPixel, DisplayDevice.Default.RefreshRate);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A event that gets executed when the window is done loading.
|
||||
/// </summary>
|
||||
public event Action<IGenericWindow> Loaded;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnLoad(EventArgs e)
|
||||
{
|
||||
WindowCode.Load(this);
|
||||
SMRenderer.CurrentWindow = this;
|
||||
|
||||
base.OnLoad(e);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnResize(EventArgs e)
|
||||
{
|
||||
base.OnResize(e);
|
||||
|
||||
WindowCode.Resize(this);
|
||||
|
||||
if (Loading)
|
||||
{
|
||||
Loading = false;
|
||||
Loaded?.Invoke(this);
|
||||
AppliedSetup?.Loaded(this);
|
||||
OnLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This gets called, when the window completed with all initilization steps.
|
||||
/// </summary>
|
||||
protected virtual void OnLoaded()
|
||||
{
|
||||
Icon ??= new Icon(AssemblyUtility.GetAssemblyStream("SM.Base.Window.winIcon.ico"));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnUpdateFrame(FrameEventArgs e)
|
||||
{
|
||||
if (!Focused && !UpdateWhileUnfocused) return;
|
||||
|
||||
base.OnUpdateFrame(e);
|
||||
|
||||
WindowCode.Update(this, (float) e.Time);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnRenderFrame(FrameEventArgs e)
|
||||
{
|
||||
base.OnRenderFrame(e);
|
||||
|
||||
WindowCode.Render(this, (float) e.Time);
|
||||
|
||||
SwapBuffers();
|
||||
|
||||
GLDebugging.CheckGLErrors();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnMouseMove(MouseMoveEventArgs e)
|
||||
{
|
||||
base.OnMouseMove(e);
|
||||
Mouse.MouseMoveEvent(e, this);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public void TriggerLoad()
|
||||
{
|
||||
Load?.Invoke(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void TriggerResize()
|
||||
{
|
||||
Resize?.Invoke(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Update(UpdateContext context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ApplySetup(ISetup setup)
|
||||
{
|
||||
AppliedSetup = setup;
|
||||
setup.Applied(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SetScene(GenericScene scene)
|
||||
{
|
||||
if (Loading)
|
||||
{
|
||||
Loaded += window => SetScene(scene);
|
||||
return;
|
||||
}
|
||||
|
||||
WindowCode.PrepareScene(this, scene);
|
||||
CurrentScene = scene;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SetRenderPipeline(RenderPipeline renderPipeline)
|
||||
{
|
||||
if (Loading)
|
||||
{
|
||||
Loaded += window => SetRenderPipeline(renderPipeline);
|
||||
return;
|
||||
}
|
||||
|
||||
WindowCode.PreparePipeline(this, renderPipeline);
|
||||
CurrentRenderPipeline = renderPipeline;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the resolution in fullscreen mode.
|
||||
/// <para>Can be executed before changing to fullscreen, but with no effect until changed.</para>
|
||||
/// </summary>
|
||||
/// <param name="resolution">The resolution you get from <see cref="DisplayDevice.AvailableResolutions"/> or <see cref="DisplayDevice.SelectResolution"/></param>
|
||||
public void ChangeFullscreenResolution(DisplayResolution resolution)
|
||||
{
|
||||
_fullscreenResolution = resolution;
|
||||
|
||||
if (_windowFlags == WindowFlags.ExclusiveFullscreen) ApplyFullscreenResolution();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the fixed update loop.
|
||||
/// <para>Need to get executed before <see cref="IFixedScriptable"/> can be used.</para>
|
||||
/// </summary>
|
||||
/// <param name="updatesPerSecond"></param>
|
||||
public void RunFixedUpdate(float updatesPerSecond)
|
||||
{
|
||||
Deltatime.FixedUpdateDelta = 1 / (float)updatesPerSecond;
|
||||
|
||||
_fixedUpdateThread = new Thread(ExecuteFixedUpdate);
|
||||
_fixedUpdateThread.Start();
|
||||
}
|
||||
|
||||
private void ExecuteFixedUpdate()
|
||||
{
|
||||
Stopwatch deltaStop = new Stopwatch();
|
||||
while (!IsExiting)
|
||||
{
|
||||
deltaStop.Restart();
|
||||
|
||||
FixedUpdateContext context = new FixedUpdateContext();
|
||||
|
||||
CurrentScene?.FixedUpdate(context);
|
||||
|
||||
long delta = deltaStop.ElapsedMilliseconds;
|
||||
int waitTime = Math.Max((int)(Deltatime.FixedUpdateDelta * 1000) - (int)delta, 0);
|
||||
Thread.Sleep(waitTime);
|
||||
}
|
||||
}
|
||||
|
||||
private void GLWindow_FocusedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (_windowFlags == WindowFlags.ExclusiveFullscreen)
|
||||
{
|
||||
if (!Focused)
|
||||
{
|
||||
DisplayDevice.Default.ChangeResolution(_normalResolution);
|
||||
WindowState = WindowState.Minimized;
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyFullscreenResolution();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private void ChangeWindowFlag(WindowFlags newFlag, WindowFlags oldFlag)
|
||||
{
|
||||
if (oldFlag == WindowFlags.Window)
|
||||
{
|
||||
_flagWindowSize = WindowSize;
|
||||
_flagWindowPos = new Vector2(X, Y);
|
||||
}
|
||||
|
||||
switch (newFlag)
|
||||
{
|
||||
case WindowFlags.Window:
|
||||
DisplayDevice.Default.ChangeResolution(_normalResolution);
|
||||
WindowState = WindowState.Normal;
|
||||
Width = (int)_flagWindowSize.X;
|
||||
Height = (int)_flagWindowSize.Y;
|
||||
|
||||
X = (int) _flagWindowPos.X;
|
||||
Y = (int) _flagWindowPos.Y;
|
||||
|
||||
WindowBorder = WindowBorder.Resizable;
|
||||
|
||||
|
||||
break;
|
||||
case WindowFlags.BorderlessWindow:
|
||||
DisplayDevice.Default.ChangeResolution(_normalResolution);
|
||||
WindowState = WindowState.Maximized;
|
||||
WindowBorder = WindowBorder.Hidden;
|
||||
|
||||
X = 0;
|
||||
Y = 0;
|
||||
Width = DisplayDevice.Default.Width;
|
||||
Height = DisplayDevice.Default.Height;
|
||||
|
||||
break;
|
||||
case WindowFlags.ExclusiveFullscreen:
|
||||
|
||||
|
||||
WindowState = WindowState.Fullscreen;
|
||||
ApplyFullscreenResolution();
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(newFlag), newFlag, null);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void ApplyFullscreenResolution()
|
||||
{
|
||||
DisplayDevice.Default.ChangeResolution(_fullscreenResolution);
|
||||
Width = _fullscreenResolution.Width;
|
||||
Height = _fullscreenResolution.Height;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue