Added Summeries

This commit is contained in:
Michel Fedde 2021-03-19 20:59:02 +01:00
parent 71a22df8bd
commit 8296d9b8a9
47 changed files with 812 additions and 177 deletions

1
.gitignore vendored
View file

@ -26,6 +26,7 @@ bld/
[Bb]in/ [Bb]in/
[Oo]bj/ [Oo]bj/
[Ll]og/ [Ll]og/
build/*
# Visual Studio 2015/2017 cache/options directory # Visual Studio 2015/2017 cache/options directory
.vs/ .vs/

View file

@ -28,6 +28,18 @@ namespace SM.Base.Controls
/// </summary> /// </summary>
public static Vector2 InScreenNormalized { get; private set; } 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> /// <summary>
/// The event to update the values. /// The event to update the values.
/// </summary> /// </summary>
@ -53,11 +65,21 @@ namespace SM.Base.Controls
_mouseState = OpenTK.Input.Mouse.GetState(); _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) public static bool IsDown(MouseButton button, bool once = false)
{ {
return _mouseState?[button] == true && !(once && _lastButtonsPressed.Contains(button)); 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) public static bool IsUp(MouseButton button, bool once = false)
{ {
return _mouseState?[button] == false && !(once && !_lastButtonsPressed.Contains(button)); return _mouseState?[button] == false && !(once && !_lastButtonsPressed.Contains(button));

View file

@ -55,6 +55,7 @@ namespace SM.Base.Drawing
/// </summary> /// </summary>
public bool Active { get; set; } = true; public bool Active { get; set; } = true;
/// <inheritdoc />
public bool RenderActive { get; set; } = true; public bool RenderActive { get; set; } = true;
/// <inheritdoc /> /// <inheritdoc />

View file

@ -34,19 +34,10 @@
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="GLWpfControl, Version=3.2.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\OpenTK.GLWpfControl.3.2.3\lib\net452\GLWpfControl.dll</HintPath>
</Reference>
<Reference Include="OpenTK, Version=3.3.1.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL"> <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> <HintPath>..\..\packages\OpenTK.3.3.1\lib\net20\OpenTK.dll</HintPath>
</Reference> </Reference>
<Reference Include="PresentationCore" /> <Reference Include="PresentationCore" />
<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" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Drawing" /> <Reference Include="System.Drawing" />

View file

@ -15,8 +15,8 @@ namespace SM.Base.Scene
/// </summary> /// </summary>
public abstract class GenericItemCollection : List<IShowItem>, IShowItem, IShowCollection, IScriptable, IFixedScriptable public abstract class GenericItemCollection : List<IShowItem>, IShowItem, IShowCollection, IScriptable, IFixedScriptable
{ {
private List<IScriptable> _scriptableObjects = new List<IScriptable>(); private readonly List<IScriptable> _scriptableObjects = new List<IScriptable>();
private List<IFixedScriptable> _fixedScriptables = new List<IFixedScriptable>(); private readonly List<IFixedScriptable> _fixedScriptables = new List<IFixedScriptable>();
/// <summary> /// <summary>
/// Currently active script objects. /// Currently active script objects.
@ -45,6 +45,7 @@ namespace SM.Base.Scene
/// <inheritdoc /> /// <inheritdoc />
public bool RenderActive { get; set; } = true; public bool RenderActive { get; set; } = true;
/// <inheritdoc />
public virtual void FixedUpdate(FixedUpdateContext context) public virtual void FixedUpdate(FixedUpdateContext context)
{ {
if (!Active || !UpdateActive) return; if (!Active || !UpdateActive) return;
@ -126,6 +127,11 @@ namespace SM.Base.Scene
if (item is IFixedScriptable fs) _fixedScriptables.Add(fs); if (item is IFixedScriptable fs) _fixedScriptables.Add(fs);
} }
/// <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 IShowItem[] items) public void Remove(params IShowItem[] items)
{ {
foreach (var item in items) foreach (var item in items)
@ -161,6 +167,12 @@ namespace SM.Base.Scene
if (item is IFixedScriptable fs) _fixedScriptables.Remove(fs); if (item is IFixedScriptable fs) _fixedScriptables.Remove(fs);
} }
/// <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) public ICollection<IShowItem> GetAllItems(bool includeCollections = false)
{ {
List<IShowItem> items = new List<IShowItem>(); List<IShowItem> items = new List<IShowItem>();
@ -224,7 +236,6 @@ namespace SM.Base.Scene
/// <summary> /// <summary>
/// Contains a list of show items with transformation. /// Contains a list of show items with transformation.
/// </summary> /// </summary>
/// <typeparam name="TItem">The type of show items.</typeparam>
/// <typeparam name="TTransformation">The type of transformation.</typeparam> /// <typeparam name="TTransformation">The type of transformation.</typeparam>
public abstract class GenericItemCollection<TTransformation> : GenericItemCollection, public abstract class GenericItemCollection<TTransformation> : GenericItemCollection,
IShowTransformItem<TTransformation> IShowTransformItem<TTransformation>

View file

@ -213,18 +213,24 @@ namespace SM.Base.Scene
/// A generic scene that imports different functions. /// A generic scene that imports different functions.
/// </summary> /// </summary>
/// <typeparam name="TCamera">The type of cameras.</typeparam> /// <typeparam name="TCamera">The type of cameras.</typeparam>
/// <typeparam name="TItem">The type of show items.</typeparam>
/// <typeparam name="TCollection">The type for collections</typeparam> /// <typeparam name="TCollection">The type for collections</typeparam>
public abstract class GenericScene<TCamera, TCollection> : GenericScene public abstract class GenericScene<TCamera, TCollection> : GenericScene
where TCamera : GenericCamera, new() where TCamera : GenericCamera, new()
where TCollection : GenericItemCollection, new() where TCollection : GenericItemCollection, new()
{ {
/// <summary>
/// Objects inside the scene, but as the collection type.
/// </summary>
public new TCollection Objects public new TCollection Objects
{ {
get => (TCollection) base.Objects; get => (TCollection) base.Objects;
set => base.Objects = value; set => base.Objects = value;
} }
/// <summary>
/// HUD-Objects inside the scene, but as the collection type.
/// </summary>
public new TCollection HUD public new TCollection HUD
{ {
get get
@ -235,18 +241,28 @@ namespace SM.Base.Scene
set => base.HUD = value; 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 public new TCamera Camera
{ {
get => (TCamera) base.Camera; get => (TCamera) base.Camera;
set => base.Camera = value; set => base.Camera = value;
} }
/// <summary>
/// A camera to control the HUD.
/// </summary>
public new TCamera HUDCamera public new TCamera HUDCamera
{ {
get => (TCamera) base.HUDCamera; get => (TCamera) base.HUDCamera;
set => base.HUDCamera = value; set => base.HUDCamera = value;
} }
/// <summary>
/// A camera to control the background.
/// </summary>
public new TCamera BackgroundCamera public new TCamera BackgroundCamera
{ {
get => (TCamera) base.BackgroundCamera; get => (TCamera) base.BackgroundCamera;

View file

@ -55,19 +55,36 @@ namespace SM.Base.Scene
void OnRemoved(object sender); void OnRemoved(object sender);
} }
/// <summary>
/// Interface to implement transformation.
/// </summary>
/// <typeparam name="TTransform"></typeparam>
public interface ITransformItem<TTransform> public interface ITransformItem<TTransform>
where TTransform : GenericTransformation where TTransform : GenericTransformation
{ {
/// <summary>
/// Controls the transformation of the object.
/// </summary>
TTransform Transform { get; set; } 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> public interface IShowTransformItem<TTransform> : IShowItem, ITransformItem<TTransform>
where TTransform : GenericTransformation where TTransform : GenericTransformation
{ {
} }
/// <summary>
/// Interface to implement models in the object.
/// </summary>
public interface IModelItem public interface IModelItem
{ {
/// <summary>
/// The mesh the rendering should use.
/// </summary>
GenericMesh Mesh { get; set; } GenericMesh Mesh { get; set; }
} }
} }

View file

@ -96,7 +96,6 @@ namespace SM.Base.Types
/// <summary> /// <summary>
/// Conversion from <see cref="float" /> to One-dimensional Vector. /// Conversion from <see cref="float" /> to One-dimensional Vector.
/// </summary> /// </summary>
/// <param name="f"></param>
/// <returns></returns> /// <returns></returns>
//public static implicit operator CVector1(float f) => new CVector1(f); //public static implicit operator CVector1(float f) => new CVector1(f);
protected virtual float GetLengthProcess() protected virtual float GetLengthProcess()
@ -104,14 +103,27 @@ namespace SM.Base.Types
return X * X; return X * X;
} }
/// <summary>
/// Normalizes the vector.
/// </summary>
/// <param name="length"></param>
protected virtual void NormalizationProcess(float length) protected virtual void NormalizationProcess(float length)
{ {
X *= length; X *= length;
} }
/// <summary>
/// This triggers the <see cref="Changed"/> event.
/// </summary>
protected void TriggerChanged() protected void TriggerChanged()
{ {
Changed?.Invoke(); Changed?.Invoke();
} }
/// <inheritdoc />
public override string ToString()
{
return X.ToString();
}
} }
} }

View file

@ -46,6 +46,12 @@ namespace SM.Base.Types
Y *= length; Y *= length;
} }
/// <inheritdoc />
public override string ToString()
{
return "{"+X+"; "+Y+"}";
}
/// <summary> /// <summary>
/// Sets each component to the same value /// Sets each component to the same value
/// </summary> /// </summary>
@ -58,7 +64,6 @@ namespace SM.Base.Types
/// <summary> /// <summary>
/// Sets each component to the <see cref="Vector2" /> counter-part. /// Sets each component to the <see cref="Vector2" /> counter-part.
/// </summary> /// </summary>
/// <param name="vector"></param>
public void Set(Vector2 vector, bool triggerChanged = true) public void Set(Vector2 vector, bool triggerChanged = true)
{ {
Set(vector.X, vector.Y, triggerChanged); Set(vector.X, vector.Y, triggerChanged);
@ -67,8 +72,6 @@ namespace SM.Base.Types
/// <summary> /// <summary>
/// Sets the a own value to each component. /// Sets the a own value to each component.
/// </summary> /// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
public void Set(float x, float y, bool triggerChanged = true) public void Set(float x, float y, bool triggerChanged = true)
{ {
Y = y; Y = y;

View file

@ -46,6 +46,12 @@ namespace SM.Base.Types
Z *= length; Z *= length;
} }
/// <inheritdoc />
public override string ToString()
{
return "{" + X + "; " + Y + "}";
}
/// <inheritdoc /> /// <inheritdoc />
public override void Set(float uniform, bool triggerChanged = true) public override void Set(float uniform, bool triggerChanged = true)
{ {

View file

@ -6,12 +6,24 @@ using SM.Base.Scene;
namespace SM.Base.Window namespace SM.Base.Window
{ {
/// <summary>
/// A context that gets send when a window want to update the scene.
/// </summary>
public struct UpdateContext public struct UpdateContext
{ {
/// <summary>
/// The window what triggered the updated.
/// </summary>
public IGenericWindow Window; public IGenericWindow Window;
/// <summary>
/// A current update delta time. Equivalent to <see cref="SMRenderer.DefaultDeltatime"/>.
/// </summary>
public float Deltatime => SMRenderer.DefaultDeltatime.DeltaTime; public float Deltatime => SMRenderer.DefaultDeltatime.DeltaTime;
/// <summary>
/// The scene that gets updated.
/// </summary>
public GenericScene Scene; public GenericScene Scene;
} }
} }

View file

@ -18,17 +18,80 @@ using Mouse = SM.Base.Controls.Mouse;
namespace SM.Base.Window namespace SM.Base.Window
{ {
/// <summary>
/// This provides the main entry, by executing the window.
/// </summary>
public class GLWindow : GameWindow, IGenericWindow public class GLWindow : GameWindow, IGenericWindow
{ {
private Vector2 _flagWindowSize; private Vector2 _flagWindowSize;
private Thread _fixedUpdateThread; private Thread _fixedUpdateThread;
private WindowFlags _windowFlags;
public WindowFlags WindowFlags;
/// <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 = value;
ChangeWindowFlag(value);
}
}
}
/// <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) 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) : public GLWindow(int width, int height, string title, WindowFlags flags, VSyncMode vSync = VSyncMode.On) :
base(width, height, default, title, (GameWindowFlags) flags, DisplayDevice.Default, base(width, height, default, title, (GameWindowFlags) flags, DisplayDevice.Default,
GLSettings.ForcedVersion.MajorVersion, GLSettings.ForcedVersion.MinorVersion, GLSettings.ForcedVersion.MajorVersion, GLSettings.ForcedVersion.MinorVersion,
@ -37,39 +100,16 @@ namespace SM.Base.Window
VSync = vSync; VSync = vSync;
_flagWindowSize = new Vector2(width, height); _flagWindowSize = new Vector2(width, height);
ChangeWindowFlag(flags); WindowFlags = flags;
} }
public bool Loading { get; private set; } = true;
public float AspectRatio { get; set; }
public GenericCamera ViewportCamera { get; set; }
public bool ForceViewportCamera { get; set; }
public bool DrawWhileUnfocused { get; set; } = true;
public bool UpdateWhileUnfocused { get; set; } = false;
public Vector2 WindowSize { get; set; }
public ISetup AppliedSetup { get; private set; }
public new event Action<IGenericWindow> Resize;
public new event Action<IGenericWindow> Load;
public GenericScene CurrentScene { get; private set; }
public RenderPipeline CurrentRenderPipeline { get; private set; }
public void TriggerLoad()
{
Load?.Invoke(this);
}
public void TriggerResize()
{
Resize?.Invoke(this);
}
/// <summary>
/// A event that gets executed when the window is done loading.
/// </summary>
public event Action<IGenericWindow> Loaded; public event Action<IGenericWindow> Loaded;
/// <inheritdoc />
protected override void OnLoad(EventArgs e) protected override void OnLoad(EventArgs e)
{ {
WindowCode.Load(this); WindowCode.Load(this);
@ -78,6 +118,7 @@ namespace SM.Base.Window
base.OnLoad(e); base.OnLoad(e);
} }
/// <inheritdoc />
protected override void OnResize(EventArgs e) protected override void OnResize(EventArgs e)
{ {
base.OnResize(e); base.OnResize(e);
@ -94,6 +135,7 @@ namespace SM.Base.Window
} }
} }
/// <inheritdoc />
protected override void OnUpdateFrame(FrameEventArgs e) protected override void OnUpdateFrame(FrameEventArgs e)
{ {
if (!Focused && !UpdateWhileUnfocused) return; if (!Focused && !UpdateWhileUnfocused) return;
@ -104,6 +146,7 @@ namespace SM.Base.Window
} }
/// <inheritdoc />
protected override void OnRenderFrame(FrameEventArgs e) protected override void OnRenderFrame(FrameEventArgs e)
{ {
base.OnRenderFrame(e); base.OnRenderFrame(e);
@ -115,23 +158,40 @@ namespace SM.Base.Window
GLDebugging.CheckGLErrors(); GLDebugging.CheckGLErrors();
} }
/// <inheritdoc />
protected override void OnMouseMove(MouseMoveEventArgs e) protected override void OnMouseMove(MouseMoveEventArgs e)
{ {
base.OnMouseMove(e); base.OnMouseMove(e);
Mouse.MouseMoveEvent(e, this); Mouse.MouseMoveEvent(e, this);
} }
/// <inheritdoc />
public void TriggerLoad()
{
Load?.Invoke(this);
}
/// <inheritdoc />
public void TriggerResize()
{
Resize?.Invoke(this);
}
/// <inheritdoc />
public void Update(UpdateContext context) public void Update(UpdateContext context)
{ {
} }
/// <inheritdoc />
public void ApplySetup(ISetup setup) public void ApplySetup(ISetup setup)
{ {
AppliedSetup = setup; AppliedSetup = setup;
setup.Applied(this); setup.Applied(this);
} }
/// <inheritdoc />
public void SetScene(GenericScene scene) public void SetScene(GenericScene scene)
{ {
if (Loading) if (Loading)
@ -144,6 +204,7 @@ namespace SM.Base.Window
CurrentScene = scene; CurrentScene = scene;
} }
/// <inheritdoc />
public void SetRenderPipeline(RenderPipeline renderPipeline) public void SetRenderPipeline(RenderPipeline renderPipeline)
{ {
if (Loading) if (Loading)
@ -156,34 +217,12 @@ namespace SM.Base.Window
CurrentRenderPipeline = renderPipeline; CurrentRenderPipeline = renderPipeline;
} }
public void ChangeWindowFlag(WindowFlags newFlag)
{
WindowFlags = newFlag;
switch (newFlag)
{
case WindowFlags.Window:
Width = (int) _flagWindowSize.X;
Height = (int) _flagWindowSize.Y;
WindowBorder = WindowBorder.Resizable;
break;
case WindowFlags.BorderlessWindow:
WindowBorder = WindowBorder.Hidden;
X = Screen.PrimaryScreen.Bounds.Left;
Y = Screen.PrimaryScreen.Bounds.Top;
Width = Screen.PrimaryScreen.Bounds.Width;
Height = Screen.PrimaryScreen.Bounds.Height;
break;
case WindowFlags.ExclusiveFullscreen:
break;
default:
throw new ArgumentOutOfRangeException(nameof(newFlag), newFlag, null);
}
}
/// <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) public void RunFixedUpdate(float updatesPerSecond)
{ {
Deltatime.FixedUpdateDelta = 1 / (float)updatesPerSecond; Deltatime.FixedUpdateDelta = 1 / (float)updatesPerSecond;
@ -208,5 +247,31 @@ namespace SM.Base.Window
Thread.Sleep(waitTime); Thread.Sleep(waitTime);
} }
} }
private void ChangeWindowFlag(WindowFlags newFlag)
{
switch (newFlag)
{
case WindowFlags.Window:
Width = (int)_flagWindowSize.X;
Height = (int)_flagWindowSize.Y;
WindowBorder = WindowBorder.Resizable;
break;
case WindowFlags.BorderlessWindow:
WindowBorder = WindowBorder.Hidden;
X = Screen.PrimaryScreen.Bounds.Left;
Y = Screen.PrimaryScreen.Bounds.Top;
Width = Screen.PrimaryScreen.Bounds.Width;
Height = Screen.PrimaryScreen.Bounds.Height;
break;
case WindowFlags.ExclusiveFullscreen:
break;
default:
throw new ArgumentOutOfRangeException(nameof(newFlag), newFlag, null);
}
}
} }
} }

View file

@ -10,39 +10,106 @@ using SM.OGL.Framebuffer;
namespace SM.Base.Window namespace SM.Base.Window
{ {
/// <summary>
/// This interface sets ground functions for windows.
/// </summary>
public interface IGenericWindow : IFramebufferWindow public interface IGenericWindow : IFramebufferWindow
{ {
/// <summary>
/// If true, the window is currently loading.
/// </summary>
bool Loading { get; } bool Loading { get; }
/// <summary>
/// Holds the aspect ratio of the window.
/// </summary>
float AspectRatio { get; set; } float AspectRatio { get; set; }
/// <summary>
/// The viewport camera is used, when no camera is found in the scene.
/// </summary>
GenericCamera ViewportCamera { get; set; } GenericCamera ViewportCamera { get; set; }
/// <summary>
/// Turning this to true, will force the window to render in the viewport camera.
/// </summary>
bool ForceViewportCamera { get; set; } bool ForceViewportCamera { get; set; }
/// <summary>
/// Turning this to false will not allow drawing while the window is not in focus.
/// </summary>
bool DrawWhileUnfocused { get; set; } bool DrawWhileUnfocused { get; set; }
/// <summary>
/// Turning this to false will not allow updating while the window is not in focus.
/// </summary>
bool UpdateWhileUnfocused { get; set; } bool UpdateWhileUnfocused { get; set; }
/// <summary>
/// Contains the window size.
/// </summary>
Vector2 WindowSize { get; set; } Vector2 WindowSize { get; set; }
/// <summary>
/// The rectangle the window is using.
/// </summary>
Rectangle ClientRectangle { get; } Rectangle ClientRectangle { get; }
/// <summary>
/// The setup that was applied to the window.
/// </summary>
ISetup AppliedSetup { get; } ISetup AppliedSetup { get; }
/// <summary>
/// The scene that is currently used.
/// </summary>
GenericScene CurrentScene { get; } GenericScene CurrentScene { get; }
/// <summary>
/// The render pipeline that is currently used.
/// </summary>
RenderPipeline CurrentRenderPipeline { get; } RenderPipeline CurrentRenderPipeline { get; }
/// <summary>
/// An event, when the window resizes.
/// </summary>
event Action<IGenericWindow> Resize; event Action<IGenericWindow> Resize;
/// <summary>
/// An event, when the window is loading.
/// </summary>
event Action<IGenericWindow> Load; event Action<IGenericWindow> Load;
/// <summary>
/// This gets executed, when the window should update something.
/// </summary>
/// <param name="context">The context of the update.</param>
void Update(UpdateContext context); void Update(UpdateContext context);
/// <summary>
/// This applies a setup to the window.
/// </summary>
/// <param name="setup"></param>
void ApplySetup(ISetup setup); void ApplySetup(ISetup setup);
/// <summary>
/// This sets a scene for the window to use.
/// </summary>
/// <param name="scene"></param>
void SetScene(GenericScene scene); void SetScene(GenericScene scene);
/// <summary>
/// This sets a render pipeline, from where the scene gets rendered.
/// </summary>
/// <param name="renderPipeline"></param>
void SetRenderPipeline(RenderPipeline renderPipeline); void SetRenderPipeline(RenderPipeline renderPipeline);
/// <summary>
/// This triggeres the <see cref="Load"/> event.
/// </summary>
void TriggerLoad(); void TriggerLoad();
/// <summary>
/// This triggeres the <see cref="Resize"/> event.
/// </summary>
void TriggerResize(); void TriggerResize();
/// <summary>
/// This closes the window.
/// </summary>
void Close(); void Close();
} }
} }

View file

@ -1,8 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="OpenTK" version="3.3.1" targetFramework="net452" /> <package id="OpenTK" version="3.3.1" targetFramework="net452" />
<package id="OpenTK.GLWpfControl" version="3.2.3" targetFramework="net452" />
<package id="SharpDX" version="4.2.0" targetFramework="net452" />
<package id="SharpDX.XInput" version="4.2.0" targetFramework="net452" />
</packages> </packages>

View file

@ -14,7 +14,7 @@ namespace SM.OGL.Framebuffer
/// </summary> /// </summary>
public class ColorAttachment : TextureBase public class ColorAttachment : TextureBase
{ {
private int _multisamples; private readonly int _multisamples;
/// <summary> /// <summary>
/// The ID the attachment was given. /// The ID the attachment was given.
@ -50,6 +50,12 @@ namespace SM.OGL.Framebuffer
public ColorAttachment(int attachmentId) : this(attachmentId, PixelInformation.RGBA_LDR) public ColorAttachment(int attachmentId) : this(attachmentId, PixelInformation.RGBA_LDR)
{ } { }
/// <summary>
/// Creates a color attachment with a specific id, specific pixel informations and multisamples.
/// </summary>
/// <param name="attachmentID"></param>
/// <param name="pixelInformation"></param>
/// <param name="multisamples"></param>
public ColorAttachment(int attachmentID, PixelInformation pixelInformation, int multisamples = 0) public ColorAttachment(int attachmentID, PixelInformation pixelInformation, int multisamples = 0)
{ {
AttachmentID = attachmentID; AttachmentID = attachmentID;

View file

@ -14,6 +14,7 @@ namespace SM.OGL.Framebuffer
/// </summary> /// </summary>
public class Framebuffer : GLObject public class Framebuffer : GLObject
{ {
/// <inheritdoc />
protected override bool AutoCompile { get; set; } = true; protected override bool AutoCompile { get; set; } = true;
/// <summary> /// <summary>
@ -25,8 +26,8 @@ namespace SM.OGL.Framebuffer
CanCompile = false, CanCompile = false,
}; };
private IFramebufferWindow _window; private readonly IFramebufferWindow _window;
private float _windowScale; private readonly float _windowScale;
/// <inheritdoc /> /// <inheritdoc />
public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Framebuffer; public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Framebuffer;
@ -42,6 +43,9 @@ namespace SM.OGL.Framebuffer
public Dictionary<string, ColorAttachment> ColorAttachments { get; private set; } = public Dictionary<string, ColorAttachment> ColorAttachments { get; private set; } =
new Dictionary<string, ColorAttachment>(); new Dictionary<string, ColorAttachment>();
/// <summary>
/// Contains the current renderbuffer attachments of the framebuffer.
/// </summary>
public List<RenderbufferAttachment> RenderbufferAttachments { get; } = new List<RenderbufferAttachment>(); public List<RenderbufferAttachment> RenderbufferAttachments { get; } = new List<RenderbufferAttachment>();
/// <summary> /// <summary>
@ -131,6 +135,10 @@ namespace SM.OGL.Framebuffer
ColorAttachments.Add(key, value); ColorAttachments.Add(key, value);
} }
/// <summary>
/// Appends a renderbuffer attachment to the framebuffer.
/// </summary>
/// <param name="attachment"></param>
public void AppendRenderbuffer(RenderbufferAttachment attachment) public void AppendRenderbuffer(RenderbufferAttachment attachment)
{ {
RenderbufferAttachments.Add(attachment); RenderbufferAttachments.Add(attachment);
@ -173,6 +181,11 @@ namespace SM.OGL.Framebuffer
GL.Clear(clear); GL.Clear(clear);
} }
/// <summary>
/// Returns a <see cref="Framebuffer"/> handle of the current framebuffer.
/// </summary>
/// <param name="target"></param>
/// <returns></returns>
public static Framebuffer GetCurrentlyActive(FramebufferTarget target = FramebufferTarget.Framebuffer) public static Framebuffer GetCurrentlyActive(FramebufferTarget target = FramebufferTarget.Framebuffer)
{ {
Framebuffer buffer = new Framebuffer() Framebuffer buffer = new Framebuffer()

View file

@ -5,7 +5,13 @@
/// </summary> /// </summary>
public interface IFramebufferWindow public interface IFramebufferWindow
{ {
/// <summary>
/// The width of the window.
/// </summary>
int Width { get; } int Width { get; }
/// <summary>
/// The height of the window.
/// </summary>
int Height { get; } int Height { get; }
} }
} }

View file

@ -14,20 +14,30 @@ namespace SM.OGL
/// </summary> /// </summary>
public abstract class GLObject public abstract class GLObject
{ {
private static List<GLObject> _disposableObjects = new List<GLObject>(); private static readonly List<GLObject> _disposableObjects = new List<GLObject>();
private string _name = ""; private string _name = "";
protected bool ReportAsNotCompiled;
/// <summary> /// <summary>
/// Contains the OpenGL ID /// Contains the OpenGL ID
/// </summary> /// </summary>
protected int _id = -1; protected int _id = -1;
/// <summary>
/// This can mark the object to never report as compiled, even when it was.
/// <para>You can still figure out, if it was compiled by checking <see cref="_id"/>. If not -1, its compiled.</para>
/// <para>Default: false</para>
/// </summary>
protected bool ReportAsNotCompiled;
/// <summary>
/// This can prevent the object to compile.
/// <para>Default: true</para>
/// </summary>
protected bool CanCompile = true; protected bool CanCompile = true;
/// <summary> /// <summary>
/// If true, the system will call "Compile()", when "ID" is tried to get, but the id is still -1. /// If true, the system will call "Compile()", when "ID" is tried to get, but the id is still -1.
/// <para>Default: false</para>
/// </summary> /// </summary>
protected virtual bool AutoCompile { get; set; } = false; protected virtual bool AutoCompile { get; set; } = false;
@ -36,6 +46,10 @@ namespace SM.OGL
/// </summary> /// </summary>
public bool WasCompiled => _id > 0 && !ReportAsNotCompiled; public bool WasCompiled => _id > 0 && !ReportAsNotCompiled;
/// <summary>
/// Names the object
/// <para>If <see cref="GLSystem.Debugging"/> is true, then it will also name the object in the system.</para>
/// </summary>
public string Name public string Name
{ {
get => _name; get => _name;
@ -111,11 +125,15 @@ namespace SM.OGL
Compile(); Compile();
} }
/// <inheritdoc />
public override string ToString() public override string ToString()
{ {
return $"{GetType().Name} {(string.IsNullOrEmpty(_name) ? "" : $"\"{_name}\" ")}[{_id}]"; return $"{GetType().Name} {(string.IsNullOrEmpty(_name) ? "" : $"\"{_name}\" ")}[{_id}]";
} }
/// <summary>
/// This disposes the current objects, that where marked by the garbage collector.
/// </summary>
public static void DisposeMarkedObjects() public static void DisposeMarkedObjects()
{ {
foreach (GLObject o in _disposableObjects) foreach (GLObject o in _disposableObjects)
@ -134,6 +152,9 @@ namespace SM.OGL
return glo.ID; return glo.ID;
} }
/// <summary>
/// If the garbage collector is trying to remove this object, it will add the object to a list, what get removed when <see cref="DisposeMarkedObjects"/> is called.
/// </summary>
~GLObject() ~GLObject()
{ {
if (WasCompiled) _disposableObjects.Add(this); if (WasCompiled) _disposableObjects.Add(this);

View file

@ -49,21 +49,59 @@ namespace SM.OGL.Mesh
/// <returns></returns> /// <returns></returns>
public Vector3 this[bool x, bool y, bool z] => Get(x,y,z); public Vector3 this[bool x, bool y, bool z] => Get(x,y,z);
/// <summary>
/// Equivalent to <see cref="this"/>.
/// <para>Returns specific configurations of corners</para>
/// </summary>
/// <param name="x">If true, it takes the X-value of maximum, otherwise the minimum.</param>
/// <param name="y">If true, it takes the Y-value of maximum, otherwise the minimum.</param>
/// <param name="z">If true, it takes the Z-value of maximum, otherwise the minimum.</param>
/// <returns></returns>
public Vector3 Get(bool x, bool y, bool z) public Vector3 Get(bool x, bool y, bool z)
{ {
return new Vector3(x ? Max.X : Min.X, y ? Max.Y : Min.Y, z ? Max.Z : Min.Z); return new Vector3(x ? Max.X : Min.X, y ? Max.Y : Min.Y, z ? Max.Z : Min.Z);
} }
/// <summary>
/// Returns the configuration of the two furthest away corners.
/// </summary>
/// <param name="xyz">If true, it will take the maximum, otherwise the minimum.</param>
/// <returns></returns>
public Vector3 Get(bool xyz) => Get(xyz, xyz, xyz); public Vector3 Get(bool xyz) => Get(xyz, xyz, xyz);
/// <summary>
/// Returns the configuration of one corner and applies a transformation to it.
/// <para>If the transformation causes the points to shift to no being in the right location is NOT checked!</para>
/// <para>For that use <see cref="GetBounds"/></para>
/// </summary>
/// <param name="transformation">The transformation</param>
/// <param name="x">If true, it takes the X-value of maximum, otherwise the minimum.</param>
/// <param name="y">If true, it takes the Y-value of maximum, otherwise the minimum.</param>
/// <param name="z">If true, it takes the Z-value of maximum, otherwise the minimum.</param>
/// <returns></returns>
public Vector3 Get(Matrix4 transformation, bool x, bool y, bool z) public Vector3 Get(Matrix4 transformation, bool x, bool y, bool z)
{ {
Vector3 get = Get(x, y, z); Vector3 get = Get(x, y, z);
return (new Vector4(get, 1) * transformation).Xyz; return (new Vector4(get, 1) * transformation).Xyz;
} }
/// <summary>
/// Returns the configuration of the two furthest away corners.
/// <para>If the transformation causes the points to shift to no being in the right location is NOT checked!</para>
/// <para>For that use <see cref="GetBounds"/></para>
/// </summary>
/// <param name="transformation">The transformation</param>
/// <param name="xyz">If true, it will take the maximum, otherwise the minimum.</param>
/// <returns></returns>
public Vector3 Get(Matrix4 transformation, bool xyz) => Get(transformation, xyz, xyz, xyz); public Vector3 Get(Matrix4 transformation, bool xyz) => Get(transformation, xyz, xyz, xyz);
/// <summary>
/// Returns the bounds of the bounding box while applying a transformation.
/// <para>This takes care of min and max locations.</para>
/// </summary>
/// <param name="transformation"></param>
/// <param name="min"></param>
/// <param name="max"></param>
public void GetBounds(Matrix4 transformation, out Vector3 min, out Vector3 max) public void GetBounds(Matrix4 transformation, out Vector3 min, out Vector3 max)
{ {
min = Get(transformation, false); min = Get(transformation, false);
@ -79,6 +117,10 @@ namespace SM.OGL.Mesh
} }
} }
/// <summary>
/// Updates the bounding box to the mesh provided.
/// </summary>
/// <param name="mesh"></param>
public void Update(GenericMesh mesh) public void Update(GenericMesh mesh)
{ {
int pos = 0; int pos = 0;

View file

@ -14,8 +14,6 @@ namespace SM.OGL.Mesh
{ {
private bool _boundingBoxUpdated = false; private bool _boundingBoxUpdated = false;
public static int LastID { get; internal set; } = -1;
/// <inheritdoc /> /// <inheritdoc />
protected override bool AutoCompile { get; set; } = true; protected override bool AutoCompile { get; set; } = true;
@ -71,12 +69,18 @@ namespace SM.OGL.Mesh
}; };
} }
/// <summary>
/// Updates the object bounding box.
/// </summary>
public void UpdateBoundingBox() public void UpdateBoundingBox()
{ {
BoundingBox.Update(this); BoundingBox.Update(this);
_boundingBoxUpdated = true; _boundingBoxUpdated = true;
} }
/// <summary>
/// Activates the object to be rendered.
/// </summary>
public void Activate() public void Activate()
{ {
GL.BindVertexArray(ID); GL.BindVertexArray(ID);
@ -99,6 +103,7 @@ namespace SM.OGL.Mesh
GL.BindVertexArray(0); GL.BindVertexArray(0);
} }
/// <inheritdoc />
public override void Dispose() public override void Dispose()
{ {
GL.DeleteVertexArray(_id); GL.DeleteVertexArray(_id);

View file

@ -18,6 +18,12 @@
/// </summary> /// </summary>
public VBO ConnectedVBO; public VBO ConnectedVBO;
/// <summary>
/// Creates a attribute for a mesh.
/// </summary>
/// <param name="index"></param>
/// <param name="name"></param>
/// <param name="buffer"></param>
public MeshAttribute(int index, string name, VBO buffer) public MeshAttribute(int index, string name, VBO buffer)
{ {
Index = index; Index = index;

View file

@ -49,6 +49,11 @@ namespace SM.OGL.Mesh
Add(new MeshAttribute(id, name, vbo)); Add(new MeshAttribute(id, name, vbo));
} }
/// <summary>
/// Checks if the attribute list has the attribute name.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public bool Has(string name) public bool Has(string name)
{ {
VBO attribute = this[name]; VBO attribute = this[name];

View file

@ -139,6 +139,10 @@ namespace SM.OGL.Mesh
Add(vector.X, vector.Y, z, w); Add(vector.X, vector.Y, z, w);
} }
/// <summary>
/// Adds a array of vector2s.
/// </summary>
/// <param name="vectors"></param>
public void Add(params Vector2[] vectors) public void Add(params Vector2[] vectors)
{ {
foreach (Vector2 vector in vectors) foreach (Vector2 vector in vectors)
@ -163,6 +167,10 @@ namespace SM.OGL.Mesh
Add(vector.X, vector.Y, vector.Z, w); Add(vector.X, vector.Y, vector.Z, w);
} }
/// <summary>
/// Adds a array of Vector3s.
/// </summary>
/// <param name="vectors"></param>
public void Add(params Vector3[] vectors) public void Add(params Vector3[] vectors)
{ {
foreach (Vector3 vector in vectors) foreach (Vector3 vector in vectors)

View file

@ -70,6 +70,11 @@ namespace SM.OGL.Shaders
ShaderFileFiles = new ShaderFileCollection(vertex,fragment, geometry); ShaderFileFiles = new ShaderFileCollection(vertex,fragment, geometry);
} }
/// <summary>
/// Creates a shader out of a vertex and an fragment shader.
/// </summary>
/// <param name="vertex"></param>
/// <param name="fragment"></param>
protected GenericShader(string vertex, string fragment) : this(new ShaderFileCollection(vertex, fragment)){} protected GenericShader(string vertex, string fragment) : this(new ShaderFileCollection(vertex, fragment)){}
/// <inheritdoc /> /// <inheritdoc />
@ -81,6 +86,10 @@ namespace SM.OGL.Shaders
/// <inheritdoc /> /// <inheritdoc />
public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Program; public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Program;
/// <summary>
/// Updates the shader files and recompiles the shader.
/// </summary>
/// <param name="newShaderFiles"></param>
public void Update(ShaderFileCollection newShaderFiles) public void Update(ShaderFileCollection newShaderFiles)
{ {
ShaderFileFiles = newShaderFiles; ShaderFileFiles = newShaderFiles;
@ -104,6 +113,9 @@ namespace SM.OGL.Shaders
GLDebugging.CheckGLErrors($"A error occured at shader creation for '{GetType()}': %code%"); GLDebugging.CheckGLErrors($"A error occured at shader creation for '{GetType()}': %code%");
} }
/// <summary>
/// Activates the shader
/// </summary>
public void Activate() public void Activate()
{ {
GL.UseProgram(ID); GL.UseProgram(ID);
@ -115,6 +127,7 @@ namespace SM.OGL.Shaders
Load(); Load();
} }
/// <inheritdoc />
public override void Dispose() public override void Dispose()
{ {
GL.DeleteProgram(this); GL.DeleteProgram(this);
@ -136,14 +149,15 @@ namespace SM.OGL.Shaders
/// <summary> /// <summary>
/// Draws the mesh while forcing a primitive type instead of using the mesh type. /// Draws the mesh while forcing a primitive type instead of using the mesh type.
/// </summary> /// </summary>
/// <param name="modelType">The type, as what the object should be rendered.</param>
/// <param name="mesh">The mesh.</param> /// <param name="mesh">The mesh.</param>
/// <param name="amount">The amounts for instancing.</param> /// <param name="amount">The amounts for instancing.</param>
public static void DrawObject(PrimitiveType forcedType, GenericMesh mesh, int amount = 1) public static void DrawObject(PrimitiveType modelType, GenericMesh mesh, int amount = 1)
{ {
if (mesh.Indices != null) if (mesh.Indices != null)
GL.DrawElementsInstanced(forcedType, 0, DrawElementsType.UnsignedInt, mesh.Indices, amount); GL.DrawElementsInstanced(modelType, 0, DrawElementsType.UnsignedInt, mesh.Indices, amount);
else else
GL.DrawArraysInstanced(forcedType, 0, mesh.Vertex.Count / mesh.Vertex.PointerSize, amount); GL.DrawArraysInstanced(modelType, 0, mesh.Vertex.Count / mesh.Vertex.PointerSize, amount);
} }
/// <summary> /// <summary>

View file

@ -2,28 +2,51 @@
namespace SM.OGL.Shaders namespace SM.OGL.Shaders
{ {
/// <summary>
/// This class controls uniform array structures.
/// </summary>
public class UniformArray : IUniform public class UniformArray : IUniform
{ {
private Dictionary<int, Dictionary<string, Uniform>> storedUniforms = new Dictionary<int, Dictionary<string, Uniform>>(); private readonly Dictionary<int, Dictionary<string, Uniform>> storedUniforms = new Dictionary<int, Dictionary<string, Uniform>>();
internal List<string> uniformNames = new List<string>(); internal List<string> UniformNames = new List<string>();
/// <inheritdoc />
public int Location { get; internal set; } public int Location { get; internal set; }
/// <summary>
/// The name of the uniform.
/// </summary>
public string Name { get; internal set; } public string Name { get; internal set; }
/// <summary>
/// The uniform collection the uniform is from.
/// </summary>
public UniformCollection Parent { get; internal set; } public UniformCollection Parent { get; internal set; }
/// <summary>
/// The shader the uniform is from.
/// </summary>
public GenericShader ParentShader { get; internal set; } public GenericShader ParentShader { get; internal set; }
/// <summary>
/// The length of the array.
/// </summary>
public int Length => storedUniforms.Count; public int Length => storedUniforms.Count;
/// <summary>
/// Returns a dictionary to control the current index inside the array.
/// </summary>
public Dictionary<string, Uniform> this[int index] => Get(index); public Dictionary<string, Uniform> this[int index] => Get(index);
/// <summary>
/// Equivalent to <see cref="this"/>
/// <para>Returns a dictionary to control the current index inside the array.</para>
/// </summary>
public Dictionary<string, Uniform> Get(int index) public Dictionary<string, Uniform> Get(int index)
{ {
if (!storedUniforms.ContainsKey(index)) if (!storedUniforms.ContainsKey(index))
{ {
Dictionary<string, Uniform> dic = storedUniforms[index] = new Dictionary<string, Uniform>(); Dictionary<string, Uniform> dic = storedUniforms[index] = new Dictionary<string, Uniform>();
for (int i = 0; i < uniformNames.Count; i++) for (int i = 0; i < UniformNames.Count; i++)
{ {
dic.Add(uniformNames[i], new Uniform(Name + $"[{index}]." + uniformNames[i], ParentShader, Parent)); dic.Add(UniformNames[i], new Uniform(Name + $"[{index}]." + UniformNames[i], ParentShader, Parent));
} }
} }

View file

@ -8,14 +8,34 @@ using OpenTK.Graphics.OpenGL4;
namespace SM.OGL.Shaders namespace SM.OGL.Shaders
{ {
/// <summary>
/// Collects and provied the uniforms of a shader.
/// </summary>
public class UniformCollection : Dictionary<string, IUniform> public class UniformCollection : Dictionary<string, IUniform>
{ {
public int NextTexture = 0;
internal string KeyString = ""; internal string KeyString = "";
/// <summary>
/// The next uniform-position for textures.
/// </summary>
public int NextTexture = 0;
/// <summary>
/// The shader this collections is connected to.
/// </summary>
public GenericShader ParentShader { get; internal set; } public GenericShader ParentShader { get; internal set; }
/// <summary>
///
/// </summary>
/// <param name="key"></param>
public new Uniform this[string key] => Get(key); public new Uniform this[string key] => Get(key);
/// <summary>
/// Equivalent to <see cref="this"/>
/// <para>Gets the uniform with the provied key.</para>
/// <para>If it can't find it, it will create a warning and a uniform with the location of -1.</para>
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public Uniform Get(string key) public Uniform Get(string key)
{ {
try try
@ -31,18 +51,22 @@ namespace SM.OGL.Shaders
} }
} }
/// <summary>
/// Gets a array.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
/// <exception cref="KeyNotFoundException">If the key wasn't found, it will throw a exception</exception>
public UniformArray GetArray(string key) public UniformArray GetArray(string key)
{ {
try if (ContainsKey(key))
{
return (UniformArray) base[key]; return (UniformArray) base[key];
} else throw new KeyNotFoundException("UniformArray '"+key+"' wasn't found");
catch (KeyNotFoundException)
{
throw new Exception("UniformArray '"+key+"' wasn't found");
}
} }
/// <summary>
/// Adds a uniform to the collection.
/// </summary>
public void Add(string key, int location) public void Add(string key, int location)
{ {
base.Add(key, new Uniform(location, this)); base.Add(key, new Uniform(location, this));
@ -101,7 +125,7 @@ namespace SM.OGL.Shaders
} }
if (keySplits[1] == "0") if (keySplits[1] == "0")
array.uniformNames.Add(keySplits[2].Substring(1)); array.UniformNames.Add(keySplits[2].Substring(1));
} }
else else
{ {

View file

@ -8,8 +8,14 @@ using SM2D.Types;
namespace SM2D.Controls namespace SM2D.Controls
{ {
/// <summary>
/// Contains special methods for the mouse.
/// </summary>
public class Mouse2D public class Mouse2D
{ {
/// <summary>
/// Returns the current position of the mouse inside the world.
/// </summary>
public static Vector2 InWorld(Vector2 worldScale) public static Vector2 InWorld(Vector2 worldScale)
{ {
var res = worldScale; var res = worldScale;
@ -17,28 +23,63 @@ namespace SM2D.Controls
return Mouse.InScreenNormalized * res - res / 2; return Mouse.InScreenNormalized * res - res / 2;
} }
/// <summary>
/// Returns the current position of the mouse inside the world.
/// </summary>
public static Vector2 InWorld(Camera cam) public static Vector2 InWorld(Camera cam)
{ {
return InWorld(cam.WorldScale) + cam.Position; return InWorld(cam.WorldScale) + cam.Position;
} }
/// <summary>
/// Returns the current position of the mouse inside the world.
/// </summary>
public static Vector2 InWorld(Vector2 worldScale, Vector2 position) public static Vector2 InWorld(Vector2 worldScale, Vector2 position)
{ {
return InWorld(worldScale) + position; return InWorld(worldScale) + position;
} }
/// <summary>
/// Checks if the mouse is over an object.
/// </summary>
/// <param name="mousePos">The position in the world. See <see cref="InWorld(Camera)"/></param>
/// <param name="checkingObjects"></param>
/// <typeparam name="TObject"></typeparam>
public static bool MouseOver<TObject>(Vector2 mousePos, params TObject[] checkingObjects) public static bool MouseOver<TObject>(Vector2 mousePos, params TObject[] checkingObjects)
where TObject : IModelItem, ITransformItem<Transformation> where TObject : IModelItem, ITransformItem<Transformation>
=> MouseOver(mousePos, out _, checkingObjects); => MouseOver(mousePos, out _, checkingObjects);
/// <summary>
/// Checks if the mouse is over an object.
/// </summary>
/// <param name="mousePos">The position in the world. See <see cref="InWorld(Camera)"/></param>
/// <param name="checkingObjects"></param>
/// <typeparam name="TObject"></typeparam>
/// <returns></returns>
public static bool MouseOver<TObject>(Vector2 mousePos, ICollection<TObject> checkingObjects) public static bool MouseOver<TObject>(Vector2 mousePos, ICollection<TObject> checkingObjects)
where TObject : IModelItem, ITransformItem<Transformation> where TObject : IModelItem, ITransformItem<Transformation>
=> MouseOver<TObject>(mousePos, out _, checkingObjects); => MouseOver<TObject>(mousePos, out _, checkingObjects);
/// <summary>
/// Checks if the mouse is over an object and returns the object that was clicked on.
/// </summary>
/// <param name="mousePos">The position in the world. See <see cref="InWorld(Camera)"/></param>
/// <param name="clicked"></param>
/// <param name="checkingObjects"></param>
/// <typeparam name="TObject"></typeparam>
/// <returns></returns>
public static bool MouseOver<TObject>(Vector2 mousePos, out TObject clicked, params TObject[] checkingObjects) public static bool MouseOver<TObject>(Vector2 mousePos, out TObject clicked, params TObject[] checkingObjects)
where TObject : IModelItem, ITransformItem<Transformation> where TObject : IModelItem, ITransformItem<Transformation>
=> MouseOver<TObject>(mousePos, out clicked, (ICollection<TObject>)checkingObjects); => MouseOver<TObject>(mousePos, out clicked, (ICollection<TObject>)checkingObjects);
/// <summary>
/// Checks if the mouse is over an object and returns the object that was clicked on.
/// </summary>
/// <param name="mousePos">The position in the world. See <see cref="InWorld(Camera)"/></param>
/// <param name="clickedObj"></param>
/// <param name="checkingObjects"></param>
/// <typeparam name="TObject"></typeparam>
/// <returns></returns>
public static bool MouseOver<TObject>(Vector2 mousePos, out TObject clickedObj, ICollection<TObject> checkingObjects) public static bool MouseOver<TObject>(Vector2 mousePos, out TObject clickedObj, ICollection<TObject> checkingObjects)
where TObject : IModelItem, ITransformItem<Transformation> where TObject : IModelItem, ITransformItem<Transformation>
{ {
@ -70,6 +111,13 @@ namespace SM2D.Controls
return success; return success;
} }
/// <summary>
/// Checks if the mouse is over an object and returns the object that was clicked on.
/// </summary>
/// <param name="mousePos">The position in the world. See <see cref="InWorld(Camera)"/></param>
/// <param name="boundingBox"></param>
/// <param name="transform"></param>
/// <returns></returns>
public static bool MouseOver(Vector2 mousePos, BoundingBox boundingBox, Transformation transform) public static bool MouseOver(Vector2 mousePos, BoundingBox boundingBox, Transformation transform)
{ {
Matrix4 worldPos = transform.InWorldSpace; Matrix4 worldPos = transform.InWorldSpace;

View file

@ -14,14 +14,23 @@ using SM2D.Scene;
namespace SM2D.Drawing namespace SM2D.Drawing
{ {
/// <summary>
/// Allows easy access to draw something on the background.
/// </summary>
public class DrawBackground : DrawingBasis, IBackgroundItem public class DrawBackground : DrawingBasis, IBackgroundItem
{ {
/// <summary>
/// Sets the color or tint (in case a texture is set).
/// </summary>
public Color4 Color public Color4 Color
{ {
get => Material.Tint; get => Material.Tint;
set => Material.Tint = value; set => Material.Tint = value;
} }
/// <summary>
/// Sets the texture of the background.
/// </summary>
public TextureBase Texture public TextureBase Texture
{ {
get => Material.Texture; get => Material.Texture;
@ -32,18 +41,34 @@ namespace SM2D.Drawing
} }
} }
/// <summary>
/// Creates a black background.
/// </summary>
public DrawBackground() : this(Color4.Black) {} public DrawBackground() : this(Color4.Black) {}
/// <summary>
/// Creates a background with a color.
/// </summary>
/// <param name="color"></param>
public DrawBackground(Color4 color) public DrawBackground(Color4 color)
{ {
Color = color; Color = color;
} }
/// <summary>
/// Creates a background with a texture.
/// </summary>
/// <param name="texture"></param>
public DrawBackground(Bitmap texture) public DrawBackground(Bitmap texture)
{ {
Texture = (Texture) texture; Texture = (Texture) texture;
} }
/// <summary>
/// Creates a background with a texture and a tint.
/// </summary>
/// <param name="texture"></param>
/// <param name="tint"></param>
public DrawBackground(Bitmap texture, Color4 tint) public DrawBackground(Bitmap texture, Color4 tint)
{ {
Color = tint; Color = tint;
@ -51,6 +76,7 @@ namespace SM2D.Drawing
} }
/// <inheritdoc />
protected override void DrawContext(ref DrawContext context) protected override void DrawContext(ref DrawContext context)
{ {
base.DrawContext(ref context); base.DrawContext(ref context);

View file

@ -10,46 +10,72 @@ using SM2D.Types;
namespace SM2D.Drawing namespace SM2D.Drawing
{ {
/// <inheritdoc />
public class DrawObject2D : DrawingBasis<Transformation> public class DrawObject2D : DrawingBasis<Transformation>
{ {
/// <summary>
/// The texture the object should use.
/// </summary>
public Texture Texture public Texture Texture
{ {
get => (Texture) Material.Texture; get => (Texture) Material.Texture;
set => Material.Texture = value; set => Material.Texture = value;
} }
/// <summary>
/// The color or tint the object should use.
/// </summary>
public Color4 Color public Color4 Color
{ {
get => Material.Tint; get => Material.Tint;
set => Material.Tint = value; set => Material.Tint = value;
} }
/// <inheritdoc />
protected override void DrawContext(ref DrawContext context) protected override void DrawContext(ref DrawContext context)
{ {
base.DrawContext(ref context); base.DrawContext(ref context);
context.Shader.Draw(context); context.Shader.Draw(context);
} }
public void SetShader(MaterialShader shader) => Material.CustomShader = shader; /// <summary>
/// Applies a polygon to the object.
/// </summary>
/// <param name="vertices"></param>
/// <returns></returns>
public Polygon ApplyPolygon(ICollection<Vector2> vertices)
{
Polygon polygon = new Polygon(vertices);
Mesh = polygon;
return polygon;
}
public Polygon ApplyPolygon(ICollection<Vector2> vertices, bool centerUVs = false) /// <summary>
{ /// Applies a polygon to the object.
Polygon polygon = new Polygon(vertices); /// </summary>
Mesh = polygon; /// <param name="vertices"></param>
return polygon; /// <returns></returns>
} public Polygon ApplyPolygon(ICollection<PolygonVertex> vertices)
public Polygon ApplyPolygon(ICollection<PolygonVertex> vertices, bool centerUVs = false)
{ {
Polygon polygon = new Polygon(vertices); Polygon polygon = new Polygon(vertices);
Mesh = polygon; Mesh = polygon;
return polygon; return polygon;
} }
/// <summary>
/// Applies a polygon to the object.
/// </summary>
public void ApplyPolygon(Polygon polygon) public void ApplyPolygon(Polygon polygon)
{ {
Mesh = polygon; Mesh = polygon;
} }
public Polygon ApplyCircle(int segments = 32, bool centerUVs = false) /// <summary>
/// This applies a circle.
/// </summary>
/// <param name="segments"></param>
/// <returns></returns>
public Polygon ApplyCircle(int segments = 32)
{ {
Polygon pol = Polygon.GenerateCircle(segments); Polygon pol = Polygon.GenerateCircle(segments);
Mesh = pol; Mesh = pol;

View file

@ -6,14 +6,20 @@ using SM2D.Types;
namespace SM2D.Drawing namespace SM2D.Drawing
{ {
/// <summary>
/// Creates particles.
/// </summary>
public class DrawParticles : ParticleDrawingBasis<Transformation, Vector2> public class DrawParticles : ParticleDrawingBasis<Transformation, Vector2>
{ {
/// <inheritdoc />
public override Func<Vector2, ParticleContext, Vector2> MovementCalculation { get; set; } = ParticleMovement.Default2D; public override Func<Vector2, ParticleContext, Vector2> MovementCalculation { get; set; } = ParticleMovement.Default2D;
/// <inheritdoc />
public DrawParticles(TimeSpan duration) : base(duration) public DrawParticles(TimeSpan duration) : base(duration)
{ {
} }
/// <inheritdoc />
protected override ParticleStruct<Vector2> CreateObject(int index) protected override ParticleStruct<Vector2> CreateObject(int index)
{ {
return new ParticleStruct<Vector2>() return new ParticleStruct<Vector2>()
@ -24,6 +30,7 @@ namespace SM2D.Drawing
}; };
} }
/// <inheritdoc />
protected override Matrix4 CreateMatrix(ParticleStruct<Vector2> Struct, Vector2 direction) protected override Matrix4 CreateMatrix(ParticleStruct<Vector2> Struct, Vector2 direction)
{ {
return Struct.Matrix * Matrix4.CreateTranslation(direction.X, direction.Y, 0); return Struct.Matrix * Matrix4.CreateTranslation(direction.X, direction.Y, 0);

View file

@ -9,14 +9,21 @@ using SM2D.Types;
namespace SM2D.Drawing namespace SM2D.Drawing
{ {
/// <summary>
/// Draws a text to the world.
/// </summary>
public class DrawText : TextDrawingBasis<Transformation> public class DrawText : TextDrawingBasis<Transformation>
{ {
/// <summary>
/// Creates a text object.
/// </summary>
public DrawText(Font font, string text) : base(font) public DrawText(Font font, string text) : base(font)
{ {
_text = text; _text = text;
Transform.Size = new CVector2(1); Transform.Size = new CVector2(1);
} }
/// <inheritdoc />
protected override void DrawContext(ref DrawContext context) protected override void DrawContext(ref DrawContext context)
{ {
base.DrawContext(ref context); base.DrawContext(ref context);

View file

@ -5,15 +5,36 @@ using SM.OGL.Mesh;
namespace SM2D.Object namespace SM2D.Object
{ {
/// <summary>
/// Allows different type of lines.
/// </summary>
public enum PolyLineType public enum PolyLineType
{ {
/// <summary>
/// Those lines are not connected to each other.
/// <para>Every two points starts a new line.</para>
/// </summary>
NotConnected = 1, NotConnected = 1,
/// <summary>
/// Those lines are connected with each other, but don't connect the start and the end.
/// </summary>
Connected = 3, Connected = 3,
/// <summary>
/// Those lines are connected and they connect start and end.
/// </summary>
ConnectedLoop = 2 ConnectedLoop = 2
} }
/// <summary>
/// Creates new poly line.
/// </summary>
public class PolyLine : Polygon, ILineMesh public class PolyLine : Polygon, ILineMesh
{ {
/// <summary>
/// Creates a new polyline by using <see cref="Vector2"/>.
/// </summary>
/// <param name="vertices"></param>
/// <param name="lineType"></param>
public PolyLine(ICollection<Vector2> vertices, PolyLineType lineType = PolyLineType.NotConnected) : base(vertices) public PolyLine(ICollection<Vector2> vertices, PolyLineType lineType = PolyLineType.NotConnected) : base(vertices)
{ {
UVs.Active = false; UVs.Active = false;
@ -21,6 +42,11 @@ namespace SM2D.Object
PrimitiveType = (PrimitiveType)lineType; PrimitiveType = (PrimitiveType)lineType;
} }
/// <summary>
/// Creates a new polyline by using <see cref="PolygonVertex"/>.
/// </summary>
/// <param name="vertices"></param>
/// <param name="lineType"></param>
public PolyLine(ICollection<PolygonVertex> vertices, PolyLineType lineType = PolyLineType.NotConnected) : base(vertices) public PolyLine(ICollection<PolygonVertex> vertices, PolyLineType lineType = PolyLineType.NotConnected) : base(vertices)
{ {
UVs.Active = false; UVs.Active = false;

View file

@ -11,8 +11,27 @@ using SM.OGL.Mesh;
namespace SM2D.Object namespace SM2D.Object
{ {
/// <summary>
/// Creates a polygon.
/// </summary>
public class Polygon : Mesh public class Polygon : Mesh
{ {
/// <inheritdoc />
public override VBO Vertex { get; protected set; } = new VBO();
/// <inheritdoc />
public override VBO UVs { get; protected set; } = new VBO(pointerSize: 2);
/// <inheritdoc />
public override VBO Color { get; protected set; } = new VBO(pointerSize: 4);
/// <inheritdoc />
public override PrimitiveType PrimitiveType { get; protected set; } = PrimitiveType.TriangleFan;
/// <summary>
/// Creates a polygon with <see cref="Vector2"/>s.
/// </summary>
/// <param name="vertices"></param>
public Polygon(ICollection<Vector2> vertices) : base(PrimitiveType.TriangleFan) public Polygon(ICollection<Vector2> vertices) : base(PrimitiveType.TriangleFan)
{ {
Color.Active = false; Color.Active = false;
@ -27,25 +46,23 @@ namespace SM2D.Object
if (UVs.Active) foreach (var vertex in vertices) AddUV(vertex); if (UVs.Active) foreach (var vertex in vertices) AddUV(vertex);
} }
/// <summary>
/// Creates a polygon with <see cref="PolygonVertex"/>, what allows colors hard coded.
/// </summary>
/// <param name="vertices"></param>
public Polygon(ICollection<PolygonVertex> vertices) : base(PrimitiveType.TriangleFan) public Polygon(ICollection<PolygonVertex> vertices) : base(PrimitiveType.TriangleFan)
{ {
foreach (var polygonVertex in vertices) foreach (var polygonVertex in vertices)
{ {
Color.Add(polygonVertex.Color); Color.Add(polygonVertex.Color);
Vertex.Add(polygonVertex.Vertex, 0); Vertex.Add(polygonVertex.Position, 0);
} }
UpdateBoundingBox(); UpdateBoundingBox();
if (UVs.Active) foreach (var vertex in vertices) AddUV(vertex.Vertex); if (UVs.Active) foreach (var vertex in vertices) AddUV(vertex.Position);
} }
public override VBO Vertex { get; protected set; } = new VBO();
public override VBO UVs { get; protected set; } = new VBO(pointerSize: 2);
public override VBO Color { get; protected set; } = new VBO(pointerSize: 4);
public override PrimitiveType PrimitiveType { get; protected set; } = PrimitiveType.TriangleFan;
private void AddUV(Vector2 vertex) private void AddUV(Vector2 vertex)
{ {
var uv = Vector2.Divide(vertex - BoundingBox.Min.Xy, BoundingBox.Max.Xy - BoundingBox.Min.Xy); var uv = Vector2.Divide(vertex - BoundingBox.Min.Xy, BoundingBox.Max.Xy - BoundingBox.Min.Xy);
@ -53,6 +70,11 @@ namespace SM2D.Object
UVs.Add(uv); UVs.Add(uv);
} }
/// <summary>
/// Creates a circle.
/// </summary>
/// <param name="secments"></param>
/// <returns></returns>
public static Polygon GenerateCircle(int secments = 32) public static Polygon GenerateCircle(int secments = 32)
{ {
var vertices = new List<Vector2> {Vector2.Zero}; var vertices = new List<Vector2> {Vector2.Zero};

View file

@ -7,17 +7,36 @@ using OpenTK.Graphics;
namespace SM2D.Object namespace SM2D.Object
{ {
/// <summary>
/// Allows storing more information inside a vertex.
/// </summary>
public struct PolygonVertex public struct PolygonVertex
{ {
public Vector2 Vertex; /// <summary>
/// The position in the polygon.
/// </summary>
public Vector2 Position;
/// <summary>
/// The color of the vertex.
/// </summary>
public Color4 Color; public Color4 Color;
public PolygonVertex(Vector2 vertex = default, Color4 color = default) /// <summary>
/// Creates a polygon vertex.
/// </summary>
/// <param name="position"></param>
/// <param name="color"></param>
public PolygonVertex(Vector2 position = default, Color4 color = default)
{ {
Vertex = vertex; Position = position;
Color = color; Color = color;
} }
/// <summary>
/// Automaticly translates Vector2s to PolygonVertex
/// </summary>
/// <param name="vec"></param>
/// <returns></returns>
public static implicit operator PolygonVertex(Vector2 vec) => new PolygonVertex(vec, Color4.White); public static implicit operator PolygonVertex(Vector2 vec) => new PolygonVertex(vec, Color4.White);
} }
} }

View file

@ -4,13 +4,22 @@ using SM2D.Shader;
namespace SM2D.Pipelines namespace SM2D.Pipelines
{ {
/// <summary>
/// This implements the most basic render pipeline.
/// </summary>
public class Basic2DPipeline : RenderPipeline public class Basic2DPipeline : RenderPipeline
{ {
/// <summary>
/// The access to the pipeline.
/// </summary>
public static Basic2DPipeline Pipeline = new Basic2DPipeline(); public static Basic2DPipeline Pipeline = new Basic2DPipeline();
/// <inheritdoc />
public override MaterialShader DefaultShader { get; protected set; } = ShaderCollection.Instanced; public override MaterialShader DefaultShader { get; protected set; } = ShaderCollection.Instanced;
private Basic2DPipeline() {}
/// <inheritdoc />
protected override void RenderProcess(ref DrawContext context) protected override void RenderProcess(ref DrawContext context)
{ {
context.Scene?.Draw(context); context.Scene?.Draw(context);

View file

@ -8,7 +8,7 @@
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SM2D</RootNamespace> <RootNamespace>SM2D</RootNamespace>
<AssemblyName>SM2D</AssemblyName> <AssemblyName>SMRenderer2D</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic> <Deterministic>true</Deterministic>
@ -21,6 +21,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\SMRenderer2D.xml</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
@ -47,13 +48,11 @@
<Compile Include="Pipelines\Basic2DPipeline.cs" /> <Compile Include="Pipelines\Basic2DPipeline.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Scene\Camera.cs" /> <Compile Include="Scene\Camera.cs" />
<Compile Include="Scene\I2DShowItem.cs" />
<Compile Include="Scene\ItemCollection.cs" /> <Compile Include="Scene\ItemCollection.cs" />
<Compile Include="Scene\Scene.cs" /> <Compile Include="Scene\Scene.cs" />
<Compile Include="Shader\ShaderCollection.cs" /> <Compile Include="Shader\ShaderCollection.cs" />
<Compile Include="Types\Transformation.cs" /> <Compile Include="Types\Transformation.cs" />
<Compile Include="Window\Window2DSetup.cs" /> <Compile Include="Window\Window2DSetup.cs" />
<Compile Include="Window\I2DSetup.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\SM.Base\SM.Base.csproj"> <ProjectReference Include="..\SM.Base\SM.Base.csproj">
@ -69,9 +68,6 @@
<PackageReference Include="OpenTK"> <PackageReference Include="OpenTK">
<Version>3.3.1</Version> <Version>3.3.1</Version>
</PackageReference> </PackageReference>
<PackageReference Include="OpenTK.GLWpfControl">
<Version>3.2.3</Version>
</PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Shader\ShaderFiles\basic.glsl" /> <EmbeddedResource Include="Shader\ShaderFiles\basic.glsl" />

View file

@ -10,6 +10,7 @@ using SM.Base.Window;
namespace SM2D.Scene namespace SM2D.Scene
{ {
/// <inheritdoc />
public class Camera : GenericCamera public class Camera : GenericCamera
{ {
internal static int ResizeCounter = 0; internal static int ResizeCounter = 0;
@ -19,6 +20,14 @@ namespace SM2D.Scene
private bool _updateWorldScale = false; private bool _updateWorldScale = false;
private Vector2? _requestedWorldScale = null; private Vector2? _requestedWorldScale = null;
/// <summary>
/// This vector allows to request a world scale.
/// <para>Following cases are possible. ("not set" means 0)</para>
/// <para>None is set: It takes the window size.</para>
/// <para>X is set: Y get calculated by the aspect ratio of the window.</para>
/// <para>Y is set: X get calculated by the aspect ratio of the window.</para>
/// <para>Both are set: Now the system try to keep a (invisible) rectangle in view, by increasing the width or height of the view, if needed.</para>
/// </summary>
public Vector2? RequestedWorldScale public Vector2? RequestedWorldScale
{ {
get => _requestedWorldScale; get => _requestedWorldScale;
@ -29,18 +38,32 @@ namespace SM2D.Scene
} }
} }
/// <summary>
/// The world scale that got calculated.
/// </summary>
public Vector2 WorldScale { get; private set; } = Vector2.Zero; public Vector2 WorldScale { get; private set; } = Vector2.Zero;
/// <summary>
/// A event that gets triggered, when the world scale changed.
/// <para>Possible causes: Window resizes, <see cref="RequestedWorldScale"/> changed</para>
/// </summary>
public event Action<Camera> WorldScaleChanged; public event Action<Camera> WorldScaleChanged;
/// <summary>
/// The position of the camera.
/// </summary>
public CVector2 Position = new CVector2(0); public CVector2 Position = new CVector2(0);
/// <inheritdoc />
public override bool Orthographic { get; } = true; public override bool Orthographic { get; } = true;
/// <inheritdoc />
protected override Matrix4 ViewCalculation(IGenericWindow window) protected override Matrix4 ViewCalculation(IGenericWindow window)
{ {
return Matrix4.LookAt(Position.X, Position.Y, Distance, Position.X, Position.Y, 0f, 0, 1, 0); return Matrix4.LookAt(Position.X, Position.Y, Distance, Position.X, Position.Y, 0f, 0, 1, 0);
} }
/// <inheritdoc />
protected override bool WorldCalculation(IGenericWindow window, out Matrix4 world) protected override bool WorldCalculation(IGenericWindow window, out Matrix4 world)
{ {
world = Matrix4.Identity; world = Matrix4.Identity;
@ -57,6 +80,11 @@ namespace SM2D.Scene
return false; return false;
} }
/// <summary>
/// This calculates the world scale.
/// <para>Usually gets called, by the camera itself, but if you need the world scale for additional calculations, you can execute it by yourself.</para>
/// </summary>
/// <param name="window"></param>
public void CalculateWorldScale(IGenericWindow window) public void CalculateWorldScale(IGenericWindow window)
{ {
if (RequestedWorldScale.HasValue) if (RequestedWorldScale.HasValue)

View file

@ -1,13 +0,0 @@
#region usings
using SM.Base.Scene;
#endregion
namespace SM2D.Scene
{
public interface I2DShowItem : IShowItem
{
int ZIndex { get; set; }
}
}

View file

@ -2,23 +2,19 @@
using SM.Base.Scene; using SM.Base.Scene;
using SM.Base.Types; using SM.Base.Types;
using SM.Base.Window;
using SM2D.Types; using SM2D.Types;
#endregion #endregion
namespace SM2D.Scene namespace SM2D.Scene
{ {
/// <inheritdoc />
public class ItemCollection : GenericItemCollection<Transformation> public class ItemCollection : GenericItemCollection<Transformation>
{ {
/// <inheritdoc />
public ItemCollection() public ItemCollection()
{ {
Transform.Size = new CVector2(1); Transform.Size = new CVector2(1);
} }
public override void Draw(DrawContext context)
{
base.Draw(context);
}
} }
} }

View file

@ -11,17 +11,25 @@ using SM2D.Drawing;
namespace SM2D.Scene namespace SM2D.Scene
{ {
/// <summary>
/// The scene allows connecting different objects to render together.
/// </summary>
public class Scene : GenericScene<Camera, ItemCollection> public class Scene : GenericScene<Camera, ItemCollection>
{ {
private static DrawObject2D _axisHelper; private static readonly DrawObject2D _axisHelper;
/// <summary>
/// This determent how large the axishelper should be.
/// </summary>
public float AxisHelperSize = 100; public float AxisHelperSize = 100;
static Scene() static Scene()
{ {
_axisHelper = new DrawObject2D(); _axisHelper = new DrawObject2D {Mesh = AxisHelper.Object};
_axisHelper.Mesh = AxisHelper.Object;
} }
/// <summary>
/// This creates a new scene.
/// </summary>
public Scene() public Scene()
{ {
_Background = new DrawBackground(Color4.Black); _Background = new DrawBackground(Color4.Black);
@ -32,12 +40,16 @@ namespace SM2D.Scene
} }
/// <summary>
/// Gets/Sets the background.
/// </summary>
public DrawBackground Background public DrawBackground Background
{ {
get => (DrawBackground) _Background; get => (DrawBackground) _Background;
set => _Background = value; set => _Background = value;
} }
/// <inheritdoc />
public override void DrawHUD(DrawContext context) public override void DrawHUD(DrawContext context)
{ {
context.ModelMatrix *= Matrix4.CreateTranslation(0,0,1); context.ModelMatrix *= Matrix4.CreateTranslation(0,0,1);
@ -45,6 +57,7 @@ namespace SM2D.Scene
base.DrawHUD(context); base.DrawHUD(context);
} }
/// <inheritdoc />
public override void DrawDebug(DrawContext context) public override void DrawDebug(DrawContext context)
{ {
if (ShowAxisHelper) if (ShowAxisHelper)

View file

@ -5,9 +5,15 @@ using SM.OGL.Shaders;
namespace SM2D.Shader namespace SM2D.Shader
{ {
public class ShaderCollection class ShaderCollection
{ {
/// <summary>
/// The most basic shader, that renders only one thing and only allows colors and one texture.
/// </summary>
public static SimpleShader Basic = new SimpleShader("basic", AssemblyUtility.ReadAssemblyFile("SM2D.Shader.ShaderFiles.basic.glsl"), SetUniforms); public static SimpleShader Basic = new SimpleShader("basic", AssemblyUtility.ReadAssemblyFile("SM2D.Shader.ShaderFiles.basic.glsl"), SetUniforms);
/// <summary>
/// The same fragment shader as <see cref="Basic"/>, but allows to be instanced and used in (f.E.) text.
/// </summary>
public static SimpleShader Instanced = new SimpleShader("instanced", AssemblyUtility.ReadAssemblyFile("SM2D.Shader.ShaderFiles.basic.glsl"), SetUniforms); public static SimpleShader Instanced = new SimpleShader("instanced", AssemblyUtility.ReadAssemblyFile("SM2D.Shader.ShaderFiles.basic.glsl"), SetUniforms);
static void SetUniforms(UniformCollection uniforms, DrawContext context) static void SetUniforms(UniformCollection uniforms, DrawContext context)

View file

@ -11,5 +11,4 @@ layout(location = 0) out vec4 color;
void main() { void main() {
color = v_Color * Tint; color = v_Color * Tint;
if (UseTexture) color *= texture(Texture, v_TexCoords); if (UseTexture) color *= texture(Texture, v_TexCoords);
color *= 1.2;
} }

View file

@ -10,22 +10,46 @@ using SM.Base.Utility;
namespace SM2D.Types namespace SM2D.Types
{ {
/// <inheritdoc />
public class Transformation : GenericTransformation public class Transformation : GenericTransformation
{ {
public static int ZIndexPercision = 300; /// <summary>
/// The precision of the Z-Index.
/// <para>High values can result into "z-fighting" and cliping.</para>
/// </summary>
public static int ZIndexPercision = 100;
/// <summary>
/// The transformations translation.
/// </summary>
public CVector2 Position { get; set; } = new CVector2(0); public CVector2 Position { get; set; } = new CVector2(0);
/// <summary>
/// The scaling.
/// </summary>
public CVector2 Size { get; set; } = new CVector2(50); public CVector2 Size { get; set; } = new CVector2(50);
/// <summary>
/// The rotation.
/// </summary>
public CVector1 Rotation { get; set; } = new CVector1(0); public CVector1 Rotation { get; set; } = new CVector1(0);
/// <summary>
/// If true, the object get rotated on the X-Axis by 180°.
/// </summary>
public bool HorizontalFlip { get; set; } = false; public bool HorizontalFlip { get; set; } = false;
/// <summary>
/// If true, the object get rotated on the Y-Axis by 180°.
/// </summary>
public bool VerticalFlip { get; set; } = false; public bool VerticalFlip { get; set; } = false;
/// <summary>
/// The ZIndex.
/// </summary>
public CVector1 ZIndex { get; set; } = new CVector1(0); public CVector1 ZIndex { get; set; } = new CVector1(0);
/// <inheritdoc />
protected override Matrix4 RequestMatrix() protected override Matrix4 RequestMatrix()
{ {
float z = 1 / (float) ZIndexPercision * ZIndex; float z = 1 / (float) ZIndexPercision * ZIndex;
@ -37,11 +61,18 @@ namespace SM2D.Types
Matrix4.CreateTranslation(Position.X, Position.Y, z); Matrix4.CreateTranslation(Position.X, Position.Y, z);
} }
public void TurnTo(Vector2 v) /// <summary>
/// Rotates the object, so it SHOULD turn toward the position.
/// </summary>
public void TurnTo(Vector2 turnposition)
{ {
Rotation.Set(RotationUtility.TurnTowards(Position, v)); Rotation.Set(RotationUtility.TurnTowards(Position, turnposition));
} }
/// <summary>
/// Returns the vector the object is looking.
/// </summary>
/// <returns></returns>
public Vector2 LookAtVector() public Vector2 LookAtVector()
{ {
if (_modelMatrix.Determinant < 0.0001) return new Vector2(0); if (_modelMatrix.Determinant < 0.0001) return new Vector2(0);
@ -51,11 +82,20 @@ namespace SM2D.Types
return vec.Xy; return vec.Xy;
} }
/// <summary>
/// The object scale gets set to the same as the resolution of the texture.
/// </summary>
/// <param name="texture"></param>
public void ApplyTextureSize(Texture texture) public void ApplyTextureSize(Texture texture)
{ {
Size.Set(texture.Width, texture.Height); Size.Set(texture.Width, texture.Height);
} }
/// <summary>
/// The object scale gets set to the same aspect ratio as the texture and then it will set the width..
/// </summary>
/// <param name="texture"></param>
/// <param name="width"></param>
public void ApplyTextureSize(Texture texture, float width) public void ApplyTextureSize(Texture texture, float width)
{ {
Size.Set(width, width / texture.Aspect); Size.Set(width, width / texture.Aspect);

View file

@ -1,10 +0,0 @@
using OpenTK;
using SM.Base.Window;
namespace SM2D
{
public interface I2DSetup : ISetup
{
Vector2? WorldScale { get; set; }
}
}

View file

@ -7,10 +7,12 @@ using SM2D.Shader;
namespace SM2D namespace SM2D
{ {
public struct Window2DSetup : I2DSetup /// <summary>
/// Sets up a 2D window.
/// </summary>
public struct Window2DSetup : ISetup
{ {
public Vector2? WorldScale { get; set; } /// <inheritdoc />
public void Applied(IGenericWindow window) public void Applied(IGenericWindow window)
{ {
window.ViewportCamera = new Camera(); window.ViewportCamera = new Camera();
@ -18,16 +20,18 @@ namespace SM2D
SMRenderer.DefaultMaterialShader = ShaderCollection.Instanced; SMRenderer.DefaultMaterialShader = ShaderCollection.Instanced;
} }
/// <inheritdoc />
public void Load(IGenericWindow window) public void Load(IGenericWindow window)
{ {
(window.ViewportCamera as Camera).RequestedWorldScale = WorldScale;
GL.Enable(EnableCap.DepthTest); GL.Enable(EnableCap.DepthTest);
} }
/// <inheritdoc />
public void Loaded(IGenericWindow window) public void Loaded(IGenericWindow window)
{ {
} }
/// <inheritdoc />
public void Resize(IGenericWindow window) public void Resize(IGenericWindow window)
{ {
Camera.ResizeCounter++; Camera.ResizeCounter++;

View file

@ -21,13 +21,13 @@ namespace SM_TEST
{ {
font = new Font(@"C:\Windows\Fonts\Arial.ttf") font = new Font(@"C:\Windows\Fonts\Arial.ttf")
{ {
FontSize = 32 FontSize = 16
}; };
Log.SetLogFile(compressionFolder:"logs"); //Log.SetLogFile(compressionFolder:"logs");
window = new GLWindow {VSync = VSyncMode.Off}; window = new GLWindow {VSync = VSyncMode.Off};
window.ApplySetup(new Window2DSetup() {WorldScale = new Vector2(0,1000)}); window.ApplySetup(new Window2DSetup());
window.SetRenderPipeline(new TestRenderPipeline()); window.SetRenderPipeline(new TestRenderPipeline());
window.SetScene(scene = new Scene()); window.SetScene(scene = new Scene());
window.RunFixedUpdate(60); window.RunFixedUpdate(60);
@ -36,15 +36,8 @@ namespace SM_TEST
window.Run(); window.Run();
} }
private static DrawParticles particles;
private static void WindowOnUpdateFrame(object sender, FrameEventArgs e) private static void WindowOnUpdateFrame(object sender, FrameEventArgs e)
{ {
if (Keyboard.GetState()[Key.R])
particles.Trigger();
//particles.Paused = Keyboard.GetState()[Key.P];
GameControllerState s1 = new GameController(0).GetState();
GameControllerState s2 = new GameController(1).GetState();
} }
private static void WindowOnLoad(IGenericWindow window) private static void WindowOnLoad(IGenericWindow window)

View file

@ -13,11 +13,11 @@ namespace SM_TEST
public override void Initialization() public override void Initialization()
{ {
MainFramebuffer = CreateWindowFramebuffer(16); MainFramebuffer = CreateWindowFramebuffer(0);
_postBuffer = CreateWindowFramebuffer(); _postBuffer = CreateWindowFramebuffer();
Framebuffers.Add(_postBuffer); Framebuffers.Add(_postBuffer);
_bloom = new BloomEffect(MainFramebuffer, hdr: true, .5f) _bloom = new BloomEffect(MainFramebuffer, hdr: true, .75f)
{ {
Threshold = .5f, Threshold = .5f,
}; };