mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Replaced IntX by intX, Basic AssetViewer (can view Textures, kind of)
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
Texture2DArray Texture : register(t0);
|
||||
SamplerState Sampler : register(s0);
|
||||
|
||||
Texture2DArray<int4> IntTexture : register(t1);
|
||||
SamplerState IntSampler : register(s1);
|
||||
|
||||
Texture2DArray<uint4> UIntTexture : register(t2);
|
||||
SamplerState UIntSampler : register(s2);
|
||||
|
||||
#define SWIZZLE_NONE 0
|
||||
#define SWIZZLE_R 1
|
||||
#define SWIZZLE_G 2
|
||||
#define SWIZZLE_B 3
|
||||
#define SWIZZLE_A 4
|
||||
|
||||
cbuffer Constants
|
||||
{
|
||||
float ColorOffset = 0.5;
|
||||
float AlphaOffset = 0.0;
|
||||
float ColorScale = 0.5;
|
||||
float AlphaScale = 1.0;
|
||||
|
||||
float MipLevel = 0.0;
|
||||
float ArraySlice = 0.0;
|
||||
|
||||
// 0: Float | 1: Int | 2: Uint
|
||||
int Mode = 0;
|
||||
|
||||
int4 Swizzle = int4(SWIZZLE_R, SWIZZLE_G, SWIZZLE_B, SWIZZLE_A);
|
||||
|
||||
float2 Texels;
|
||||
|
||||
float4x4 WorldViewProjection;
|
||||
}
|
||||
|
||||
struct VS_Input
|
||||
{
|
||||
float2 Position : POSITION;
|
||||
float2 Texcoord : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct PS_Input
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
float2 Texcoord : TEXCOORD0;
|
||||
};
|
||||
|
||||
PS_Input VS(VS_Input input)
|
||||
{
|
||||
PS_Input output;
|
||||
|
||||
output.Position = mul(WorldViewProjection, float4(input.Position, 0.0f, 1.0f));
|
||||
output.Texcoord = input.Texcoord;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void SwizzleColor(int swizzleMode, float4 colorToSwizzle, inout float output)
|
||||
{
|
||||
switch (swizzleMode)
|
||||
{
|
||||
case SWIZZLE_R:
|
||||
output = colorToSwizzle.r;
|
||||
break;
|
||||
case SWIZZLE_G:
|
||||
output = colorToSwizzle.g;
|
||||
break;
|
||||
case SWIZZLE_B:
|
||||
output = colorToSwizzle.b;
|
||||
break;
|
||||
case SWIZZLE_A:
|
||||
output = colorToSwizzle.a;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float4 PS(PS_Input input) : SV_Target0
|
||||
{
|
||||
float4 outputColor;
|
||||
|
||||
if (Mode == 0)
|
||||
{
|
||||
//float4 color = Texture.SampleLevel(Sampler, float3(input.Texcoord, ArraySlice), MipLevel);
|
||||
// Quasi next neighbor
|
||||
float4 color = Texture.Load(int4(input.Texcoord * Texels, ArraySlice, MipLevel));
|
||||
outputColor = float4(ColorOffset.xxx, AlphaOffset) + color * float4(ColorScale.xxx, AlphaScale);
|
||||
}
|
||||
else if (Mode == 1)
|
||||
{
|
||||
int4 color = IntTexture.Load(int4(input.Texcoord * Texels, ArraySlice, MipLevel));
|
||||
outputColor = float4(ColorOffset.xxx, AlphaOffset) + color * float4(ColorScale.xxx, AlphaScale);
|
||||
}
|
||||
else if (Mode == 2)
|
||||
{
|
||||
uint4 color = UIntTexture.Load(int4(input.Texcoord * Texels, ArraySlice, MipLevel));
|
||||
outputColor = float4(ColorOffset.xxx, AlphaOffset) + color * float4(ColorScale.xxx, AlphaScale);
|
||||
}
|
||||
|
||||
float4 swizzledOutput = float4(0, 0, 0, 1);
|
||||
|
||||
SwizzleColor(Swizzle.r, outputColor, swizzledOutput.r);
|
||||
SwizzleColor(Swizzle.g, outputColor, swizzledOutput.g);
|
||||
SwizzleColor(Swizzle.b, outputColor, swizzledOutput.b);
|
||||
SwizzleColor(Swizzle.a, outputColor, swizzledOutput.a);
|
||||
|
||||
return swizzledOutput;
|
||||
}
|
||||
|
||||
#pragma Effect[VS=VS; PS=PS]
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
AssetLoader = "EffectAssetLoader",
|
||||
Config = (GlitchyEditor.Assets.EffectAssetLoaderConfig){}/* No reflection data for GlitchyEditor.Assets.EffectAssetLoaderConfig. Add [BonTarget] or force it */
|
||||
}
|
||||
@@ -430,9 +430,13 @@ static class DdsImporter
|
||||
|
||||
switch (textureInfo.PixelFormat)
|
||||
{
|
||||
case .BC1_UNorm, .BC1_UNorm_SRGB, .BC4_UNorm:
|
||||
case .BC1_UNorm, .BC1_UNorm_SRGB, .BC1_Typeless,
|
||||
.BC4_UNorm, .BC4_SNorm, .BC4_Typeless:
|
||||
blockSize = 8;
|
||||
case .BC2_UNorm, .BC2_UNorm_SRGB, .BC3_UNorm, .BC3_UNorm_SRGB, .BC5_UNorm:
|
||||
case .BC2_UNorm, .BC2_UNorm_SRGB, .BC2_Typeless,
|
||||
.BC3_UNorm, .BC3_UNorm_SRGB, .BC3_Typeless,
|
||||
.BC5_UNorm, .BC5_SNorm, .BC5_Typeless,
|
||||
.BC7_UNorm, .BC7_UNorm_SRGB, .BC7_Typeless:
|
||||
blockSize = 16;
|
||||
default:
|
||||
}
|
||||
|
||||
@@ -233,14 +233,22 @@ class MaterialAssetLoaderConfig : AssetLoaderConfig
|
||||
[BonTarget]
|
||||
public enum VariableValue
|
||||
{
|
||||
case bool(bool Value);
|
||||
case bool2(bool2 Value);
|
||||
case bool3(bool3 Value);
|
||||
case bool4(bool4 Value);
|
||||
case int(int Value);
|
||||
case int2(int2 Value);
|
||||
case int3(int3 Value);
|
||||
case int4(int4 Value);
|
||||
case uint(uint Value);
|
||||
case uint2(uint2 Value);
|
||||
case uint3(uint3 Value);
|
||||
case uint4(uint4 Value);
|
||||
case Float(float Value);
|
||||
case Float2(float2 Value);
|
||||
case Float3(float3 Value);
|
||||
case Float4(float4 Value);
|
||||
case Int(int Value);
|
||||
case Int2(Int2 Value);
|
||||
case Int3(Int3 Value);
|
||||
case Int4(Int4 Value);
|
||||
case ColorRGB(ColorRGB Value);
|
||||
case ColorRGBA(ColorRGBA Value);
|
||||
case None;
|
||||
|
||||
@@ -0,0 +1,663 @@
|
||||
using ImGui;
|
||||
using System;
|
||||
using GlitchyEngine.Content;
|
||||
using GlitchyEngine.Renderer;
|
||||
using GlitchyEngine.Math;
|
||||
using GlitchyEngine;
|
||||
namespace GlitchyEditor.EditWindows;
|
||||
|
||||
class AssetViewer : EditorWindow
|
||||
{
|
||||
public const String s_WindowTitle = "Asset Viewer";
|
||||
|
||||
public EditorContentManager _manager;
|
||||
|
||||
private AssetHandle _selectedAsset;
|
||||
|
||||
append TexturererViewerer _textureViewer = .();
|
||||
|
||||
public this(EditorContentManager contentManager)
|
||||
{
|
||||
_manager = contentManager;
|
||||
}
|
||||
|
||||
protected override void InternalShow()
|
||||
{
|
||||
if(!ImGui.Begin(s_WindowTitle, &_open, .None))
|
||||
{
|
||||
ImGui.End();
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui.PushStyleVar(.CellPadding, .(0, 0));
|
||||
|
||||
bool alt_pressed = ImGui.GetIO().KeyAlt;
|
||||
|
||||
if (ImGui.BeginTable("AssetViewerTable", 2, .BordersInnerV | .Resizable | .Reorderable | .NoPadOuterX))
|
||||
{
|
||||
if (alt_pressed)
|
||||
{
|
||||
// Header anzeigen, damit sie neu angeordnet werden können
|
||||
ImGui.TableSetupColumn("Assets");
|
||||
ImGui.TableSetupColumn("Viewer");
|
||||
ImGui.TableHeadersRow();
|
||||
}
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
|
||||
if (ImGui.BeginChild("Assets"))
|
||||
{
|
||||
DrawAssetList();
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
if (ImGui.BeginChild("Files"))
|
||||
{
|
||||
DrawAssetViewer();
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
|
||||
ImGui.EndTable();
|
||||
}
|
||||
|
||||
ImGui.PopStyleVar(1);
|
||||
|
||||
ImGui.End();
|
||||
}
|
||||
|
||||
void DrawAssetList()
|
||||
{
|
||||
for (let (handle, asset) in _manager.[Friend]_handleToAsset)
|
||||
{
|
||||
// TODO: gucken, was der Typ ist
|
||||
|
||||
String name = scope String();
|
||||
|
||||
if (asset.Identifier.IsWhiteSpace)
|
||||
name.Append("Unnamed");
|
||||
else
|
||||
name.Append(asset.Identifier);
|
||||
|
||||
name.Append(" (");
|
||||
asset.GetType().GetName(name);
|
||||
name.Append(") [");
|
||||
name.AppendF($"{handle.ID}]");
|
||||
|
||||
name.TrimStart();
|
||||
|
||||
ImGui.TreeNodeFlags flags = .Leaf;
|
||||
|
||||
if(handle == _selectedAsset)
|
||||
flags |= .Selected;
|
||||
|
||||
if (ImGui.TreeNodeEx(name, flags, name))
|
||||
{
|
||||
if (ImGui.IsItemClicked(.Left))
|
||||
_selectedAsset = handle;
|
||||
|
||||
ImGui.TreePop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawAssetViewer()
|
||||
{
|
||||
if (_selectedAsset.IsInvalid)
|
||||
{
|
||||
ImGui.Text("Select an asset to view it.");
|
||||
return;
|
||||
}
|
||||
|
||||
Asset asset = _selectedAsset.Get<Asset>();
|
||||
|
||||
/*if (!asset.Complete)
|
||||
{
|
||||
ImGui.Text("Loading asset...");
|
||||
return;
|
||||
}*/
|
||||
|
||||
/*switch (asset.GetType())
|
||||
{
|
||||
case typeof(RenderTargetGroup):
|
||||
DrawRenderTargetGroupViewer((RenderTargetGroup)asset);
|
||||
case typeof(Texture):
|
||||
_textureViewer.ViewTexture((Texture)asset);
|
||||
|
||||
}*/
|
||||
|
||||
if (var texture = asset as Texture)
|
||||
_textureViewer.ViewTexture(texture);
|
||||
if (var texture = asset as RenderTargetGroup)
|
||||
_textureViewer.ViewTexture(texture);
|
||||
}
|
||||
}
|
||||
|
||||
class TexturererViewerer
|
||||
{
|
||||
enum BackgroundMode : int32
|
||||
{
|
||||
White,
|
||||
Black,
|
||||
Pink,
|
||||
Checkerboard,
|
||||
CustomColor
|
||||
}
|
||||
|
||||
enum SampleMode : int32
|
||||
{
|
||||
Point,
|
||||
Linear
|
||||
}
|
||||
|
||||
enum ColorChannelSwizzle : int32
|
||||
{
|
||||
None,
|
||||
R,
|
||||
G,
|
||||
B,
|
||||
A
|
||||
}
|
||||
|
||||
AssetHandle<Effect> _effect;
|
||||
AssetHandle<Effect> _renderTargetEffect;
|
||||
|
||||
float _zoom = 1.0f;
|
||||
|
||||
BackgroundMode _backgroundMode = .Checkerboard;
|
||||
ColorRGBA _backgroundColor;
|
||||
|
||||
SampleMode _sampleMode = .Linear;
|
||||
|
||||
RenderTarget2D _target ~ _?.ReleaseRef();
|
||||
// TODO: we don't need depth!
|
||||
DepthStencilTarget _depth ~ _?.ReleaseRef();
|
||||
|
||||
public this()
|
||||
{
|
||||
_effect = Content.LoadAsset("Shaders\\textureViewerShader.hlsl");
|
||||
_renderTargetEffect = Content.LoadAsset("Shaders\\RenderTargetGroupViewer.hlsl");
|
||||
}
|
||||
|
||||
float2 _position;
|
||||
|
||||
bool _moving;
|
||||
|
||||
float _colorOffset = 0;
|
||||
float _colorScale = 1;
|
||||
float _alphaOffset = 0;
|
||||
float _alphaScale = 1;
|
||||
|
||||
int32 _mipLevel = 0;
|
||||
int32 _arraySlice = 0;
|
||||
int32 _groupIndex = 0;
|
||||
|
||||
ColorChannelSwizzle _swizzleR = .R;
|
||||
ColorChannelSwizzle _swizzleG = .G;
|
||||
ColorChannelSwizzle _swizzleB = .B;
|
||||
ColorChannelSwizzle _swizzleA = .A;
|
||||
|
||||
public void ViewTexture(RenderTargetGroup texture)
|
||||
{
|
||||
ShowSettings(texture.Width, texture.Height, texture.MipLevels - 1, texture.ArraySize - 1, texture);
|
||||
|
||||
UpdateInput();
|
||||
|
||||
var viewportSize = ImGui.GetContentRegionAvail();
|
||||
|
||||
viewportSize.x = Math.Max(viewportSize.x, 1);
|
||||
viewportSize.y = Math.Max(viewportSize.y, 1);
|
||||
|
||||
if(_target == null || viewportSize.x != _target.Width || viewportSize.y != _target.Height)
|
||||
{
|
||||
_target?.ReleaseRef();
|
||||
_target = new RenderTarget2D(.(.R8G8B8A8_UNorm, (.)viewportSize.x, (.)viewportSize.y));
|
||||
_target.SamplerState = SamplerStateManager.PointClamp;
|
||||
_depth?.ReleaseRef();
|
||||
_depth = new DepthStencilTarget((.)viewportSize.x, (.)viewportSize.y, .D16_UNorm);
|
||||
}
|
||||
|
||||
RenderTexture(texture);
|
||||
|
||||
ImGui.Image(_target, viewportSize);
|
||||
}
|
||||
|
||||
public void ShowSettings(float width, float height, int maxMips, int arraySize, RenderTargetGroup rtGroup)
|
||||
{
|
||||
char8*[] items = scope .("White", "Black", "Pink", "Checkerboard", "Custom Color");
|
||||
|
||||
if (ImGui.CollapsingHeader("View"))
|
||||
{
|
||||
ImGui.SliderFloat("Zoom", &_zoom, 0.01f, 100.0f);
|
||||
|
||||
float maxDimension = max(width, height);
|
||||
|
||||
ImGui.SliderFloat2("Position", *(float[2]*)&_position, 2 * -maxDimension * _zoom, 2 * maxDimension * _zoom);
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
ImGui.Combo("Background", (.)&_backgroundMode, items.Ptr, (.)items.Count);
|
||||
|
||||
if (_backgroundMode == .CustomColor)
|
||||
{
|
||||
ImGui.ColorPicker4("Color", ref _backgroundColor);
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui.CollapsingHeader("Sampling"))
|
||||
{
|
||||
items = scope .("Point", "Linear");
|
||||
|
||||
ImGui.Combo("Sampler", (.)&_sampleMode, items.Ptr, (.)items.Count);
|
||||
|
||||
ImGui.SliderInt("Mip Level", &_mipLevel, 0, (int32)maxMips);
|
||||
ImGui.SliderInt("Array Slice", &_arraySlice, 0, (int32)arraySize);
|
||||
|
||||
ImGui.BeginDisabled(rtGroup == null);
|
||||
|
||||
ImGui.SliderInt("Group Target", &_groupIndex, (rtGroup?.HasDepth == true) ? -1 : 0, (int32)(rtGroup?.ColorTargetCount ?? 1) - 1);
|
||||
|
||||
ImGui.TextUnformatted(scope $"Target name: {(rtGroup?.GetTargetDescription(_groupIndex).DebugName ?? "???")}");
|
||||
|
||||
ImGui.EndDisabled();
|
||||
}
|
||||
|
||||
if (ImGui.CollapsingHeader("Color and Transparency"))
|
||||
{
|
||||
ImGui.TextUnformatted("Channel Swizzle:");
|
||||
|
||||
if (ImGui.BeginTable("ColorAndAlpha", 4))
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
|
||||
ImGui.PushID("Color");
|
||||
|
||||
ImGui.TextUnformatted("Color:");
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.DragFloat("Offset", &_colorOffset, 0.1f);
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.DragFloat("Scale", &_colorScale, 0.1f);
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
if (ImGui.Button("Reset"))
|
||||
{
|
||||
_colorOffset = 0.0f;
|
||||
_colorScale = 1.0f;
|
||||
}
|
||||
ImGui.SameLine();
|
||||
ImGui.BeginDisabled();
|
||||
if (ImGui.Button("Auto"))
|
||||
{
|
||||
Runtime.NotImplemented();
|
||||
}
|
||||
ImGui.EndDisabled();
|
||||
|
||||
ImGui.PopID();
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
|
||||
ImGui.PushID("Alpha");
|
||||
|
||||
ImGui.TextUnformatted("Alpha:");
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.DragFloat("Offset", &_alphaOffset, 0.1f);
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.DragFloat("Scale", &_alphaScale, 0.1f);
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
if (ImGui.Button("Reset"))
|
||||
{
|
||||
_alphaOffset = 0.0f;
|
||||
_alphaScale = 1.0f;
|
||||
}
|
||||
|
||||
ImGui.PopID();
|
||||
|
||||
ImGui.EndTable();
|
||||
}
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
ImGui.TextUnformatted("Channel Swizzle:");
|
||||
|
||||
if (ImGui.BeginTable("SwizzleTable", 9))
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
|
||||
SwizzleCombo("R", ref _swizzleR);
|
||||
ImGui.TableNextColumn();
|
||||
SwizzleCombo("G", ref _swizzleG);
|
||||
ImGui.TableNextColumn();
|
||||
SwizzleCombo("B", ref _swizzleB);
|
||||
ImGui.TableNextColumn();
|
||||
SwizzleCombo("A", ref _swizzleA);
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
if (ImGui.Button("Reset swizzle"))
|
||||
{
|
||||
_swizzleR = .R;
|
||||
_swizzleG = .G;
|
||||
_swizzleB = .B;
|
||||
_swizzleA = .A;
|
||||
}
|
||||
|
||||
ImGui.EndTable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SwizzleCombo(StringView text, ref ColorChannelSwizzle swizzle)
|
||||
{
|
||||
ImGui.TextUnformatted(text);
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
if (ImGui.BeginCombo(scope $"##swizzle{text}", scope $"{swizzle}"))
|
||||
{
|
||||
if (ImGui.Selectable("R", swizzle == .R))
|
||||
swizzle = .R;
|
||||
|
||||
if (ImGui.Selectable("G", swizzle == .G))
|
||||
swizzle = .G;
|
||||
|
||||
if (ImGui.Selectable("B", swizzle == .B))
|
||||
swizzle = .B;
|
||||
|
||||
if (ImGui.Selectable("A", swizzle == .A))
|
||||
swizzle = .A;
|
||||
|
||||
if (ImGui.Selectable("None", swizzle == .None))
|
||||
swizzle = .None;
|
||||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
}
|
||||
|
||||
public void ViewTexture(Texture texture)
|
||||
{
|
||||
ShowSettings(texture.Width, texture.Height, texture.MipLevels - 1, texture.ArraySize - 1, null);
|
||||
|
||||
if (ImGui.BeginChild("imageChild"))
|
||||
{
|
||||
UpdateInput();
|
||||
|
||||
var viewportSize = ImGui.GetContentRegionAvail();
|
||||
|
||||
viewportSize.x = Math.Max(viewportSize.x, 1);
|
||||
viewportSize.y = Math.Max(viewportSize.y, 1);
|
||||
|
||||
if(_target == null || viewportSize.x != _target.Width || viewportSize.y != _target.Height)
|
||||
{
|
||||
_target?.ReleaseRef();
|
||||
_target = new RenderTarget2D(.(.R8G8B8A8_UNorm, (.)viewportSize.x, (.)viewportSize.y));
|
||||
_target.SamplerState = SamplerStateManager.PointClamp;
|
||||
_depth?.ReleaseRef();
|
||||
_depth = new DepthStencilTarget((.)viewportSize.x, (.)viewportSize.y, .D16_UNorm);
|
||||
}
|
||||
|
||||
RenderTexture(texture);
|
||||
|
||||
ImGui.Image(_target, viewportSize);
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
}
|
||||
|
||||
float lastWheel;
|
||||
|
||||
private void UpdateInput()
|
||||
{
|
||||
var windowPos = ImGui.GetWindowPos();
|
||||
var mousePos = ImGui.GetIO().MousePos;
|
||||
float2 mouseInWindow = .(mousePos.x - windowPos.x, mousePos.y - windowPos.y);
|
||||
|
||||
bool windowHovered = ImGui.IsWindowHovered();
|
||||
|
||||
if(windowHovered && Input.IsMouseButtonPressing(.MiddleButton))
|
||||
{
|
||||
_moving = true;
|
||||
}
|
||||
else if(Input.IsMouseButtonReleased(.MiddleButton))
|
||||
{
|
||||
_moving = false;
|
||||
}
|
||||
|
||||
if(windowHovered || _moving)
|
||||
{
|
||||
float mouseWheel = ImGui.GetIO().MouseWheel;
|
||||
|
||||
float delta = mouseWheel - lastWheel;
|
||||
|
||||
if(delta != 0)
|
||||
{
|
||||
_position -= mouseInWindow;
|
||||
_position /= _zoom;
|
||||
|
||||
_zoom *= Math.Pow(1.1f, delta);
|
||||
|
||||
_position *= _zoom;
|
||||
_position += mouseInWindow;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(_moving)
|
||||
{
|
||||
int2 movement = Input.GetMouseMovement();
|
||||
|
||||
_position.X += movement.X;
|
||||
_position.Y += movement.Y;
|
||||
}
|
||||
}
|
||||
|
||||
OrthographicCamera _camera = new OrthographicCamera() ~ delete _;
|
||||
|
||||
private void RenderTexture(RenderTargetGroup viewedTexture)
|
||||
{
|
||||
Viewport vp = .(0, 0, _target.Width, _target.Height);
|
||||
RenderCommand.SetViewport(vp);
|
||||
|
||||
// TODO: don't clear pink!
|
||||
RenderCommand.Clear(_target, .Pink);
|
||||
RenderCommand.Clear(_depth, .Depth, 1.0f, 0);
|
||||
|
||||
//_target.Bind();
|
||||
RenderCommand.SetRenderTarget(_target);
|
||||
RenderCommand.SetDepthStencilTarget(_depth);
|
||||
RenderCommand.BindRenderTargets();
|
||||
|
||||
float2 textureSize = float2(viewedTexture.Width, viewedTexture.Height);
|
||||
float2 zoomedTextureSize = textureSize * _zoom;
|
||||
|
||||
float2 targetSize = float2(_target.Width, _target.Height);
|
||||
|
||||
_camera.Left = 0;
|
||||
_camera.Top = 0;
|
||||
_camera.Right = targetSize.X;
|
||||
_camera.Bottom = -targetSize.Y;
|
||||
_camera.NearPlane = -5;
|
||||
_camera.FarPlane = 5;
|
||||
_camera.Update();
|
||||
|
||||
Renderer2D.BeginScene(_camera);
|
||||
|
||||
switch(_backgroundMode)
|
||||
{
|
||||
case .Black:
|
||||
Renderer2D.DrawQuadPivotCorner(float3(0, 0, 1), targetSize, 0, .Black);
|
||||
case .White:
|
||||
Renderer2D.DrawQuadPivotCorner(float3(0, 0, 1), targetSize, 0, .White);
|
||||
case .Pink:
|
||||
Renderer2D.DrawQuadPivotCorner(float3(0, 0, 1), targetSize, 0, .HotPink);
|
||||
case .CustomColor:
|
||||
Renderer2D.DrawQuadPivotCorner(float3(0, 0, 1), targetSize, 0, _backgroundColor);
|
||||
case .Checkerboard:
|
||||
float quadSize = 50.0f;
|
||||
|
||||
float2 numQuads = (targetSize / 500f) * 10f;
|
||||
|
||||
for(float x = 0; x < numQuads.X; x++)
|
||||
{
|
||||
for(float y = 0; y < numQuads.Y; y++)
|
||||
{
|
||||
Renderer2D.DrawQuadPivotCorner(float3(x * quadSize, -y * quadSize, 1), quadSize.XX, 0, ((x + y) % 2 == 0) ? .White : .Gray);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Renderer2D.EndScene();
|
||||
|
||||
// TODO: Sampler state for rt group
|
||||
//var sampler = viewedTexture.SamplerState;
|
||||
|
||||
/*switch(_sampleMode)
|
||||
{
|
||||
case .Point:
|
||||
viewedTexture.SamplerState = SamplerStateManager.PointClamp;
|
||||
case .Linear:
|
||||
viewedTexture.SamplerState = SamplerStateManager.LinearClamp;
|
||||
}*/
|
||||
|
||||
//Renderer2D.BeginScene(_camera, .SortByTexture, _effect);
|
||||
|
||||
// float3(_position * .(1, -1), 0)
|
||||
RenderCommand.Clear(_depth, .Depth, 1.0f, 0);
|
||||
|
||||
Matrix matrix = .Translation(float3(_position * .(1, -1), 0)) * .Scaling(float3(zoomedTextureSize, 1));
|
||||
|
||||
// TODO: ViewProjection kommt nicht korrekt an?
|
||||
_renderTargetEffect.Variables["WorldViewProjection"].SetData(_camera.ViewProjection * matrix);
|
||||
_renderTargetEffect.Variables["ColorOffset"].SetData(_colorOffset);
|
||||
_renderTargetEffect.Variables["ColorScale"].SetData(_colorScale);
|
||||
_renderTargetEffect.Variables["AlphaOffset"].SetData(_alphaOffset);
|
||||
_renderTargetEffect.Variables["AlphaScale"].SetData(_alphaScale);
|
||||
|
||||
_renderTargetEffect.Variables["Texels"].SetData(float2(viewedTexture.Width, viewedTexture.Height));
|
||||
|
||||
_renderTargetEffect.Variables["MipLevel"].SetData((float)_mipLevel);
|
||||
|
||||
_renderTargetEffect.Variables["Swizzle"].SetData(int4((int32)_swizzleR, (int32)_swizzleG, (int32)_swizzleB, (int32)_swizzleA));
|
||||
|
||||
var desc = _groupIndex >= 0 ? viewedTexture.[Friend]_colorTargetDescriptions[_groupIndex] : viewedTexture.[Friend]_depthTargetDescription;
|
||||
|
||||
if (desc.Format.IsInt())
|
||||
{
|
||||
_renderTargetEffect.Variables["Mode"].SetData(1);
|
||||
_renderTargetEffect.SetTexture("IntTexture", viewedTexture.GetViewBinding(_groupIndex));
|
||||
_renderTargetEffect.SetTexture("UIntTexture", null);
|
||||
_renderTargetEffect.SetTexture("Texture", null);
|
||||
}
|
||||
else if (desc.Format.IsUInt())
|
||||
{
|
||||
_renderTargetEffect.Variables["Mode"].SetData(2);
|
||||
_renderTargetEffect.SetTexture("IntTexture", null);
|
||||
_renderTargetEffect.SetTexture("UIntTexture", viewedTexture.GetViewBinding(_groupIndex));
|
||||
_renderTargetEffect.SetTexture("Texture", null);
|
||||
}
|
||||
else
|
||||
{
|
||||
_renderTargetEffect.Variables["Mode"].SetData(0);
|
||||
_renderTargetEffect.SetTexture("IntTexture", null);
|
||||
_renderTargetEffect.SetTexture("UIntTexture", null);
|
||||
_renderTargetEffect.SetTexture("Texture", viewedTexture.GetViewBinding(_groupIndex));
|
||||
}
|
||||
|
||||
_renderTargetEffect.Variables["Swizzle"].SetData(int4((int32)_swizzleR, (int32)_swizzleG, (int32)_swizzleB, (int32)_swizzleA));
|
||||
|
||||
_renderTargetEffect.ApplyChanges();
|
||||
_renderTargetEffect.Bind();
|
||||
|
||||
Quad.Draw();
|
||||
}
|
||||
|
||||
private void RenderTexture(Texture viewedTexture)
|
||||
{
|
||||
Viewport vp = .(0, 0, _target.Width, _target.Height);
|
||||
RenderCommand.SetViewport(vp);
|
||||
|
||||
// TODO: don't clear pink!
|
||||
RenderCommand.Clear(_target, .Pink);
|
||||
RenderCommand.Clear(_depth, .Depth, 1.0f, 0);
|
||||
|
||||
//_target.Bind();
|
||||
RenderCommand.SetRenderTarget(_target);
|
||||
RenderCommand.SetDepthStencilTarget(_depth);
|
||||
RenderCommand.BindRenderTargets();
|
||||
|
||||
float2 textureSize = float2(viewedTexture.Width, viewedTexture.Height);
|
||||
float2 zoomedTextureSize = textureSize * _zoom;
|
||||
|
||||
float2 targetSize = float2(_target.Width, _target.Height);
|
||||
|
||||
_effect.Variables["ColorOffset"].SetData(_colorOffset);
|
||||
_effect.Variables["ColorScale"].SetData(_colorScale);
|
||||
_effect.Variables["AlphaOffset"].SetData(_alphaOffset);
|
||||
_effect.Variables["AlphaScale"].SetData(_alphaScale);
|
||||
|
||||
_camera.Left = 0;
|
||||
_camera.Top = 0;
|
||||
_camera.Right = targetSize.X;
|
||||
_camera.Bottom = -targetSize.Y;
|
||||
_camera.NearPlane = -5;
|
||||
_camera.FarPlane = 5;
|
||||
_camera.Update();
|
||||
|
||||
Renderer2D.BeginScene(_camera);
|
||||
|
||||
switch(_backgroundMode)
|
||||
{
|
||||
case .Black:
|
||||
Renderer2D.DrawQuadPivotCorner(float3(0, 0, 1), targetSize, 0, .Black);
|
||||
case .White:
|
||||
Renderer2D.DrawQuadPivotCorner(float3(0, 0, 1), targetSize, 0, .White);
|
||||
case .Pink:
|
||||
Renderer2D.DrawQuadPivotCorner(float3(0, 0, 1), targetSize, 0, .HotPink);
|
||||
case .CustomColor:
|
||||
Renderer2D.DrawQuadPivotCorner(float3(0, 0, 1), targetSize, 0, _backgroundColor);
|
||||
case .Checkerboard:
|
||||
float quadSize = 50.0f;
|
||||
|
||||
float2 numQuads = (targetSize / 500f) * 10f;
|
||||
|
||||
for(float x = 0; x < numQuads.X; x++)
|
||||
{
|
||||
for(float y = 0; y < numQuads.Y; y++)
|
||||
{
|
||||
Renderer2D.DrawQuadPivotCorner(float3(x * quadSize, -y * quadSize, 1), quadSize.XX, 0, ((x + y) % 2 == 0) ? .White : .Gray);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Renderer2D.EndScene();
|
||||
|
||||
var sampler = viewedTexture.SamplerState..AddRef();
|
||||
|
||||
switch(_sampleMode)
|
||||
{
|
||||
case .Point:
|
||||
viewedTexture.SamplerState = SamplerStateManager.PointClamp;
|
||||
case .Linear:
|
||||
viewedTexture.SamplerState = SamplerStateManager.LinearClamp;
|
||||
}
|
||||
|
||||
Renderer2D.BeginScene(_camera, .SortByTexture, _effect);
|
||||
|
||||
Renderer2D.DrawQuad(float3(_position * .(1, -1), 0), zoomedTextureSize, 0, viewedTexture);
|
||||
|
||||
Renderer2D.EndScene();
|
||||
|
||||
viewedTexture.SamplerState = sampler;
|
||||
sampler.ReleaseRef();
|
||||
}
|
||||
}
|
||||
@@ -183,7 +183,7 @@ namespace GlitchyEditor.EditWindows
|
||||
|
||||
if (any(newMousePos != mousePos))
|
||||
{
|
||||
Input.SetMousePosition((Int2)newMousePos);
|
||||
Input.SetMousePosition((int2)newMousePos);
|
||||
// After wrapping the cursor the the other side, the camera controller must not compare the positions,
|
||||
// because the delta doesn't represent the correct movement of the cursor.
|
||||
// TODO: can be solved by using direct mouse movement instead of comparing positions
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace GlitchyEditor
|
||||
private GameViewportWindow _gameViewportWindow ~ delete _;
|
||||
private ContentBrowserWindow _contentBrowserWindow ~ delete _;
|
||||
private PropertiesWindow _propertiesWindow ~ delete _;
|
||||
private AssetViewer _assetViewer ~ delete _;
|
||||
|
||||
public Scene CurrentScene
|
||||
{
|
||||
@@ -43,6 +44,7 @@ namespace GlitchyEditor
|
||||
public GameViewportWindow GameViewportWindow => _gameViewportWindow;
|
||||
public ContentBrowserWindow ContentBrowserWindow => _contentBrowserWindow;
|
||||
public PropertiesWindow PropertiesWindow => _propertiesWindow;
|
||||
public AssetViewer AssetViewer => _assetViewer;
|
||||
|
||||
public EditorCamera* CurrentCamera { get; set; }
|
||||
|
||||
@@ -68,6 +70,7 @@ namespace GlitchyEditor
|
||||
_componentEditWindow = new ComponentEditWindow(_entityHierarchyWindow);
|
||||
_contentBrowserWindow = new ContentBrowserWindow((.)Application.Get().ContentManager);
|
||||
_propertiesWindow = new PropertiesWindow(this);
|
||||
_assetViewer = new AssetViewer((.)Application.Get().ContentManager);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
@@ -78,6 +81,7 @@ namespace GlitchyEditor
|
||||
_componentEditWindow.Show();
|
||||
_contentBrowserWindow.Show();
|
||||
_propertiesWindow.Show();
|
||||
_assetViewer.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,7 +327,8 @@ namespace GlitchyEditor
|
||||
|
||||
private bool OnImGuiRender(ImGuiRenderEvent event)
|
||||
{
|
||||
Input.ImGuiDebugDraw();
|
||||
// TODO: make window
|
||||
//Input.ImGuiDebugDraw();
|
||||
|
||||
//viewer.ViewTexture(Renderer.[Friend]_gBuffer.Target);
|
||||
|
||||
@@ -706,6 +707,9 @@ namespace GlitchyEditor
|
||||
if(ImGui.MenuItem(PropertiesWindow.s_WindowTitle))
|
||||
_editor.PropertiesWindow.Open = true;
|
||||
|
||||
if(ImGui.MenuItem(AssetViewer.s_WindowTitle))
|
||||
_editor.AssetViewer.Open = true;
|
||||
|
||||
ImGui.EndMenu();
|
||||
}
|
||||
|
||||
|
||||
@@ -105,6 +105,7 @@ namespace GlitchyEditor
|
||||
{
|
||||
_target?.ReleaseRef();
|
||||
_target = new RenderTarget2D(.(.R8G8B8A8_UNorm, (.)viewportSize.x, (.)viewportSize.y));
|
||||
_target.SamplerState = SamplerStateManager.PointClamp;
|
||||
_depth?.ReleaseRef();
|
||||
_depth = new DepthStencilTarget((.)viewportSize.x, (.)viewportSize.y, .D16_UNorm);
|
||||
}
|
||||
@@ -158,7 +159,7 @@ namespace GlitchyEditor
|
||||
|
||||
if(_moving)
|
||||
{
|
||||
Int2 movement = Input.GetMouseMovement();
|
||||
int2 movement = Input.GetMouseMovement();
|
||||
|
||||
_position.X += movement.X;
|
||||
_position.Y += movement.Y;
|
||||
|
||||
@@ -41,3 +41,8 @@ Name = "Vector3.bf"
|
||||
[[ProjectFolder.Items.Items]]
|
||||
Type = "IgnoreSource"
|
||||
Name = "Vector4.bf"
|
||||
|
||||
[[ProjectFolder.Items.Items]]
|
||||
Type = "IgnoreFolder"
|
||||
Name = "Vectors"
|
||||
AutoInclude = true
|
||||
|
||||
@@ -19,6 +19,8 @@ struct AssetHandle : IHashable
|
||||
public bool IsValid => this != .Invalid;
|
||||
public bool IsInvalid => this == .Invalid;
|
||||
|
||||
public UUID ID => _uuid;
|
||||
|
||||
/// Create a new random AssetHandle
|
||||
public this()
|
||||
{
|
||||
@@ -73,6 +75,11 @@ struct AssetHandle : IHashable
|
||||
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
public override void ToString(String strBuffer)
|
||||
{
|
||||
_uuid.ToString(strBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
struct AssetHandle<T> where T : Asset
|
||||
|
||||
@@ -36,6 +36,11 @@ namespace GlitchyEngine.Core
|
||||
return (int)_uuid;
|
||||
}
|
||||
|
||||
public override void ToString(String strBuffer)
|
||||
{
|
||||
_uuid.ToString(strBuffer);
|
||||
}
|
||||
|
||||
static void Serialize(BonWriter writer, ValueView val, BonEnvironment env, SerializeValueState state)
|
||||
{
|
||||
UUID uuid = *(UUID*)val.dataPtr;
|
||||
|
||||
@@ -119,8 +119,6 @@ namespace GlitchyEngine.ImGui
|
||||
|
||||
Begin();
|
||||
|
||||
ImGui.ShowDemoWindow();
|
||||
|
||||
{
|
||||
Debug.Profiler.ProfileScope!("ImGuiRenderEvent");
|
||||
|
||||
|
||||
+10
-10
@@ -28,15 +28,15 @@ namespace GlitchyEngine
|
||||
public static extern bool IsKeyReleasing(Key keycode);
|
||||
|
||||
// TODO: Should Input be able to set mousepos?
|
||||
public static extern void SetMousePosition(Int2 pos);
|
||||
public static extern void SetMousePosition(int2 pos);
|
||||
|
||||
public static extern bool IsMouseButtonPressed(MouseButton button);
|
||||
public static extern bool IsMouseButtonReleased(MouseButton button);
|
||||
public static extern bool IsMouseButtonPressing(MouseButton button);
|
||||
public static extern bool IsMouseButtonReleasing(MouseButton button);
|
||||
public static extern Int2 GetMousePosition();
|
||||
public static extern Int2 GetMouseMovement();
|
||||
public static extern Int2 GetRawMouseMovement();
|
||||
public static extern int2 GetMousePosition();
|
||||
public static extern int2 GetMouseMovement();
|
||||
public static extern int2 GetRawMouseMovement();
|
||||
public static extern int32 GetMouseX();
|
||||
public static extern int32 GetMouseY();
|
||||
|
||||
@@ -44,9 +44,9 @@ namespace GlitchyEngine
|
||||
// public static extern bool WasMouseButtonPressing(MouseButton button);
|
||||
public static extern bool WasMouseButtonReleased(MouseButton button);
|
||||
//public static extern bool WasMouseButtonReleasing(MouseButton button);
|
||||
public static extern Int2 GetLastMousePosition();
|
||||
public static extern Int2 GetLastMouseMovement();
|
||||
public static extern Int2 GetLastRawMouseMovement();
|
||||
public static extern int2 GetLastMousePosition();
|
||||
public static extern int2 GetLastMouseMovement();
|
||||
public static extern int2 GetLastRawMouseMovement();
|
||||
public static extern int32 GetLastMouseX();
|
||||
public static extern int32 GetLastMouseY();
|
||||
|
||||
@@ -121,14 +121,14 @@ namespace GlitchyEngine
|
||||
|
||||
public static class Mouse
|
||||
{
|
||||
private static append List<(Int2 Position, int Hash)> _lockPositions = .();
|
||||
private static append List<(int2 Position, int Hash)> _lockPositions = .();
|
||||
|
||||
public static void LockCurrentPosition(int hash)
|
||||
{
|
||||
LockPosition(Input.GetMousePosition(), hash);
|
||||
}
|
||||
|
||||
public static void LockPosition(Int2 pos, int hash)
|
||||
public static void LockPosition(int2 pos, int hash)
|
||||
{
|
||||
for (var entry in _lockPositions)
|
||||
{
|
||||
@@ -156,7 +156,7 @@ namespace GlitchyEngine
|
||||
//Log.EngineLogger.AssertDebug(false, "No mouse lock position with hash found.");
|
||||
}
|
||||
|
||||
public static Int2? LockedPosition;
|
||||
public static int2? LockedPosition;
|
||||
|
||||
public static void NewFrame()
|
||||
{
|
||||
|
||||
@@ -13,12 +13,32 @@ namespace System
|
||||
}
|
||||
|
||||
[Inline]
|
||||
public Int2 XX => Int2((int32)this);
|
||||
public int2 XX => (int32)this;
|
||||
|
||||
[Inline]
|
||||
public Int3 XXX => Int3((int32)this);
|
||||
public int3 XXX => (int32)this;
|
||||
|
||||
[Inline]
|
||||
public Int4 XXXX => Int4((int32)this);
|
||||
public int4 XXXX => (int32)this;
|
||||
}
|
||||
|
||||
extension UInt32
|
||||
{
|
||||
public uint32 X
|
||||
{
|
||||
[Inline]
|
||||
get => (uint32)this;
|
||||
[Inline]
|
||||
set mut => this = value;
|
||||
}
|
||||
|
||||
[Inline]
|
||||
public uint2 XX => (uint32)this;
|
||||
|
||||
[Inline]
|
||||
public uint3 XXX => (uint32)this;
|
||||
|
||||
[Inline]
|
||||
public uint4 XXXX => (uint32)this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,299 +0,0 @@
|
||||
using Bon;
|
||||
using System;
|
||||
|
||||
namespace GlitchyEngine.Math
|
||||
{
|
||||
[BonTarget]
|
||||
[SwizzleVector(2, "GlitchyEngine.Math.Vector")]
|
||||
public struct Vector2
|
||||
{
|
||||
public const Vector2 Zero = .(0f, 0f);
|
||||
public const Vector2 UnitX = .(1f, 0f);
|
||||
public const Vector2 UnitY = .(0f, 1f);
|
||||
public const Vector2 One = .(1f, 1f);
|
||||
|
||||
public const int ComponentCount = 2;
|
||||
|
||||
public float X, Y;
|
||||
|
||||
public this() => this = default;
|
||||
|
||||
public this(float value)
|
||||
{
|
||||
X = value;
|
||||
Y = value;
|
||||
}
|
||||
|
||||
public this(float x, float y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public ref float this[int index]
|
||||
{
|
||||
[Checked]
|
||||
get mut
|
||||
{
|
||||
if(index < 0 || index >= ComponentCount)
|
||||
Internal.ThrowIndexOutOfRange(1);
|
||||
|
||||
return ref (&X)[index];
|
||||
}
|
||||
|
||||
[Inline]
|
||||
get mut => ref (&X)[index];
|
||||
}
|
||||
|
||||
public float this[int index]
|
||||
{
|
||||
[Checked]
|
||||
get
|
||||
{
|
||||
if(index < 0 || index >= ComponentCount)
|
||||
Internal.ThrowIndexOutOfRange(1);
|
||||
|
||||
if(index == 0)
|
||||
return X;
|
||||
else
|
||||
return Y;
|
||||
}
|
||||
|
||||
[Inline]
|
||||
get
|
||||
{
|
||||
if(index == 0)
|
||||
return X;
|
||||
else
|
||||
return Y;
|
||||
}
|
||||
|
||||
[Checked]
|
||||
set mut
|
||||
{
|
||||
if(index < 0 || index >= ComponentCount)
|
||||
Internal.ThrowIndexOutOfRange(1);
|
||||
|
||||
if(index == 0)
|
||||
X = value;
|
||||
else
|
||||
Y = value;
|
||||
}
|
||||
|
||||
[Inline]
|
||||
set mut
|
||||
{
|
||||
if(index == 0)
|
||||
X = value;
|
||||
else
|
||||
Y = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the magnitude (length) of this vector.
|
||||
* @remarks MagnitudeSquared might be used if only the relative length is relevant.
|
||||
*/
|
||||
public float Magnitude()
|
||||
{
|
||||
return Math.Sqrt(X * X + Y * Y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the squared magnitude (length) of this vector.
|
||||
*/
|
||||
public float MagnitudeSquared()
|
||||
{
|
||||
return X * X + Y * Y;
|
||||
}
|
||||
|
||||
//TODO: Normalization interface is bad
|
||||
[Checked]
|
||||
public void Normalize() mut
|
||||
{
|
||||
if(this == .Zero)
|
||||
return;
|
||||
|
||||
this /= Magnitude();
|
||||
}
|
||||
|
||||
public void Normalize() mut
|
||||
{
|
||||
this /= Magnitude();
|
||||
}
|
||||
|
||||
public static Vector2 Normalize(Vector2 v)
|
||||
{
|
||||
return v / v.Magnitude();
|
||||
}
|
||||
|
||||
public static float Dot(Vector2 l, Vector2 r)
|
||||
{
|
||||
return l.X * r.X + l.Y * r.Y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the projection of a onto b
|
||||
*/
|
||||
public static Vector2 Project(Vector2 a, Vector2 b)
|
||||
{
|
||||
return (b * (Dot(a, b) / Dot(b, b)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the rejection of a from b
|
||||
*/
|
||||
public static Vector2 Reject(Vector2 a, Vector2 b)
|
||||
{
|
||||
return (a - b * (Dot(a, b) / Dot(b, b)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpolates linearly between two given vectors.
|
||||
* @param a The first vector.
|
||||
* @param b The second vector.
|
||||
* @param interpolationValue The value that linearly interpolates between a and b.
|
||||
* (0 means a will be returned, 1 means b will be returned.)
|
||||
* @returns The resulting linear interpolation.
|
||||
*/
|
||||
public static Vector2 Lerp(Vector2 a, Vector2 b, float interpolationValue)
|
||||
{
|
||||
return a + interpolationValue * (b - a);
|
||||
}
|
||||
|
||||
public static Vector2 Min(Vector2 a, Vector2 b)
|
||||
{
|
||||
return .(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y));
|
||||
}
|
||||
|
||||
public static Vector2 Max(Vector2 a, Vector2 b)
|
||||
{
|
||||
return .(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y));
|
||||
}
|
||||
|
||||
//
|
||||
// Assignment operators
|
||||
//
|
||||
|
||||
// Addition
|
||||
|
||||
public void operator +=(Vector2 value) mut
|
||||
{
|
||||
X += value.X;
|
||||
Y += value.Y;
|
||||
}
|
||||
|
||||
public void operator +=(float scalar) mut
|
||||
{
|
||||
X += scalar;
|
||||
Y += scalar;
|
||||
}
|
||||
|
||||
// Subtraction
|
||||
|
||||
public void operator -=(Vector2 value) mut
|
||||
{
|
||||
X -= value.X;
|
||||
Y -= value.Y;
|
||||
}
|
||||
|
||||
public void operator -=(float scalar) mut
|
||||
{
|
||||
X -= scalar;
|
||||
Y -= scalar;
|
||||
}
|
||||
|
||||
// Multiplication
|
||||
|
||||
public void operator *=(Vector2 value) mut
|
||||
{
|
||||
X *= value.X;
|
||||
Y *= value.Y;
|
||||
}
|
||||
|
||||
public void operator *=(float scalar) mut
|
||||
{
|
||||
X *= scalar;
|
||||
Y *= scalar;
|
||||
}
|
||||
|
||||
// Division
|
||||
|
||||
public void operator /=(float scalar) mut
|
||||
{
|
||||
float f = 1.0f / scalar;
|
||||
X *= f;
|
||||
Y *= f;
|
||||
}
|
||||
|
||||
public void operator /=(Vector2 value) mut
|
||||
{
|
||||
X /= value.X;
|
||||
Y /= value.Y;
|
||||
}
|
||||
|
||||
//
|
||||
// operators
|
||||
//
|
||||
|
||||
// Addition
|
||||
|
||||
public static Vector2 operator +(Vector2 left, Vector2 right) => Vector2(left.X + right.X, left.Y + right.Y);
|
||||
|
||||
public static Vector2 operator +(Vector2 value, float scalar) => Vector2(value.X + scalar, value.Y + scalar);
|
||||
|
||||
public static Vector2 operator +(float scalar, Vector2 value) => Vector2(scalar + value.X, scalar + value.Y);
|
||||
|
||||
public static Vector2 operator +(Vector2 value) => value;
|
||||
|
||||
// Subtraction
|
||||
|
||||
public static Vector2 operator -(Vector2 left, Vector2 right) => Vector2(left.X - right.X, left.Y - right.Y);
|
||||
|
||||
public static Vector2 operator -(Vector2 value, float scalar) => Vector2(value.X - scalar, value.Y - scalar);
|
||||
|
||||
public static Vector2 operator -(float scalar, Vector2 value) => Vector2(scalar - value.X, scalar - value.Y);
|
||||
|
||||
public static Vector2 operator -(Vector2 value) => Vector2(-value.X, -value.Y);
|
||||
|
||||
// Multiplication
|
||||
|
||||
public static Vector2 operator *(Vector2 left, Vector2 right) => Vector2(left.X * right.X, left.Y * right.Y);
|
||||
|
||||
public static Vector2 operator *(Vector2 value, float scalar) => Vector2(value.X * scalar, value.Y * scalar);
|
||||
|
||||
public static Vector2 operator *(float scalar, Vector2 value) => Vector2(scalar * value.X, scalar * value.Y);
|
||||
|
||||
// Division
|
||||
|
||||
public static Vector2 operator /(Vector2 left, Vector2 right) => Vector2(left.X / right.X, left.Y / right.Y);
|
||||
|
||||
public static Vector2 operator /(Vector2 value, float scalar)
|
||||
{
|
||||
float inv = 1.0f / scalar;
|
||||
return Vector2(value.X * inv, value.Y * inv);
|
||||
}
|
||||
|
||||
public static Vector2 operator /(float scalar, Vector2 value) => Vector2(scalar / value.X, scalar / value.Y);
|
||||
|
||||
// Equality
|
||||
|
||||
public static bool operator ==(Vector2 left, Vector2 right) => left.X == right.X && left.Y == right.Y;
|
||||
|
||||
public static bool operator !=(Vector2 left, Vector2 right) => left.X != right.X || left.Y != right.Y;
|
||||
|
||||
public override void ToString(String strBuffer) => strBuffer.AppendF("X:{0} Y:{1}", X, Y);
|
||||
|
||||
public bool Equals(Vector2 v, float epsilon = Math.[Friend]sMachineEpsilonFloat)
|
||||
{
|
||||
return (Math.Abs(v.X - X) < epsilon) && (Math.Abs(v.Y - Y) < epsilon);
|
||||
}
|
||||
|
||||
[Inline]
|
||||
public static explicit operator Self(float value) => Self(value);
|
||||
|
||||
[Inline]
|
||||
#unwarn
|
||||
public static explicit operator float[2](Vector2 value) => *(float[2]*)&value;
|
||||
}
|
||||
}
|
||||
@@ -1,349 +0,0 @@
|
||||
using Bon;
|
||||
using System;
|
||||
|
||||
namespace GlitchyEngine.Math
|
||||
{
|
||||
[BonTarget]
|
||||
[SwizzleVector(3, "GlitchyEngine.Math.Vector")]
|
||||
public struct float3
|
||||
{
|
||||
public const float3 Zero = .(0f, 0f, 0f);
|
||||
public const float3 UnitX = .(1f, 0f, 0f);
|
||||
public const float3 UnitY = .(0f, 1f, 0f);
|
||||
public const float3 UnitZ = .(0f, 0f, 1f);
|
||||
public const float3 One = .(1f, 1f, 1f);
|
||||
|
||||
public const float3 Forward = .(0f, 0f, 1f);
|
||||
public const float3 Backward = .(0f, 0f, -1f);
|
||||
public const float3 Left = .(-1f, 0f, 0f);
|
||||
public const float3 Right = .(1f, 0f, 0f);
|
||||
public const float3 Up = .(0f, 1f, 0f);
|
||||
public const float3 Down = .(0f, -1f, 0f);
|
||||
|
||||
public const int ComponentCount = 3;
|
||||
|
||||
public float X, Y, Z;
|
||||
|
||||
public this() => this = default;
|
||||
|
||||
public this(float value)
|
||||
{
|
||||
X = value;
|
||||
Y = value;
|
||||
Z = value;
|
||||
}
|
||||
|
||||
public this(Vector2 value, float z = 0.0f)
|
||||
{
|
||||
X = value.X;
|
||||
Y = value.Y;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
public this(float x, float y, float z)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
public this(float3 value)
|
||||
{
|
||||
X = value.X;
|
||||
Y = value.Y;
|
||||
Z = value.Z;
|
||||
}
|
||||
|
||||
public this(float4 value)
|
||||
{
|
||||
X = value.X;
|
||||
Y = value.Y;
|
||||
Z = value.Z;
|
||||
}
|
||||
|
||||
public ref float this[int index]
|
||||
{
|
||||
[Checked]
|
||||
get mut
|
||||
{
|
||||
if(index < 0 || index >= ComponentCount)
|
||||
Internal.ThrowIndexOutOfRange(1);
|
||||
|
||||
return ref (&X)[index];
|
||||
}
|
||||
|
||||
[Inline]
|
||||
get mut => ref (&X)[index];
|
||||
}
|
||||
|
||||
public float this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
switch(index)
|
||||
{
|
||||
case 0: return X;
|
||||
case 1: return Y;
|
||||
case 2: return Z;
|
||||
default: Internal.ThrowIndexOutOfRange(1);
|
||||
}
|
||||
}
|
||||
|
||||
set mut
|
||||
{
|
||||
switch(index)
|
||||
{
|
||||
case 0: X = value;
|
||||
case 1: Y = value;
|
||||
case 2: Z = value;
|
||||
default: Internal.ThrowIndexOutOfRange(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the magnitude (length) of this vector.
|
||||
* @remarks If the exact magnitude isn't needed (e.g. for comparisons) consider using MagnitudeSquared which doesn't use the square root operation.
|
||||
*/
|
||||
public float Magnitude() => Math.Sqrt(X * X + Y * Y + Z * Z);
|
||||
|
||||
/**
|
||||
* Calculates the squared magnitude (length) of this vector.
|
||||
* @remarks This function avoids the square root operation to calculate the magnitude and is thus more suitable for comparisons where the exact magnitude isn't needed.
|
||||
*/
|
||||
public float MagnitudeSquared() => X * X + Y * Y + Z * Z;
|
||||
|
||||
/// Normalizes this vector.
|
||||
[Checked]
|
||||
public void Normalize() mut
|
||||
{
|
||||
if(this == .Zero)
|
||||
return;
|
||||
|
||||
this /= Magnitude();
|
||||
}
|
||||
|
||||
/// Normalizes this vector.
|
||||
public void Normalize() mut
|
||||
{
|
||||
this /= Magnitude();
|
||||
}
|
||||
|
||||
/// Returns a copy of this Vector with a magnitude of 1.
|
||||
[Checked]
|
||||
public float3 Normalized()
|
||||
{
|
||||
if(this == .Zero)
|
||||
return .Zero;
|
||||
|
||||
return this / Magnitude();
|
||||
}
|
||||
|
||||
/// Returns a copy of this Vector with a magnitude of 1.
|
||||
public float3 Normalized()
|
||||
{
|
||||
return this / Magnitude();
|
||||
}
|
||||
|
||||
/// Returns a copy of the given Vector with a magnitude of 1.
|
||||
public static float3 Normalize(float3 v)
|
||||
{
|
||||
return v / v.Magnitude();
|
||||
}
|
||||
|
||||
/// Calculates the dot product of two vectors.
|
||||
public static float Dot(float3 l, float3 r) => l.X * r.X + l.Y * r.Y + l.Z * r.Z;
|
||||
|
||||
/// Calculates the distance between two vectors.
|
||||
public static float Distance(float3 a, float3 b) => (a - b).[Inline]Magnitude();
|
||||
|
||||
/// Calculates the squared distance between two vectors.
|
||||
public static float DistanceSquared(float3 a, float3 b) => (a - b).[Inline]MagnitudeSquared();
|
||||
|
||||
/// Calculates the cross product of two vectors.
|
||||
public static float3 Cross(float3 l, float3 r)
|
||||
{
|
||||
return .(l.Y * r.Z - l.Z * r.Y,
|
||||
l.Z * r.X - l.X * r.Z,
|
||||
l.X * r.Y - l.Y * r.X);
|
||||
}
|
||||
|
||||
/// Calculates the projection of a onto b.
|
||||
public static float3 Project(float3 a, float3 b)
|
||||
{
|
||||
return (b * (Dot(a, b) / Dot(b, b)));
|
||||
}
|
||||
|
||||
/// Calculates the rejection of a from b.
|
||||
public static float3 Reject(float3 a, float3 b)
|
||||
{
|
||||
return (a - b * (Dot(a, b) / Dot(b, b)));
|
||||
}
|
||||
|
||||
public static float3 Floor(float3 value) => .(Math.Floor(value.X), Math.Floor(value.Y), Math.Floor(value.Z));
|
||||
|
||||
public static float3 Ceiling(float3 value) => .(Math.Ceiling(value.X), Math.Ceiling(value.Y), Math.Ceiling(value.Z));
|
||||
|
||||
/**
|
||||
* Interpolates linearly between two given vectors.
|
||||
* @param a The first vector.
|
||||
* @param b The second vector.
|
||||
* @param interpolationValue The value that linearly interpolates between a and b.
|
||||
* (0 means a will be returned, 1 means b will be returned.)
|
||||
* @returns The resulting linear interpolation.
|
||||
*/
|
||||
public static float3 Lerp(float3 a, float3 b, float interpolationValue)
|
||||
{
|
||||
return a + interpolationValue * (b - a);
|
||||
}
|
||||
|
||||
public static float3 Min(float3 a, float3 b) => .(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y), Math.Min(a.Z, b.Z));
|
||||
|
||||
public static float3 Max(float3 a, float3 b) => .(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y), Math.Min(a.Z, b.Z));
|
||||
|
||||
public static float3 Abs(float3 v) => .(Math.Abs(v.X), Math.Abs(v.Y), Math.Abs(v.Z));
|
||||
|
||||
public static float3 Clamp(float3 v, float3 min, float3 max)
|
||||
{
|
||||
return .(Math.Clamp(v.X, min.X, max.X),
|
||||
Math.Clamp(v.Y, min.Y, max.Y),
|
||||
Math.Clamp(v.X, min.Z, max.Z));
|
||||
}
|
||||
|
||||
//
|
||||
// Assignment operators
|
||||
//
|
||||
|
||||
// Addition
|
||||
|
||||
public void operator +=(float3 value) mut
|
||||
{
|
||||
X += value.X;
|
||||
Y += value.Y;
|
||||
Z += value.Z;
|
||||
}
|
||||
|
||||
public void operator +=(float scalar) mut
|
||||
{
|
||||
X += scalar;
|
||||
Y += scalar;
|
||||
Z += scalar;
|
||||
}
|
||||
|
||||
// Subtraction
|
||||
|
||||
public void operator -=(float3 value) mut
|
||||
{
|
||||
X -= value.X;
|
||||
Y -= value.Y;
|
||||
Z -= value.Z;
|
||||
}
|
||||
|
||||
public void operator -=(float scalar) mut
|
||||
{
|
||||
X -= scalar;
|
||||
Y -= scalar;
|
||||
Z -= scalar;
|
||||
}
|
||||
|
||||
// Multiplication
|
||||
|
||||
public void operator *=(float3 value) mut
|
||||
{
|
||||
X *= value.X;
|
||||
Y *= value.Y;
|
||||
Z *= value.Z;
|
||||
}
|
||||
|
||||
public void operator *=(float scalar) mut
|
||||
{
|
||||
X *= scalar;
|
||||
Y *= scalar;
|
||||
Z *= scalar;
|
||||
}
|
||||
|
||||
// Division
|
||||
|
||||
public void operator /=(float3 value) mut
|
||||
{
|
||||
X /= value.X;
|
||||
Y /= value.Y;
|
||||
Z /= value.Z;
|
||||
}
|
||||
|
||||
public void operator /=(float scalar) mut
|
||||
{
|
||||
float inv = 1.0f / scalar;
|
||||
X *= inv;
|
||||
Y *= inv;
|
||||
Z *= inv;
|
||||
}
|
||||
|
||||
//
|
||||
// operators
|
||||
//
|
||||
|
||||
// Addition
|
||||
|
||||
public static float3 operator +(float3 left, float3 right) => float3(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
|
||||
|
||||
public static float3 operator +(float3 value, float scalar) => float3(value.X + scalar, value.Y + scalar, value.Z + scalar);
|
||||
|
||||
public static float3 operator +(float scalar, float3 value) => float3(scalar + value.X, scalar + value.Y, scalar + value.Z);
|
||||
|
||||
public static float3 operator +(float3 value) => value;
|
||||
|
||||
// Subtraction
|
||||
|
||||
public static float3 operator -(float3 left, float3 right) => float3(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
|
||||
|
||||
public static float3 operator -(float3 value, float scalar) => float3(value.X - scalar, value.Y - scalar, value.Z - scalar);
|
||||
|
||||
public static float3 operator -(float scalar, float3 value) => float3(scalar - value.X, scalar - value.Y, scalar - value.Z);
|
||||
|
||||
public static float3 operator -(float3 value) => float3(-value.X, -value.Y, -value.Z);
|
||||
|
||||
// Multiplication
|
||||
|
||||
public static float3 operator *(float3 left, float3 right) => float3(left.X * right.X, left.Y * right.Y, left.Z * right.Z);
|
||||
|
||||
public static float3 operator *(float3 value, float scalar) => float3(value.X * scalar, value.Y * scalar, value.Z * scalar);
|
||||
|
||||
public static float3 operator *(float scalar, float3 value) => float3(scalar * value.X, scalar * value.Y, scalar * value.Z);
|
||||
|
||||
// Division
|
||||
|
||||
public static float3 operator /(float3 left, float3 right) => float3(left.X / right.X, left.Y / right.Y, left.Z / right.Z);
|
||||
|
||||
public static float3 operator /(float3 value, float scalar)
|
||||
{
|
||||
float inv = 1.0f / scalar;
|
||||
return float3(value.X * inv, value.Y * inv, value.Z * inv);
|
||||
}
|
||||
|
||||
public static float3 operator /(float scalar, float3 value) => float3(scalar / value.X, scalar / value.Y, scalar / value.Z);
|
||||
|
||||
// Modulo
|
||||
|
||||
public static float3 operator %(float3 left, float3 right) => float3(left.X % right.X, left.Y % right.Y, left.Z % right.Z);
|
||||
|
||||
public static float3 operator %(float3 value, float scalar) => float3(value.X % scalar, value.Y % scalar, value.Z % scalar);
|
||||
|
||||
public static float3 operator %(float scalar, float3 value) => float3(scalar % value.X, scalar % value.Y, scalar % value.Z);
|
||||
|
||||
// Equality
|
||||
|
||||
public static bool operator ==(float3 left, float3 right) => left.X == right.X && left.Y == right.Y && left.Z == right.Z;
|
||||
|
||||
public static bool operator !=(float3 left, float3 right) => left.X != right.X || left.Y != right.Y || left.Z != right.Z;
|
||||
|
||||
public override void ToString(String strBuffer) => strBuffer.AppendF("X:{0} Y:{1} Z:{2}", X, Y, Z);
|
||||
|
||||
[Inline]
|
||||
public static explicit operator Self(float value) => Self(value);
|
||||
|
||||
[Inline]
|
||||
#unwarn
|
||||
public static explicit operator float[3](float3 value) => *(float[3]*)&value;
|
||||
}
|
||||
}
|
||||
@@ -1,330 +0,0 @@
|
||||
using Bon;
|
||||
using System;
|
||||
|
||||
namespace GlitchyEngine.Math
|
||||
{
|
||||
[BonTarget]
|
||||
[SwizzleVector(4, "GlitchyEngine.Math.Vector")]
|
||||
public struct float4
|
||||
{
|
||||
public const float4 Zero = .(0f, 0f, 0f, 0f);
|
||||
public const float4 UnitX = .(1f, 0f, 0f, 0f);
|
||||
public const float4 UnitY = .(0f, 1f, 0f, 0f);
|
||||
public const float4 UnitZ = .(0f, 0f, 1f, 0f);
|
||||
public const float4 UnitW = .(0f, 0f, 0f, 1f);
|
||||
public const float4 One = .(1f, 1f, 1f, 1f);
|
||||
|
||||
public const int ComponentCount = 4;
|
||||
|
||||
public float X, Y, Z, W;
|
||||
|
||||
public this() => this = default;
|
||||
|
||||
public this(float value)
|
||||
{
|
||||
X = value;
|
||||
Y = value;
|
||||
Z = value;
|
||||
W = value;
|
||||
}
|
||||
|
||||
public this(Vector2 value, float z, float w)
|
||||
{
|
||||
X = value.X;
|
||||
Y = value.Y;
|
||||
Z = z;
|
||||
W = w;
|
||||
}
|
||||
|
||||
public this(Vector2 value1, Vector2 value2)
|
||||
{
|
||||
X = value1.X;
|
||||
Y = value1.Y;
|
||||
Z = value2.X;
|
||||
W = value2.Y;
|
||||
}
|
||||
|
||||
public this(float3 value, float w)
|
||||
{
|
||||
X = value.X;
|
||||
Y = value.Y;
|
||||
Z = value.Z;
|
||||
W = w;
|
||||
}
|
||||
|
||||
public this(float x, float y, float z, float w)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
W = w;
|
||||
}
|
||||
|
||||
public ref float this[int index]
|
||||
{
|
||||
[Checked]
|
||||
get mut
|
||||
{
|
||||
if(index < 0 || index >= ComponentCount)
|
||||
Internal.ThrowIndexOutOfRange(1);
|
||||
|
||||
return ref (&X)[index];
|
||||
}
|
||||
|
||||
[Inline]
|
||||
get mut => ref (&X)[index];
|
||||
}
|
||||
|
||||
public float this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
switch(index)
|
||||
{
|
||||
case 0: return X;
|
||||
case 1: return Y;
|
||||
case 2: return Z;
|
||||
case 3: return W;
|
||||
default: Internal.ThrowIndexOutOfRange(1);
|
||||
}
|
||||
}
|
||||
|
||||
set mut
|
||||
{
|
||||
switch(index)
|
||||
{
|
||||
case 0: X = value;
|
||||
case 1: Y = value;
|
||||
case 2: Z = value;
|
||||
case 3: W = value;
|
||||
default: Internal.ThrowIndexOutOfRange(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the magnitude (length) of this vector.
|
||||
* @remarks MagnitudeSquared might be used if only the relative length is relevant.
|
||||
*/
|
||||
public float Magnitude()
|
||||
{
|
||||
return Math.Sqrt(X * X + Y * Y + Z * Z + W * W);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the squared magnitude (length) of this vector.
|
||||
*/
|
||||
public float MagnitudeSquared()
|
||||
{
|
||||
return X * X + Y * Y + Z * Z + W * W;
|
||||
}
|
||||
|
||||
[Checked]
|
||||
public void Normalize() mut
|
||||
{
|
||||
if(this == .Zero)
|
||||
return;
|
||||
|
||||
this /= Magnitude();
|
||||
}
|
||||
|
||||
public void Normalize() mut
|
||||
{
|
||||
this /= Magnitude();
|
||||
}
|
||||
|
||||
public static float4 Normalize(float4 v)
|
||||
{
|
||||
if(v == .Zero)
|
||||
return .Zero;
|
||||
|
||||
return v / v.Magnitude();
|
||||
}
|
||||
|
||||
[Unchecked]
|
||||
public static float4 Normalize(float4 v)
|
||||
{
|
||||
return v / v.Magnitude();
|
||||
}
|
||||
|
||||
public static float Dot(float4 l, float4 r)
|
||||
{
|
||||
return l.X * r.X + l.Y * r.Y + l.Z * r.Z + l.W * r.W;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the projection of a onto b
|
||||
*/
|
||||
public static float4 Project(float4 a, float4 b)
|
||||
{
|
||||
return (b * (Dot(a, b) / Dot(b, b)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the rejection of a from b
|
||||
*/
|
||||
public static float4 Reject(float4 a, float4 b)
|
||||
{
|
||||
return (a - b * (Dot(a, b) / Dot(b, b)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpolates linearly between two given vectors.
|
||||
* @param a The first vector.
|
||||
* @param b The second vector.
|
||||
* @param interpolationValue The value that linearly interpolates between a and b.
|
||||
* (0 means a will be returned, 1 means b will be returned.)
|
||||
* @returns The resulting linear interpolation.
|
||||
*/
|
||||
public static float4 Lerp(float4 a, float4 b, float interpolationValue)
|
||||
{
|
||||
return a + interpolationValue * (b - a);
|
||||
}
|
||||
|
||||
public static float4 Min(float4 a, float4 b)
|
||||
{
|
||||
return .(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y), Math.Min(a.Z, b.Z), Math.Min(a.W, b.W));
|
||||
}
|
||||
|
||||
public static float4 Max(float4 a, float4 b)
|
||||
{
|
||||
return .(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y), Math.Min(a.Z, b.Z), Math.Min(a.W, b.W));
|
||||
}
|
||||
|
||||
//
|
||||
// Assignment operators
|
||||
//
|
||||
|
||||
// Addition
|
||||
|
||||
public void operator +=(float4 value) mut
|
||||
{
|
||||
X += value.X;
|
||||
Y += value.Y;
|
||||
Z += value.Z;
|
||||
W += value.W;
|
||||
}
|
||||
|
||||
public void operator +=(float scalar) mut
|
||||
{
|
||||
X += scalar;
|
||||
Y += scalar;
|
||||
Z += scalar;
|
||||
W += scalar;
|
||||
}
|
||||
|
||||
// Subtraction
|
||||
|
||||
public void operator -=(float4 value) mut
|
||||
{
|
||||
X -= value.X;
|
||||
Y -= value.Y;
|
||||
Z -= value.Z;
|
||||
W -= value.W;
|
||||
}
|
||||
|
||||
public void operator -=(float scalar) mut
|
||||
{
|
||||
X -= scalar;
|
||||
Y -= scalar;
|
||||
Z -= scalar;
|
||||
W -= scalar;
|
||||
}
|
||||
|
||||
// Multiplication
|
||||
|
||||
public void operator *=(float4 value) mut
|
||||
{
|
||||
X *= value.X;
|
||||
Y *= value.Y;
|
||||
Z *= value.Z;
|
||||
W *= value.W;
|
||||
}
|
||||
|
||||
public void operator *=(float scalar) mut
|
||||
{
|
||||
X *= scalar;
|
||||
Y *= scalar;
|
||||
Z *= scalar;
|
||||
W *= scalar;
|
||||
}
|
||||
|
||||
// Division
|
||||
|
||||
public void operator /=(float scalar) mut
|
||||
{
|
||||
float f = 1.0f / scalar;
|
||||
X *= f;
|
||||
Y *= f;
|
||||
Z *= f;
|
||||
W *= f;
|
||||
}
|
||||
|
||||
public void operator /=(float4 value) mut
|
||||
{
|
||||
X /= value.X;
|
||||
Y /= value.Y;
|
||||
Z /= value.Z;
|
||||
W /= value.W;
|
||||
}
|
||||
|
||||
//
|
||||
// operators
|
||||
//
|
||||
|
||||
// Addition
|
||||
|
||||
public static float4 operator +(float4 left, float4 right) => float4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W);
|
||||
|
||||
public static float4 operator +(float4 value, float scalar) => float4(value.X + scalar, value.Y + scalar, value.Z + scalar, value.W + scalar);
|
||||
|
||||
public static float4 operator +(float scalar, float4 value) => float4(scalar + value.X, scalar + value.Y, scalar + value.Z, scalar + value.W);
|
||||
|
||||
public static float4 operator +(float4 value) => value;
|
||||
|
||||
// Subtraction
|
||||
|
||||
public static float4 operator -(float4 left, float4 right) => float4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W);
|
||||
|
||||
public static float4 operator -(float4 value, float scalar) => float4(value.X - scalar, value.Y - scalar, value.Z - scalar, value.W - scalar);
|
||||
|
||||
public static float4 operator -(float scalar, float4 value) => float4(scalar - value.X, scalar - value.Y, scalar - value.Z, scalar - value.W);
|
||||
|
||||
public static float4 operator -(float4 value) => float4(-value.X, -value.Y, -value.Z, -value.W);
|
||||
|
||||
// Multiplication
|
||||
|
||||
public static float4 operator *(float4 left, float4 right) => float4(left.X * right.X, left.Y * right.Y, left.Z * right.Z, left.W * right.W);
|
||||
|
||||
public static float4 operator *(float4 value, float scalar) => float4(value.X * scalar, value.Y * scalar, value.Z * scalar, value.W * scalar);
|
||||
|
||||
public static float4 operator *(float scalar, float4 value) => float4(scalar * value.X, scalar * value.Y, scalar * value.Z, scalar * value.W);
|
||||
|
||||
// Division
|
||||
|
||||
public static float4 operator /(float4 left, float4 right) => float4(left.X / right.X, left.Y / right.Y, left.Z / right.Z, left.W / right.W);
|
||||
|
||||
public static float4 operator /(float4 value, float scalar)
|
||||
{
|
||||
float inv = 1.0f / scalar;
|
||||
return float4(value.X * inv, value.Y * inv, value.Z * inv, value.W * inv);
|
||||
}
|
||||
|
||||
public static float4 operator /(float scalar, float4 value) => float4(scalar / value.X, scalar / value.Y, scalar / value.Z, scalar / value.W);
|
||||
|
||||
// Equality
|
||||
|
||||
public static bool operator ==(float4 left, float4 right) => left.X == right.X && left.Y == right.Y && left.Z == right.Z && left.W == right.W;
|
||||
|
||||
public static bool operator !=(float4 left, float4 right) => left.X != right.X || left.Y != right.Y || left.Z != right.Z || left.W != right.W;
|
||||
|
||||
public override void ToString(String strBuffer) => strBuffer.AppendF("X:{0} Y:{1} Z:{2} W:{3}", X, Y, Z, W);
|
||||
|
||||
[Inline]
|
||||
public static explicit operator Self(float value) => Self(value);
|
||||
|
||||
[Inline]
|
||||
#unwarn
|
||||
public static explicit operator float[4](float4 value) => *(float[4]*)&value;
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
#pragma warning disable 4204
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace GlitchyEngine.Math
|
||||
{
|
||||
/**
|
||||
* A Vector with two components of type int32.
|
||||
*/
|
||||
[SwizzleVector(2, "Int")]
|
||||
public struct Int2 : IHashable
|
||||
{
|
||||
public const Int2 Zero = .(0, 0);
|
||||
public const Int2 UnitX = .(1, 0);
|
||||
public const Int2 UnitY = .(0, 1);
|
||||
public const Int2 One = .(1, 1);
|
||||
|
||||
public int32 X, Y;
|
||||
|
||||
public this() => this = default;
|
||||
|
||||
public this(int32 value)
|
||||
{
|
||||
X = value;
|
||||
Y = value;
|
||||
}
|
||||
|
||||
public this(int value)
|
||||
{
|
||||
X = (.)value;
|
||||
Y = (.)value;
|
||||
}
|
||||
|
||||
public this(int32 x, int32 y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public this(int x, int y)
|
||||
{
|
||||
X = (.)x;
|
||||
Y = (.)y;
|
||||
}
|
||||
|
||||
public ref int32 this[int index]
|
||||
{
|
||||
[Inline]
|
||||
get
|
||||
{
|
||||
#if DEBUG
|
||||
if(index < 0 || index >= 2)
|
||||
Internal.ThrowIndexOutOfRange(1);
|
||||
#endif
|
||||
|
||||
return ref (&X)[index];
|
||||
}
|
||||
}
|
||||
|
||||
public int32 MagnitudeSquared() => X * X + Y * Y;
|
||||
|
||||
public float Magnitude() => Math.Sqrt(X * X + Y * Y);
|
||||
|
||||
public Int2 Abs() => .(Math.Abs(X), Math.Abs(Y));
|
||||
|
||||
//
|
||||
// Assignment operators
|
||||
//
|
||||
|
||||
public void operator +=(Int2 value) mut
|
||||
{
|
||||
X += value.X;
|
||||
Y += value.Y;
|
||||
}
|
||||
|
||||
public void operator +=(int32 value) mut
|
||||
{
|
||||
X += value;
|
||||
Y += value;
|
||||
}
|
||||
|
||||
public void operator -=(Int2 value) mut
|
||||
{
|
||||
X -= value.X;
|
||||
Y -= value.Y;
|
||||
}
|
||||
|
||||
public void operator -=(int32 value) mut
|
||||
{
|
||||
X -= value;
|
||||
Y -= value;
|
||||
}
|
||||
|
||||
public void operator *=(Int2 value) mut
|
||||
{
|
||||
X *= value.X;
|
||||
Y *= value.Y;
|
||||
}
|
||||
|
||||
public void operator *=(int32 value) mut
|
||||
{
|
||||
X *= value;
|
||||
Y *= value;
|
||||
}
|
||||
|
||||
public void operator /=(Int2 value) mut
|
||||
{
|
||||
X /= value.X;
|
||||
Y /= value.Y;
|
||||
}
|
||||
|
||||
public void operator /=(int32 value) mut
|
||||
{
|
||||
X /= value;
|
||||
Y /= value;
|
||||
}
|
||||
|
||||
// Operators
|
||||
|
||||
public static Int2 operator +(Int2 value) => value;
|
||||
public static Int2 operator +(Int2 left, Int2 right) => .(left.X + right.X, left.Y + right.Y);
|
||||
public static Int2 operator +(Int2 left, int32 right) => .(left.X + right, left.Y + right);
|
||||
public static Int2 operator +(int32 left, Int2 right) => .(left + right.X, left + right.Y);
|
||||
|
||||
public static Int2 operator -(Int2 value) => .(-value.X, -value.Y);
|
||||
public static Int2 operator -(Int2 left, Int2 right) => .(left.X - right.X, left.Y - right.Y);
|
||||
public static Int2 operator -(Int2 left, int32 right) => .(left.X - right, left.Y - right);
|
||||
public static Int2 operator -(int32 left, Int2 right) => .(left - right.X, left - right.Y);
|
||||
|
||||
public static Int2 operator *(Int2 left, Int2 right) => .(left.X * right.X, left.Y * right.Y);
|
||||
public static Int2 operator *(Int2 left, int32 right) => .(left.X * right, left.Y * right);
|
||||
public static Int2 operator *(int32 left, Int2 right) => .(left * right.X, left * right.Y);
|
||||
|
||||
public static Int2 operator /(Int2 left, Int2 right) => .(left.X / right.X, left.Y / right.Y);
|
||||
public static Int2 operator /(Int2 left, int32 right) => .(left.X / right, left.Y / right);
|
||||
public static Int2 operator /(int32 left, Int2 right) => .(left / right.X, left / right.Y);
|
||||
|
||||
public static Int2 operator %(Int2 left, Int2 right) => .(left.X % right.X, left.Y % right.Y);
|
||||
public static Int2 operator %(Int2 left, int32 right) => .(left.X % right, left.Y % right);
|
||||
public static Int2 operator %(int32 left, Int2 right) => .(left % right.X, left % right.Y);
|
||||
|
||||
public static bool operator ==(Int2 left, Int2 right) => left.X == right.X && left.Y == right.Y;
|
||||
public static bool operator ==(Int2 left, int32 right) => left.X == right && left.Y == right;
|
||||
public static bool operator ==(int32 left, Int2 right) => left == right.X && left == right.Y;
|
||||
|
||||
public static bool operator !=(Int2 left, Int2 right) => left.X != right.X || left.Y != right.Y;
|
||||
public static bool operator !=(Int2 left, int32 right) => left.X != right || left.Y != right;
|
||||
public static bool operator !=(int32 left, Int2 right) => left != right.X || left != right.Y;
|
||||
|
||||
public override void ToString(String strBuffer) => strBuffer.AppendF($"X:{X} Y:{Y}");
|
||||
|
||||
public static explicit operator float2(Int2 point) => .(point.X, point.Y);
|
||||
|
||||
public static explicit operator Int2(float2 point) => .((int32)point.X, (int32)point.Y);
|
||||
|
||||
public int GetHashCode()
|
||||
{
|
||||
return (X * 39) ^ Y;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,206 +0,0 @@
|
||||
#pragma warning disable 4204
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace GlitchyEngine.Math
|
||||
{
|
||||
/**
|
||||
* A Vector with three components of type int32.
|
||||
*/
|
||||
[SwizzleVector(3, "Int")]
|
||||
public struct Int3 : IHashable
|
||||
{
|
||||
public const Int3 Zero = .(0, 0, 0);
|
||||
public const Int3 UnitX = .(1, 0, 0);
|
||||
public const Int3 UnitY = .(0, 1, 0);
|
||||
public const Int3 UnitZ = .(0, 0, 1);
|
||||
public const Int3 One = .(1, 1, 1);
|
||||
|
||||
public int32 X, Y, Z;
|
||||
|
||||
public this() => this = default;
|
||||
|
||||
public this(int32 value)
|
||||
{
|
||||
X = value;
|
||||
Y = value;
|
||||
Z = value;
|
||||
}
|
||||
|
||||
public this(int value)
|
||||
{
|
||||
X = (.)value;
|
||||
Y = (.)value;
|
||||
Z = (.)value;
|
||||
}
|
||||
|
||||
public this(int32 x, int32 y, int32 z)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
public this(Int2 xy, int32 z)
|
||||
{
|
||||
X = xy.X;
|
||||
Y = xy.Y;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
public this(int32 x, Int2 yz)
|
||||
{
|
||||
X = x;
|
||||
Y = yz.X;
|
||||
Z = yz.Y;
|
||||
}
|
||||
|
||||
public this(int x, int y, int z)
|
||||
{
|
||||
X = (.)x;
|
||||
Y = (.)y;
|
||||
Z = (.)z;
|
||||
}
|
||||
|
||||
public this(Int2 xy, int z)
|
||||
{
|
||||
X = xy.X;
|
||||
Y = xy.Y;
|
||||
Z = (.)z;
|
||||
}
|
||||
|
||||
public this(int x, Int2 yz)
|
||||
{
|
||||
X = (.)x;
|
||||
Y = yz.X;
|
||||
Z = yz.Y;
|
||||
}
|
||||
|
||||
public ref int32 this[int index]
|
||||
{
|
||||
[Inline]
|
||||
get
|
||||
{
|
||||
#if DEBUG
|
||||
if(index < 0 || index >= 3)
|
||||
Internal.ThrowIndexOutOfRange(1);
|
||||
#endif
|
||||
|
||||
return ref (&X)[index];
|
||||
}
|
||||
}
|
||||
|
||||
public int32 MagnitudeSquared() => X * X + Y * Y + Z * Z;
|
||||
|
||||
public float Magnitude() => Math.Sqrt(X * X + Y * Y + Z * Z);
|
||||
|
||||
public Int3 Abs() => .(Math.Abs(X), Math.Abs(Y), Math.Abs(Z));
|
||||
|
||||
//
|
||||
// Assignment operators
|
||||
//
|
||||
|
||||
public void operator +=(Int3 value) mut
|
||||
{
|
||||
X += value.X;
|
||||
Y += value.Y;
|
||||
Z += value.Z;
|
||||
}
|
||||
|
||||
public void operator +=(int32 value) mut
|
||||
{
|
||||
X += value;
|
||||
Y += value;
|
||||
Z += value;
|
||||
}
|
||||
|
||||
public void operator -=(Int3 value) mut
|
||||
{
|
||||
X -= value.X;
|
||||
Y -= value.Y;
|
||||
Z -= value.Z;
|
||||
}
|
||||
|
||||
public void operator -=(int32 value) mut
|
||||
{
|
||||
X -= value;
|
||||
Y -= value;
|
||||
Z -= value;
|
||||
}
|
||||
|
||||
public void operator *=(Int3 value) mut
|
||||
{
|
||||
X *= value.X;
|
||||
Y *= value.Y;
|
||||
Z *= value.Z;
|
||||
}
|
||||
|
||||
public void operator *=(int32 value) mut
|
||||
{
|
||||
X *= value;
|
||||
Y *= value;
|
||||
Z *= value;
|
||||
}
|
||||
|
||||
public void operator /=(Int3 value) mut
|
||||
{
|
||||
X /= value.X;
|
||||
Y /= value.Y;
|
||||
Z /= value.Z;
|
||||
}
|
||||
|
||||
public void operator /=(int32 value) mut
|
||||
{
|
||||
X /= value;
|
||||
Y /= value;
|
||||
Z /= value;
|
||||
}
|
||||
|
||||
// Operators
|
||||
|
||||
public static Int3 operator +(Int3 value) => value;
|
||||
public static Int3 operator +(Int3 left, Int3 right) => .(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
|
||||
public static Int3 operator +(Int3 left, int32 right) => .(left.X + right, left.Y + right, left.Z + right);
|
||||
public static Int3 operator +(int32 left, Int3 right) => .(left + right.X, left + right.Y, left + right.Z);
|
||||
|
||||
public static Int3 operator -(Int3 value) => .(-value.X, -value.Y, -value.Z);
|
||||
public static Int3 operator -(Int3 left, Int3 right) => .(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
|
||||
public static Int3 operator -(Int3 left, int32 right) => .(left.X - right, left.Y - right, left.Z- right);
|
||||
public static Int3 operator -(int32 left, Int3 right) => .(left - right.X, left - right.Y, left - right.Z);
|
||||
|
||||
public static Int3 operator *(Int3 left, Int3 right) => .(left.X * right.X, left.Y * right.Y, left.Z * right.Z);
|
||||
public static Int3 operator *(Int3 left, int32 right) => .(left.X * right, left.Y * right, left.Z * right);
|
||||
public static Int3 operator *(int32 left, Int3 right) => .(left * right.X, left * right.Y, left * right.Z);
|
||||
|
||||
public static Int3 operator /(Int3 left, Int3 right) => .(left.X / right.X, left.Y / right.Y, left.Z / right.Z);
|
||||
public static Int3 operator /(Int3 left, int32 right) => .(left.X / right, left.Y / right, left.Z / right);
|
||||
public static Int3 operator /(int32 left, Int3 right) => .(left / right.X, left / right.Y, left / right.Z);
|
||||
|
||||
public static Int3 operator %(Int3 left, Int3 right) => .(left.X % right.X, left.Y % right.Y, left.Z % right.Z);
|
||||
public static Int3 operator %(Int3 left, int32 right) => .(left.X % right, left.Y % right, left.Z % right);
|
||||
public static Int3 operator %(int32 left, Int3 right) => .(left % right.X, left % right.Y, left % right.Z);
|
||||
|
||||
public static bool operator ==(Int3 left, Int3 right) => left.X == right.X && left.Y == right.Y && left.Z == right.Z;
|
||||
public static bool operator ==(Int3 left, int32 right) => left.X == right && left.Y == right && left.Z == right;
|
||||
public static bool operator ==(int32 left, Int3 right) => left == right.X && left == right.Y && left == right.Z;
|
||||
|
||||
public static bool operator !=(Int3 left, Int3 right) => left.X != right.X || left.Y != right.Y || left.Z != right.Z;
|
||||
public static bool operator !=(Int3 left, int32 right) => left.X != right || left.Y != right || left.Z != right;
|
||||
public static bool operator !=(int32 left, Int3 right) => left != right.X || left != right.Y || left != right.Z;
|
||||
|
||||
public override void ToString(String strBuffer) => strBuffer.AppendF($"X:{X} Y:{Y} Z:{Z}");
|
||||
|
||||
public static explicit operator float3(Int3 point) => .(point.X, point.Y, point.Z);
|
||||
|
||||
public static explicit operator Int3(float3 point) => .((int32)point.X, (int32)point.Y, (int32)point.Z);
|
||||
|
||||
[Inline]
|
||||
public static explicit operator Int2(in Int3 point) => *(Int2*)&point;
|
||||
|
||||
public int GetHashCode()
|
||||
{
|
||||
return (((X * 39) ^ Y) * 39) ^ Z;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
#pragma warning disable 4204
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace GlitchyEngine.Math
|
||||
{
|
||||
/**
|
||||
* A Vector with four components of type int32.
|
||||
*/
|
||||
[SwizzleVector(4, "Int")]
|
||||
public struct Int4 : IHashable
|
||||
{
|
||||
public const Int4 Zero = .(0, 0, 0, 0);
|
||||
public const Int4 UnitX = .(1, 0, 0, 0);
|
||||
public const Int4 UnitY = .(0, 1, 0, 0);
|
||||
public const Int4 UnitZ = .(0, 0, 1, 0);
|
||||
public const Int4 UnitW = .(0, 0, 0, 1);
|
||||
public const Int4 One = .(1, 1, 1, 1);
|
||||
|
||||
public int32 X, Y, Z, W;
|
||||
|
||||
public this() => this = default;
|
||||
|
||||
public this(int32 value)
|
||||
{
|
||||
X = value;
|
||||
Y = value;
|
||||
Z = value;
|
||||
W = value;
|
||||
}
|
||||
|
||||
public this(int value)
|
||||
{
|
||||
X = (.)value;
|
||||
Y = (.)value;
|
||||
Z = (.)value;
|
||||
W = (.)value;
|
||||
}
|
||||
|
||||
public this(int32 x, int32 y, int32 z, int32 w)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
W = w;
|
||||
}
|
||||
|
||||
public this(Int2 xy, int32 z, int32 w)
|
||||
{
|
||||
X = xy.X;
|
||||
Y = xy.Y;
|
||||
Z = z;
|
||||
W = w;
|
||||
}
|
||||
|
||||
public this(int32 x, Int2 yz, int32 w)
|
||||
{
|
||||
X = x;
|
||||
Y = yz.X;
|
||||
Z = yz.Y;
|
||||
W = w;
|
||||
}
|
||||
|
||||
public this(int32 x, int32 y, Int2 zw)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = zw.X;
|
||||
W = zw.Y;
|
||||
}
|
||||
|
||||
public this(Int2 xy, Int2 zw)
|
||||
{
|
||||
X = xy.X;
|
||||
Y = xy.Y;
|
||||
Z = zw.X;
|
||||
W = zw.Y;
|
||||
}
|
||||
|
||||
public this(Int3 xyz, int32 w)
|
||||
{
|
||||
X = xyz.X;
|
||||
Y = xyz.Y;
|
||||
Z = xyz.Z;
|
||||
W = w;
|
||||
}
|
||||
|
||||
public this(int32 x, Int3 yzw)
|
||||
{
|
||||
X = x;
|
||||
Y = yzw.X;
|
||||
Z = yzw.Y;
|
||||
W = yzw.Z;
|
||||
}
|
||||
|
||||
public ref int32 this[int index]
|
||||
{
|
||||
[Inline]
|
||||
get
|
||||
{
|
||||
#if DEBUG
|
||||
if(index < 0 || index >= 3)
|
||||
Internal.ThrowIndexOutOfRange(1);
|
||||
#endif
|
||||
|
||||
return ref (&X)[index];
|
||||
}
|
||||
}
|
||||
|
||||
public int32 MagnitudeSquared() => X * X + Y * Y + Z * Z + W * W;
|
||||
|
||||
public float Magnitude() => Math.Sqrt(X * X + Y * Y + Z * Z + W * W);
|
||||
|
||||
public Int4 Abs() => .(Math.Abs(X), Math.Abs(Y), Math.Abs(Z), Math.Abs(W));
|
||||
|
||||
//
|
||||
// Assignment operators
|
||||
//
|
||||
|
||||
public void operator +=(Int4 value) mut
|
||||
{
|
||||
X += value.X;
|
||||
Y += value.Y;
|
||||
Z += value.Z;
|
||||
W += value.W;
|
||||
}
|
||||
|
||||
public void operator +=(int32 value) mut
|
||||
{
|
||||
X += value;
|
||||
Y += value;
|
||||
Z += value;
|
||||
W += value;
|
||||
}
|
||||
|
||||
public void operator -=(Int4 value) mut
|
||||
{
|
||||
X -= value.X;
|
||||
Y -= value.Y;
|
||||
Z -= value.Z;
|
||||
W -= value.W;
|
||||
}
|
||||
|
||||
public void operator -=(int32 value) mut
|
||||
{
|
||||
X -= value;
|
||||
Y -= value;
|
||||
Z -= value;
|
||||
W -= value;
|
||||
}
|
||||
|
||||
public void operator *=(Int4 value) mut
|
||||
{
|
||||
X *= value.X;
|
||||
Y *= value.Y;
|
||||
Z *= value.Z;
|
||||
W *= value.W;
|
||||
}
|
||||
|
||||
public void operator *=(int32 value) mut
|
||||
{
|
||||
X *= value;
|
||||
Y *= value;
|
||||
Z *= value;
|
||||
W *= value;
|
||||
}
|
||||
|
||||
public void operator /=(Int4 value) mut
|
||||
{
|
||||
X /= value.X;
|
||||
Y /= value.Y;
|
||||
Z /= value.Z;
|
||||
W /= value.W;
|
||||
}
|
||||
|
||||
public void operator /=(int32 value) mut
|
||||
{
|
||||
X /= value;
|
||||
Y /= value;
|
||||
Z /= value;
|
||||
W /= value;
|
||||
}
|
||||
|
||||
// Operators
|
||||
|
||||
public static Int4 operator +(Int4 value) => value;
|
||||
public static Int4 operator +(Int4 left, Int4 right) => .(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W);
|
||||
public static Int4 operator +(Int4 left, int32 right) => .(left.X + right, left.Y + right, left.Z + right, left.W + right);
|
||||
public static Int4 operator +(int32 left, Int4 right) => .(left + right.X, left + right.Y, left + right.Z, left + right.W);
|
||||
|
||||
public static Int4 operator -(Int4 value) => .(-value.X, -value.Y, -value.Z, -value.W);
|
||||
public static Int4 operator -(Int4 left, Int4 right) => .(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W);
|
||||
public static Int4 operator -(Int4 left, int32 right) => .(left.X - right, left.Y - right, left.Z - right, left.W - right);
|
||||
public static Int4 operator -(int32 left, Int4 right) => .(left - right.X, left - right.Y, left - right.Z, left - right.W);
|
||||
|
||||
public static Int4 operator *(Int4 left, Int4 right) => .(left.X * right.X, left.Y * right.Y, left.Z * right.Z, left.W * right.W);
|
||||
public static Int4 operator *(Int4 left, int32 right) => .(left.X * right, left.Y * right, left.Z * right, left.W * right);
|
||||
public static Int4 operator *(int32 left, Int4 right) => .(left * right.X, left * right.Y, left * right.Z, left * right.W);
|
||||
|
||||
public static Int4 operator /(Int4 left, Int4 right) => .(left.X / right.X, left.Y / right.Y, left.Z / right.Z, left.W / right.W);
|
||||
public static Int4 operator /(Int4 left, int32 right) => .(left.X / right, left.Y / right, left.Z / right, left.W / right);
|
||||
public static Int4 operator /(int32 left, Int4 right) => .(left / right.X, left / right.Y, left / right.Z, left / right.W);
|
||||
|
||||
public static Int4 operator %(Int4 left, Int4 right) => .(left.X % right.X, left.Y % right.Y, left.Z % right.Z, left.W % right.W);
|
||||
public static Int4 operator %(Int4 left, int32 right) => .(left.X % right, left.Y % right, left.Z % right, left.W % right);
|
||||
public static Int4 operator %(int32 left, Int4 right) => .(left % right.X, left % right.Y, left % right.Z, left % right.W);
|
||||
|
||||
public static bool operator ==(Int4 left, Int4 right) => left.X == right.X && left.Y == right.Y && left.Z == right.Z && left.W == right.W;
|
||||
public static bool operator ==(Int4 left, int32 right) => left.X == right && left.Y == right && left.Z == right && left.W == right;
|
||||
public static bool operator ==(int32 left, Int4 right) => left == right.X && left == right.Y && left == right.Z && left == right.W;
|
||||
|
||||
public static bool operator !=(Int4 left, Int4 right) => left.X != right.X || left.Y != right.Y || left.Z != right.Z || left.W != right.W;
|
||||
public static bool operator !=(Int4 left, int32 right) => left.X != right || left.Y != right || left.Z != right || left.W != right;
|
||||
public static bool operator !=(int32 left, Int4 right) => left != right.X || left != right.Y || left != right.Z || left != right.W;
|
||||
|
||||
public override void ToString(String strBuffer) => strBuffer.AppendF($"X:{X} Y:{Y} Z:{Z} W:{W}");
|
||||
|
||||
public static explicit operator float4(Int4 point) => .(point.X, point.Y, point.Z, point.W);
|
||||
|
||||
public static explicit operator Int4(float4 point) => .((int32)point.X, (int32)point.Y, (int32)point.Z, (int32)point.W);
|
||||
|
||||
[Inline]
|
||||
public static explicit operator Int2(in Int4 point) => *(Int2*)&point;
|
||||
|
||||
[Inline]
|
||||
public static explicit operator Int3(in Int4 point) => *(Int3*)&point;
|
||||
|
||||
public int GetHashCode()
|
||||
{
|
||||
return (((((X * 39) ^ Y) * 39) ^ Z) * 39) ^ W;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using Bon;
|
||||
using System;
|
||||
|
||||
namespace GlitchyEngine.Math;
|
||||
|
||||
[BonTarget]
|
||||
[Vector<double, 2>]
|
||||
[ComparableVector<double, 2>]
|
||||
[VectorMath<double, 2>]
|
||||
[SwizzleVector(2, "GlitchyEngine.Math.double")]
|
||||
public struct double2
|
||||
{
|
||||
public const double2 Zero = .(0, 0);
|
||||
public const double2 UnitX = .(1, 0);
|
||||
public const double2 UnitY = .(0, 1);
|
||||
public const double2 One = .(1, 1);
|
||||
|
||||
public static explicit operator int2(double2 value)
|
||||
{
|
||||
return int2((int32)value.X, (int32)value.Y);
|
||||
}
|
||||
|
||||
public static explicit operator uint2(double2 value)
|
||||
{
|
||||
return uint2((uint32)value.X, (uint32)value.Y);
|
||||
}
|
||||
|
||||
public static explicit operator half2(double2 value)
|
||||
{
|
||||
return half2((half)value.X, (half)value.Y);
|
||||
}
|
||||
|
||||
public static explicit operator float2(double2 value)
|
||||
{
|
||||
return float2((float)value.X, (float)value.Y);
|
||||
}
|
||||
}
|
||||
|
||||
[BonTarget]
|
||||
[Vector<double, 3>]
|
||||
[ComparableVector<double, 3>]
|
||||
[VectorMath<double, 3>]
|
||||
[SwizzleVector(3, "GlitchyEngine.Math.double")]
|
||||
public struct double3
|
||||
{
|
||||
public const double3 Zero = .(0, 0, 0);
|
||||
public const double3 UnitX = .(1, 0, 0);
|
||||
public const double3 UnitY = .(0, 1, 0);
|
||||
public const double3 UnitZ = .(0, 0, 1);
|
||||
public const double3 One = .(1, 1, 1);
|
||||
|
||||
public const double3 Forward = .(0, 0, 1);
|
||||
public const double3 Backward = .(0, 0, -1);
|
||||
public const double3 Left = .(-1, 0, 0);
|
||||
public const double3 Right = .(1, 0, 0);
|
||||
public const double3 Up = .(0, 1, 0);
|
||||
public const double3 Down = .(0, -1, 0);
|
||||
|
||||
public static explicit operator int3(double3 value)
|
||||
{
|
||||
return int3((int32)value.X, (int32)value.Y, (int32)value.Z);
|
||||
}
|
||||
|
||||
public static explicit operator uint3(double3 value)
|
||||
{
|
||||
return uint3((uint32)value.X, (uint32)value.Y, (uint32)value.Z);
|
||||
}
|
||||
|
||||
public static explicit operator half3(double3 value)
|
||||
{
|
||||
return half3((half)(float)value.X, (half)(float)value.Y, (half)(float)value.Z);
|
||||
}
|
||||
|
||||
public static explicit operator float3(double3 value)
|
||||
{
|
||||
return float3((float)value.X, (float)value.Y, (float)value.Z);
|
||||
}
|
||||
}
|
||||
|
||||
[BonTarget]
|
||||
[Vector<double, 4>]
|
||||
[ComparableVector<double, 4>]
|
||||
[VectorMath<double, 4>]
|
||||
[SwizzleVector(4, "GlitchyEngine.Math.double")]
|
||||
public struct double4
|
||||
{
|
||||
public const double4 Zero = .(0, 0, 0, 0);
|
||||
public const double4 UnitX = .(1, 0, 0, 0);
|
||||
public const double4 UnitY = .(0, 1, 0, 0);
|
||||
public const double4 UnitZ = .(0, 0, 1, 0);
|
||||
public const double4 UnitW = .(0, 0, 0, 1);
|
||||
public const double4 One = .(1, 1, 1, 1);
|
||||
|
||||
public static explicit operator int4(double4 value)
|
||||
{
|
||||
return int4((int32)value.X, (int32)value.Y, (int32)value.Z, (int32)value.W);
|
||||
}
|
||||
|
||||
public static explicit operator uint4(double4 value)
|
||||
{
|
||||
return uint4((uint32)value.X, (uint32)value.Y, (uint32)value.Z, (uint32)value.W);
|
||||
}
|
||||
|
||||
public static explicit operator half4(double4 value)
|
||||
{
|
||||
return half4((half)(float)value.X, (half)(float)value.Y, (half)(float)value.Z, (half)(float)value.W);
|
||||
}
|
||||
|
||||
public static explicit operator float4(double4 value)
|
||||
{
|
||||
return float4((float)value.X, (float)value.Y, (float)value.Z, (float)value.W);
|
||||
}
|
||||
}
|
||||
@@ -10,10 +10,20 @@ namespace GlitchyEngine.Math;
|
||||
[SwizzleVector(2, "GlitchyEngine.Math.int")]
|
||||
public struct int2
|
||||
{
|
||||
public const int2 Zero = .(0, 0);
|
||||
public const int2 UnitX = .(1, 0);
|
||||
public const int2 UnitY = .(0, 1);
|
||||
public const int2 One = .(1, 1);
|
||||
|
||||
public static implicit operator float2(int2 value)
|
||||
{
|
||||
return float2(value.X, value.Y);
|
||||
}
|
||||
|
||||
public static explicit operator uint2(int2 value)
|
||||
{
|
||||
return uint2((uint32)value.X, (uint32)value.Y);
|
||||
}
|
||||
}
|
||||
|
||||
[BonTarget]
|
||||
@@ -23,10 +33,21 @@ public struct int2
|
||||
[SwizzleVector(3, "GlitchyEngine.Math.int")]
|
||||
public struct int3
|
||||
{
|
||||
public const int3 Zero = .(0, 0, 0);
|
||||
public const int3 UnitX = .(1, 0, 0);
|
||||
public const int3 UnitY = .(0, 1, 0);
|
||||
public const int3 UnitZ = .(0, 0, 1);
|
||||
public const int3 One = .(1, 1, 1);
|
||||
|
||||
public static implicit operator float3(int3 value)
|
||||
{
|
||||
return float3(value.X, value.Y, value.Z);
|
||||
}
|
||||
|
||||
public static explicit operator uint3(int3 value)
|
||||
{
|
||||
return uint3((uint32)value.X, (uint32)value.Y, (uint32)value.Z);
|
||||
}
|
||||
}
|
||||
|
||||
[BonTarget]
|
||||
@@ -36,8 +57,92 @@ public struct int3
|
||||
[SwizzleVector(4, "GlitchyEngine.Math.int")]
|
||||
public struct int4
|
||||
{
|
||||
public const int4 Zero = .(0, 0, 0, 0);
|
||||
public const int4 UnitX = .(1, 0, 0, 0);
|
||||
public const int4 UnitY = .(0, 1, 0, 0);
|
||||
public const int4 UnitZ = .(0, 0, 1, 0);
|
||||
public const int4 UnitW = .(0, 0, 0, 1);
|
||||
public const int4 One = .(1, 1, 1, 1);
|
||||
|
||||
public static implicit operator float4(int4 value)
|
||||
{
|
||||
return float4(value.X, value.Y, value.Z, value.W);
|
||||
}
|
||||
}
|
||||
|
||||
public static explicit operator uint4(int4 value)
|
||||
{
|
||||
return uint4((uint32)value.X, (uint32)value.Y, (uint32)value.Z, (uint32)value.W);
|
||||
}
|
||||
}
|
||||
|
||||
[BonTarget]
|
||||
[Vector<uint32, 2>]
|
||||
[ComparableVector<uint32, 2>]
|
||||
//[VectorMath<uint32, 2>]
|
||||
[SwizzleVector(2, "GlitchyEngine.Math.uint")]
|
||||
public struct uint2
|
||||
{
|
||||
public const uint2 Zero = .(0, 0);
|
||||
public const uint2 UnitX = .(1, 0);
|
||||
public const uint2 UnitY = .(0, 1);
|
||||
public const uint2 One = .(1, 1);
|
||||
|
||||
public static implicit operator float2(uint2 value)
|
||||
{
|
||||
return float2(value.X, value.Y);
|
||||
}
|
||||
|
||||
public static explicit operator int2(uint2 value)
|
||||
{
|
||||
return int2((int32)value.X, (int32)value.Y);
|
||||
}
|
||||
}
|
||||
|
||||
[BonTarget]
|
||||
[Vector<uint32, 3>]
|
||||
[ComparableVector<uint32, 3>]
|
||||
//[VectorMath<uint32, 3>]
|
||||
[SwizzleVector(3, "GlitchyEngine.Math.uint")]
|
||||
public struct uint3
|
||||
{
|
||||
public const uint3 Zero = .(0, 0, 0);
|
||||
public const uint3 UnitX = .(1, 0, 0);
|
||||
public const uint3 UnitY = .(0, 1, 0);
|
||||
public const uint3 UnitZ = .(0, 0, 1);
|
||||
public const uint3 One = .(1, 1, 1);
|
||||
|
||||
public static implicit operator float3(uint3 value)
|
||||
{
|
||||
return float3(value.X, value.Y, value.Z);
|
||||
}
|
||||
|
||||
public static explicit operator int3(uint3 value)
|
||||
{
|
||||
return int3((int32)value.X, (int32)value.Y, (int32)value.Z);
|
||||
}
|
||||
}
|
||||
|
||||
[BonTarget]
|
||||
[Vector<uint32, 4>]
|
||||
[ComparableVector<uint32, 4>]
|
||||
//[VectorMath<uint32, 4>]
|
||||
[SwizzleVector(4, "GlitchyEngine.Math.uint")]
|
||||
public struct uint4
|
||||
{
|
||||
public const uint4 Zero = .(0, 0, 0, 0);
|
||||
public const uint4 UnitX = .(1, 0, 0, 0);
|
||||
public const uint4 UnitY = .(0, 1, 0, 0);
|
||||
public const uint4 UnitZ = .(0, 0, 1, 0);
|
||||
public const uint4 UnitW = .(0, 0, 0, 1);
|
||||
public const uint4 One = .(1, 1, 1, 1);
|
||||
|
||||
public static implicit operator float4(uint4 value)
|
||||
{
|
||||
return float4(value.X, value.Y, value.Z, value.W);
|
||||
}
|
||||
|
||||
public static explicit operator int4(uint4 value)
|
||||
{
|
||||
return int4((int32)value.X, (int32)value.Y, (int32)value.Z, (int32)value.W);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,7 +479,7 @@ namespace GlitchyEngine.Renderer
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
public override void CopyTo(RenderTargetGroup destination, int dstTarget, Int2 dstTopLeft, Int2 size, Int2 srcTopLeft, int srcTarget)
|
||||
public override void CopyTo(RenderTargetGroup destination, int dstTarget, int2 dstTopLeft, int2 size, int2 srcTopLeft, int srcTarget)
|
||||
{
|
||||
ID3D11Texture2D* dstTexture = destination.GetNativeTexture(dstTarget);
|
||||
ID3D11Texture2D* srcTexture = GetNativeTexture(srcTarget);
|
||||
|
||||
@@ -19,13 +19,13 @@ namespace GlitchyEngine
|
||||
//[CLink, CallingConvention(.Stdcall)]
|
||||
//static extern int16 GetKeyState(int32 keycode);
|
||||
[CLink, CallingConvention(.Stdcall)]
|
||||
static extern IntBool GetCursorPos(out Int2 p);
|
||||
static extern IntBool GetCursorPos(out int2 p);
|
||||
[CLink, CallingConvention(.Stdcall)]
|
||||
static extern IntBool SetCursorPos(c_int x, c_int y);
|
||||
[CLink, CallingConvention(.Stdcall)]
|
||||
static extern IntBool ScreenToClient(HWnd hWnd, ref Int2 p);
|
||||
static extern IntBool ScreenToClient(HWnd hWnd, ref int2 p);
|
||||
[CLink, CallingConvention(.Stdcall)]
|
||||
static extern IntBool ClientToScreen(HWnd hWnd, ref Int2 p);
|
||||
static extern IntBool ClientToScreen(HWnd hWnd, ref int2 p);
|
||||
|
||||
[Import("user32.lib"), CLink]
|
||||
public static extern IntBool RegisterRawInputDevices(RAWINPUTDEVICE* pRawInputDevices, uint32 uiNumDevices, uint32 cbSize);
|
||||
@@ -50,9 +50,9 @@ namespace GlitchyEngine
|
||||
struct WindowsInputState
|
||||
{
|
||||
public int8[256] KeyStates;
|
||||
public Int2 CursorPosition;
|
||||
public Int2 CursorPositionDifference;
|
||||
public Int2 RawCursorMovement;
|
||||
public int2 CursorPosition;
|
||||
public int2 CursorPositionDifference;
|
||||
public int2 RawCursorMovement;
|
||||
}
|
||||
|
||||
static WindowsInputState[2] IputStates;
|
||||
@@ -157,11 +157,11 @@ namespace GlitchyEngine
|
||||
|
||||
public override static bool IsMouseButtonReleasing(MouseButton button) => IsMouseButtonReleased(button) && WasMouseButtonPressed(button);
|
||||
|
||||
public override static Int2 GetMousePosition() => CurrentState.CursorPosition;
|
||||
public override static int2 GetMousePosition() => CurrentState.CursorPosition;
|
||||
|
||||
public override static Int2 GetMouseMovement() => CurrentState.CursorPositionDifference;
|
||||
public override static int2 GetMouseMovement() => CurrentState.CursorPositionDifference;
|
||||
|
||||
public override static Int2 GetRawMouseMovement() => CurrentState.RawCursorMovement;
|
||||
public override static int2 GetRawMouseMovement() => CurrentState.RawCursorMovement;
|
||||
|
||||
public override static int32 GetMouseX() => CurrentState.CursorPosition.X;
|
||||
|
||||
@@ -182,17 +182,17 @@ namespace GlitchyEngine
|
||||
return state >= 0;
|
||||
}
|
||||
|
||||
public override static Int2 GetLastMousePosition() => LastState.CursorPosition;
|
||||
public override static int2 GetLastMousePosition() => LastState.CursorPosition;
|
||||
|
||||
public override static Int2 GetLastMouseMovement() => LastState.CursorPositionDifference;
|
||||
public override static int2 GetLastMouseMovement() => LastState.CursorPositionDifference;
|
||||
|
||||
public override static Int2 GetLastRawMouseMovement() => LastState.RawCursorMovement;
|
||||
public override static int2 GetLastRawMouseMovement() => LastState.RawCursorMovement;
|
||||
|
||||
public override static int32 GetLastMouseX() => LastState.CursorPosition.X;
|
||||
|
||||
public override static int32 GetLastMouseY() => LastState.CursorPosition.Y;
|
||||
|
||||
public override static void SetMousePosition(Int2 pos)
|
||||
public override static void SetMousePosition(int2 pos)
|
||||
{
|
||||
HWnd windowHandle = (HWnd)(int)Application.Get().Window.NativeWindow;
|
||||
|
||||
|
||||
@@ -67,13 +67,13 @@ namespace GlitchyEngine
|
||||
//
|
||||
// Size
|
||||
//
|
||||
public override Int2 Size
|
||||
public override int2 Size
|
||||
{
|
||||
get => *(Int2*)&_clientRect.Width;
|
||||
get => *(int2*)&_clientRect.Width;
|
||||
|
||||
set
|
||||
{
|
||||
*(Int2*)&_clientRect.Width = value;
|
||||
*(int2*)&_clientRect.Width = value;
|
||||
ApplyRectangle();
|
||||
}
|
||||
}
|
||||
@@ -103,13 +103,13 @@ namespace GlitchyEngine
|
||||
//
|
||||
// Position
|
||||
//
|
||||
public override Int2 Position
|
||||
public override int2 Position
|
||||
{
|
||||
get => *(Int2*)&_clientRect;
|
||||
get => *(int2*)&_clientRect;
|
||||
|
||||
set
|
||||
{
|
||||
*(Int2*)&_clientRect = value;
|
||||
*(int2*)&_clientRect = value;
|
||||
ApplyRectangle();
|
||||
}
|
||||
}
|
||||
@@ -263,7 +263,7 @@ namespace GlitchyEngine
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
internal Int2 _rawMouseMovementAccumulator;
|
||||
internal int2 _rawMouseMovementAccumulator;
|
||||
|
||||
private static LRESULT MessageHandler(HWND hwnd, uint32 uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
@@ -478,7 +478,7 @@ namespace GlitchyEngine
|
||||
window._eventCallback(event);
|
||||
|
||||
// We accumulate the raw movements an collect them once each frame in WindowsInput.Impl_NewFrame()
|
||||
window._rawMouseMovementAccumulator += Int2(raw.Data.Mouse.lLastX, raw.Data.Mouse.lLastY);
|
||||
window._rawMouseMovementAccumulator += int2(raw.Data.Mouse.lLastX, raw.Data.Mouse.lLastY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,31 @@ namespace GlitchyEngine.Renderer
|
||||
{
|
||||
case typeof(bool):
|
||||
EnsureTypeMatch(1, 1, .Bool);
|
||||
case typeof(bool2):
|
||||
EnsureTypeMatch(1, 2, .Bool);
|
||||
case typeof(bool3):
|
||||
EnsureTypeMatch(1, 3, .Bool);
|
||||
case typeof(bool4):
|
||||
EnsureTypeMatch(1, 4, .Bool);
|
||||
|
||||
case typeof(int32):
|
||||
EnsureTypeMatch(1, 1, .Int);
|
||||
case typeof(int2):
|
||||
EnsureTypeMatch(1, 2, .Int);
|
||||
case typeof(int3):
|
||||
EnsureTypeMatch(1, 3, .Int);
|
||||
case typeof(int4):
|
||||
EnsureTypeMatch(1, 4, .Int);
|
||||
|
||||
case typeof(uint32):
|
||||
EnsureTypeMatch(1, 1, .UInt);
|
||||
case typeof(uint2):
|
||||
EnsureTypeMatch(1, 2, .UInt);
|
||||
case typeof(uint3):
|
||||
EnsureTypeMatch(1, 3, .UInt);
|
||||
case typeof(uint4):
|
||||
EnsureTypeMatch(1, 4, .UInt);
|
||||
|
||||
case typeof(float):
|
||||
EnsureTypeMatch(1, 1, .Float);
|
||||
case typeof(float2):
|
||||
@@ -87,18 +111,6 @@ namespace GlitchyEngine.Renderer
|
||||
case typeof(float4):
|
||||
EnsureTypeMatch(1, 4, .Float);
|
||||
|
||||
case typeof(int32):
|
||||
EnsureTypeMatch(1, 1, .Int);
|
||||
case typeof(Int2):
|
||||
EnsureTypeMatch(1, 2, .Int);
|
||||
case typeof(Int3):
|
||||
EnsureTypeMatch(1, 3, .Int);
|
||||
case typeof(Int4):
|
||||
EnsureTypeMatch(1, 4, .Int);
|
||||
|
||||
case typeof(uint32):
|
||||
EnsureTypeMatch(1, 1, .UInt);
|
||||
|
||||
case typeof(Matrix4x3):
|
||||
EnsureTypeMatch(4, 3, .Float);
|
||||
case typeof(Matrix3x3):
|
||||
@@ -130,19 +142,25 @@ namespace GlitchyEngine.Renderer
|
||||
}
|
||||
|
||||
public void SetData(bool value) => SetData<bool>(value);
|
||||
public void SetData(bool2 value) => SetData<bool2>(value);
|
||||
public void SetData(bool3 value) => SetData<bool3>(value);
|
||||
public void SetData(bool4 value) => SetData<bool4>(value);
|
||||
|
||||
public void SetData(int32 value) => SetData<int32>(value);
|
||||
public void SetData(int2 value) => SetData<int2>(value);
|
||||
public void SetData(int3 value) => SetData<int3>(value);
|
||||
public void SetData(int4 value) => SetData<int4>(value);
|
||||
|
||||
public void SetData(uint32 value) => SetData<uint32>(value);
|
||||
public void SetData(uint2 value) => SetData<uint2>(value);
|
||||
public void SetData(uint3 value) => SetData<uint3>(value);
|
||||
public void SetData(uint4 value) => SetData<uint4>(value);
|
||||
|
||||
public void SetData(float value) => SetData<float>(value);
|
||||
public void SetData(float2 value) => SetData<float2>(value);
|
||||
public void SetData(float3 value) => SetData<float3>(value);
|
||||
public void SetData(float4 value) => SetData<float4>(value);
|
||||
|
||||
public void SetData(int32 value) => SetData<int32>(value);
|
||||
public void SetData(Int2 value) => SetData<Int2>(value);
|
||||
public void SetData(Int3 value) => SetData<Int3>(value);
|
||||
public void SetData(Int4 value) => SetData<Int4>(value);
|
||||
|
||||
public void SetData(uint32 value) => SetData<uint32>(value);
|
||||
|
||||
public void SetData(ColorRGB value) => SetData<ColorRGB>(value);
|
||||
public void SetData(ColorRGBA value) => SetData<ColorRGBA>(value);
|
||||
public void SetData(Color value) => SetData<ColorRGBA>((ColorRGBA)value);
|
||||
|
||||
@@ -53,4 +53,57 @@ namespace GlitchyEngine.Renderer
|
||||
RenderCommand.DrawIndexed(s_fullscreenQuadGeometry);
|
||||
}
|
||||
}
|
||||
|
||||
static class Quad
|
||||
{
|
||||
static GeometryBinding s_quadGeometry;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
s_quadGeometry = new GeometryBinding();
|
||||
s_quadGeometry.SetPrimitiveTopology(.TriangleList);
|
||||
|
||||
using(var quadVertices = new VertexBuffer(typeof(float4), 4, .Immutable))
|
||||
{
|
||||
float4[4] vertices = .(
|
||||
.(-0.5f,-0.5f, 0, 1),
|
||||
.(-0.5f, 0.5f, 0, 0),
|
||||
.( 0.5f, 0.5f, 1, 0),
|
||||
.( 0.5f,-0.5f, 1, 1)
|
||||
);
|
||||
|
||||
quadVertices.SetData(vertices);
|
||||
s_quadGeometry.SetVertexBufferSlot(quadVertices, 0);
|
||||
}
|
||||
|
||||
using(var quadIndices = new IndexBuffer(6, .Immutable))
|
||||
{
|
||||
uint16[6] indices = .(0, 1, 2, 2, 3, 0);
|
||||
|
||||
quadIndices.SetData(indices);
|
||||
s_quadGeometry.SetIndexBuffer(quadIndices);
|
||||
}
|
||||
|
||||
VertexElement[] vertexElements = new .(
|
||||
VertexElement(.R32G32_Float, "POSITION"),
|
||||
VertexElement(.R32G32_Float, "TEXCOORD")
|
||||
);
|
||||
|
||||
using (var quadBatchLayout = new VertexLayout(vertexElements, true))
|
||||
{
|
||||
s_quadGeometry.SetVertexLayout(quadBatchLayout);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Deinit()
|
||||
{
|
||||
s_quadGeometry.ReleaseRef();
|
||||
}
|
||||
|
||||
public static void Draw()
|
||||
{
|
||||
s_quadGeometry.Bind();
|
||||
RenderCommand.DrawIndexed(s_quadGeometry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -144,17 +144,30 @@ public class Material : Asset
|
||||
}
|
||||
}
|
||||
|
||||
public void SetVariable(String name, bool value) => SetVariable<bool>(name, value);
|
||||
public void SetVariable(String name, bool2 value) => SetVariable<bool2>(name, value);
|
||||
public void SetVariable(String name, bool3 value) => SetVariable<bool3>(name, value);
|
||||
public void SetVariable(String name, bool4 value) => SetVariable<bool4>(name, value);
|
||||
|
||||
public void SetVariable(String name, int32 value) => SetVariable<int32>(name, value);
|
||||
public void SetVariable(String name, int2 value) => SetVariable<int2>(name, value);
|
||||
public void SetVariable(String name, int3 value) => SetVariable<int3>(name, value);
|
||||
public void SetVariable(String name, int4 value) => SetVariable<int4>(name, value);
|
||||
|
||||
public void SetVariable(String name, uint32 value) => SetVariable<uint32>(name, value);
|
||||
public void SetVariable(String name, uint2 value) => SetVariable<uint2>(name, value);
|
||||
public void SetVariable(String name, uint3 value) => SetVariable<uint3>(name, value);
|
||||
public void SetVariable(String name, uint4 value) => SetVariable<uint4>(name, value);
|
||||
|
||||
public void SetVariable(String name, float value) => SetVariable<float>(name, value);
|
||||
public void SetVariable(String name, float2 value) => SetVariable<float2>(name, value);
|
||||
public void SetVariable(String name, float3 value) => SetVariable<float3>(name, value);
|
||||
public void SetVariable(String name, float4 value) => SetVariable<float4>(name, value);
|
||||
|
||||
public void SetVariable(String name, int32 value) => SetVariable<int32>(name, value);
|
||||
public void SetVariable(String name, Int2 value) => SetVariable<Int2>(name, value);
|
||||
public void SetVariable(String name, Int3 value) => SetVariable<Int3>(name, value);
|
||||
public void SetVariable(String name, Int4 value) => SetVariable<Int4>(name, value);
|
||||
|
||||
public void SetVariable(String name, uint32 value) => SetVariable<uint32>(name, value);
|
||||
/*public void SetVariable(String name, float value) => SetVariable<double>(name, value);
|
||||
public void SetVariable(String name, float2 value) => SetVariable<float2>(name, value);
|
||||
public void SetVariable(String name, float3 value) => SetVariable<float3>(name, value);
|
||||
public void SetVariable(String name, float4 value) => SetVariable<float4>(name, value);*/
|
||||
|
||||
public void SetVariable(String name, Color value) => SetVariable<ColorRGBA>(name, (ColorRGBA)value);
|
||||
public void SetVariable(String name, ColorRGB value) => SetVariable<ColorRGB>(name, value);
|
||||
@@ -216,15 +229,14 @@ public class Material : Asset
|
||||
}
|
||||
|
||||
// Supporeted types
|
||||
// Float, Float2, Float3, Float4
|
||||
// Bool, Bool2, Bool3, Bool4
|
||||
// Int, int2, int3, int4
|
||||
// UInt, UInt2, UInt3, UInt4
|
||||
// Color, ColorRGB, ColorRGBA
|
||||
// Int, Int2, Int3, Int4
|
||||
// UInt
|
||||
// Float, Float2, Float3, Float4
|
||||
// Matrix3x3, Matrix4x3, Matrix
|
||||
|
||||
// TODO: Add missing variable types
|
||||
// UInt2, UInt3, UInt4
|
||||
// Bool, Bool2, Bool3, Bool4
|
||||
// Half, Half2, Half3, Half4
|
||||
// Byte, Byte2, Byte3, Byte4
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ using GlitchyEngine.Core;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using GlitchyEngine.Math;
|
||||
using GlitchyEngine.Content;
|
||||
|
||||
namespace GlitchyEngine.Renderer
|
||||
{
|
||||
@@ -107,6 +108,28 @@ namespace GlitchyEngine.Renderer
|
||||
case Depth = D24_UNorm_S8_UInt;
|
||||
|
||||
public bool IsDepth => HasFlag(DepthMarker);
|
||||
|
||||
public bool IsInt()
|
||||
{
|
||||
switch(this)
|
||||
{
|
||||
case R8_SInt:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsUInt()
|
||||
{
|
||||
switch(this)
|
||||
{
|
||||
case R32_UInt:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum ClearColor
|
||||
@@ -129,7 +152,7 @@ namespace GlitchyEngine.Renderer
|
||||
}
|
||||
}
|
||||
|
||||
public struct TargetDescription
|
||||
public struct TargetDescription : IDisposable
|
||||
{
|
||||
public RenderTargetFormat Format = .None;
|
||||
|
||||
@@ -140,22 +163,30 @@ namespace GlitchyEngine.Renderer
|
||||
public ClearColor ClearColor = .Default;
|
||||
|
||||
public SamplerStateDescription SamplerDescription = .();
|
||||
|
||||
public String DebugName = null;
|
||||
|
||||
public this() { }
|
||||
|
||||
public this(RenderTargetFormat format, bool isSwapchainTarget = false, bool isShaderReadable = true, ClearColor clearColor = .Default, SamplerStateDescription samplerDescription = .())
|
||||
public this(RenderTargetFormat format, bool isSwapchainTarget = false, bool isShaderReadable = true, ClearColor clearColor = .Default, SamplerStateDescription samplerDescription = .(), String ownDebugName = null)
|
||||
{
|
||||
Format = format;
|
||||
IsSwapchainTarget = isSwapchainTarget;
|
||||
IsShaderReadable = isShaderReadable;
|
||||
SamplerDescription = samplerDescription;
|
||||
ClearColor = clearColor;
|
||||
DebugName = ownDebugName;
|
||||
}
|
||||
|
||||
public static implicit operator Self(RenderTargetFormat format)
|
||||
{
|
||||
return Self(format);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
delete DebugName;
|
||||
}
|
||||
}
|
||||
|
||||
public struct RenderTargetGroupDescription
|
||||
@@ -181,15 +212,22 @@ namespace GlitchyEngine.Renderer
|
||||
}
|
||||
}
|
||||
|
||||
public class RenderTargetGroup : RefCounter
|
||||
public class RenderTargetGroup : Asset
|
||||
{
|
||||
internal RenderTargetGroupDescription _description;
|
||||
|
||||
internal TargetDescription[] _colorTargetDescriptions ~ delete _;
|
||||
internal TargetDescription[] _colorTargetDescriptions ~ {
|
||||
for (var desc in _)
|
||||
{
|
||||
desc.Dispose();
|
||||
}
|
||||
|
||||
delete _;
|
||||
};
|
||||
internal SamplerState[] _colorSamplerStates ~ DeleteContainerAndReleaseItems!(_);
|
||||
internal SamplerState _depthSamplerState ~ _?.ReleaseRef();
|
||||
|
||||
internal TargetDescription _depthTargetDescription;
|
||||
internal TargetDescription _depthTargetDescription ~ _.Dispose();
|
||||
|
||||
public uint32 Width => _description.Width;
|
||||
public uint32 Height => _description.Height;
|
||||
@@ -201,6 +239,8 @@ namespace GlitchyEngine.Renderer
|
||||
public int TargetCount => _colorTargetDescriptions.Count + (_depthTargetDescription.Format.IsDepth ? 1 : 0);
|
||||
public int ColorTargetCount => _colorTargetDescriptions.Count;
|
||||
|
||||
public bool HasDepth => _depthTargetDescription.Format.IsDepth;
|
||||
|
||||
[AllowAppend]
|
||||
public this(RenderTargetGroupDescription description)
|
||||
{
|
||||
@@ -265,6 +305,18 @@ namespace GlitchyEngine.Renderer
|
||||
return PlatformGetViewBinding(index);
|
||||
}
|
||||
|
||||
public TargetDescription GetTargetDescription(int index)
|
||||
{
|
||||
if (index == -1 && HasDepth)
|
||||
{
|
||||
return _depthTargetDescription;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _colorTargetDescriptions[index];
|
||||
}
|
||||
}
|
||||
|
||||
protected extern TextureViewBinding PlatformGetViewBinding(int index);
|
||||
|
||||
protected extern Result<void> PlatformGetData(void* destination, uint32 elementSize,
|
||||
@@ -278,6 +330,6 @@ namespace GlitchyEngine.Renderer
|
||||
return PlatformGetData(data, (.)sizeof(T), left, top, width, height, renderTarget, arraySlice, mipSlice);
|
||||
}
|
||||
|
||||
public extern void CopyTo(RenderTargetGroup destination, int dstTarget, Int2 dstTopLeft, Int2 size, Int2 srcTopLeft, int srcTarget);
|
||||
public extern void CopyTo(RenderTargetGroup destination, int dstTarget, int2 dstTopLeft, int2 size, int2 srcTopLeft, int srcTarget);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace GlitchyEngine.Renderer
|
||||
public uint32 Width => _width;
|
||||
public uint32 Height => _height;
|
||||
|
||||
public Int2 Size => .(_width, _height);
|
||||
public uint2 Size => .(_width, _height);
|
||||
|
||||
public RenderTargetGroup Target ~ _?.ReleaseRef();
|
||||
|
||||
@@ -47,25 +47,28 @@ namespace GlitchyEngine.Renderer
|
||||
RenderTargetGroupDescription targetDesc = .(width, height,
|
||||
TargetDescription[](
|
||||
// RGB: Albedo A: Transparency
|
||||
.(RenderTargetFormat.R8G8B8A8_UNorm){SamplerDescription = samplerDesc},
|
||||
.(RenderTargetFormat.R8G8B8A8_UNorm, ownDebugName: new String("RGB: Albedo A: Alpha")){SamplerDescription = samplerDesc},
|
||||
// RG: TextureNormal.XY | BA: GeoNrm.XY
|
||||
.(RenderTargetFormat.R16G16B16A16_SNorm){SamplerDescription = samplerDesc},
|
||||
.(RenderTargetFormat.R16G16B16A16_SNorm, ownDebugName: new String("RG: TextureNormal.XY | BA: GeoNrm.XY")){SamplerDescription = samplerDesc},
|
||||
// R: GeoNrm.Z | GBA: GeoTan.XYZ
|
||||
.(RenderTargetFormat.R16G16B16A16_SNorm){SamplerDescription = samplerDesc},
|
||||
.(RenderTargetFormat.R16G16B16A16_SNorm, ownDebugName: new String("R: GeoNrm.Z | GBA: GeoTan.XYZ")){SamplerDescription = samplerDesc},
|
||||
// RGB: world position XYZ | A: 1.0
|
||||
.(RenderTargetFormat.R32G32B32A32_Float){SamplerDescription = samplerDesc},
|
||||
.(RenderTargetFormat.R32G32B32A32_Float, ownDebugName: new String("RGB: world position XYZ | A: 1.0")){SamplerDescription = samplerDesc},
|
||||
// RGB: emissive light and color | A: unused
|
||||
.(RenderTargetFormat.R16G16B16A16_Float){SamplerDescription = samplerDesc},
|
||||
.(RenderTargetFormat.R16G16B16A16_Float, ownDebugName: new String("RGB: emissive light and color | A: unused")){SamplerDescription = samplerDesc},
|
||||
// R: Metallicity | G: Roughness | B: Ambient | A: Unused
|
||||
.(RenderTargetFormat.R8G8B8A8_UNorm){SamplerDescription = samplerDesc},
|
||||
.(RenderTargetFormat.R8G8B8A8_UNorm, ownDebugName: new String("R: Metallicity | G: Roughness | B: Ambient | A: Unused")){SamplerDescription = samplerDesc},
|
||||
// EntityId : Needed for editor picking. Simply pass through the EntityId.
|
||||
.(RenderTargetFormat.R32_UInt){SamplerDescription = samplerDesc, ClearColor = .UInt(uint32.MaxValue)},
|
||||
.(RenderTargetFormat.R32_UInt, ownDebugName: new String("EntityId")){SamplerDescription = samplerDesc, ClearColor = .UInt(uint32.MaxValue)},
|
||||
),
|
||||
TargetDescription(.D24_UNorm_S8_UInt){
|
||||
TargetDescription(.D24_UNorm_S8_UInt, ownDebugName: new String("DepthStencil")){
|
||||
SamplerDescription = samplerDesc,
|
||||
ClearColor = .DepthStencil(1.0f, 0)
|
||||
});
|
||||
Target = new RenderTargetGroup(targetDesc);
|
||||
// TODO: there needs to be a proper way to do it
|
||||
Target.[Friend]Identifier = "GBuffer";
|
||||
Content.ManageAsset(Target, null);
|
||||
}
|
||||
|
||||
_width = width;
|
||||
@@ -120,6 +123,7 @@ namespace GlitchyEngine.Renderer
|
||||
RenderCommand.Init();
|
||||
Renderer2D.Init();
|
||||
FullscreenQuad.Init();
|
||||
Quad.Init();
|
||||
|
||||
InitLineRenderer();
|
||||
InitDeferredRenderer();
|
||||
@@ -135,6 +139,7 @@ namespace GlitchyEngine.Renderer
|
||||
|
||||
FullscreenQuad.Deinit();
|
||||
Renderer2D.Deinit();
|
||||
Quad.Deinit();
|
||||
}
|
||||
|
||||
static void InitLineRenderer()
|
||||
@@ -301,7 +306,6 @@ namespace GlitchyEngine.Renderer
|
||||
|
||||
RenderCommand.SetBlendState(_gBufferBlend);
|
||||
|
||||
|
||||
for (SubmittedMesh entry in _queue)
|
||||
{
|
||||
Debug.Profiler.ProfileRendererScope!("Draw Mesh");
|
||||
@@ -378,7 +382,7 @@ namespace GlitchyEngine.Renderer
|
||||
_lights.Clear();
|
||||
|
||||
// Copy EntityIDs to compositionTarget
|
||||
_gBuffer.Target.CopyTo(_sceneConstants.CompositionTarget, 1, Int2.Zero, Int2(_sceneConstants.CameraTarget.Width, _sceneConstants.CameraTarget.Height), Int2.Zero, 6);
|
||||
_gBuffer.Target.CopyTo(_sceneConstants.CompositionTarget, 1, int2.Zero, int2((int32)_sceneConstants.CameraTarget.Width, (int32)_sceneConstants.CameraTarget.Height), int2.Zero, 6);
|
||||
|
||||
RenderCommand.SetBlendState(_gBufferBlend);
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace GlitchyEngine.Renderer
|
||||
|
||||
public this(Texture2D texture) : this(_texture, .(0, 0, 1, 1)) { }
|
||||
|
||||
public this(Texture2D texture, Int2 topLeft, Int2 size) :
|
||||
public this(Texture2D texture, int2 topLeft, int2 size) :
|
||||
this(texture,
|
||||
{
|
||||
float2 texSize = float2(texture.Width, texture.Height);
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace GlitchyEngine.Renderer.Text
|
||||
public FT_UInt GlyphIndex;
|
||||
|
||||
// TODO: Consider using floats
|
||||
public Int3 MapCoord;
|
||||
public int3 MapCoord;
|
||||
public int32 Width, Height;
|
||||
|
||||
public double TranslationX, TranslationY;
|
||||
@@ -49,10 +49,10 @@ namespace GlitchyEngine.Renderer.Text
|
||||
private int32 _faceIndex;
|
||||
private bool _hasColor;
|
||||
|
||||
private Int3 _penPos;
|
||||
private int3 _penPos;
|
||||
private int32 _lastRowHeight;
|
||||
internal Texture2D _atlas ~ _?.ReleaseRef();
|
||||
private Int3 _atlasSize;
|
||||
private int3 _atlasSize;
|
||||
|
||||
private Dictionary<char32, GlyphDescriptor> _glyphs = new .() ~ delete _;//DeleteDictionaryAndValues!(_);
|
||||
private Dictionary<uint32, GlyphDescriptor> _glyphsById = new .() ~ DeleteDictionaryAndValues!(_);
|
||||
@@ -335,14 +335,14 @@ namespace GlitchyEngine.Renderer.Text
|
||||
UpdateAtlas();
|
||||
}
|
||||
|
||||
Int3 PrepareAtlas()
|
||||
int3 PrepareAtlas()
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
const uint32 maxRes = 16384; // D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION
|
||||
const uint32 maxArray = 2048; // D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION
|
||||
|
||||
ref Int3 pen = ref _penPos;
|
||||
ref int3 pen = ref _penPos;
|
||||
ref int32 rowHeight = ref _lastRowHeight;
|
||||
|
||||
int32 atlasWidth = _atlasSize.X;
|
||||
@@ -422,10 +422,10 @@ namespace GlitchyEngine.Renderer.Text
|
||||
{
|
||||
Debug.Profiler.ProfileResourceFunction!();
|
||||
|
||||
Int3 oldAtlasSize = _atlasSize;
|
||||
int3 oldAtlasSize = _atlasSize;
|
||||
_atlasSize = PrepareAtlas();
|
||||
|
||||
if(_atlasSize != oldAtlasSize)
|
||||
if(any(_atlasSize != oldAtlasSize))
|
||||
{
|
||||
Debug.Profiler.ProfileResourceScope!("Recreate Atlas");
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ enum ScriptFieldType
|
||||
|
||||
SByte,
|
||||
Short,
|
||||
Int,// Int2, Int3, Int4,
|
||||
Int,// int2, int3, int4,
|
||||
Long,
|
||||
Byte,
|
||||
UShort,
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace GlitchyEngine
|
||||
/**
|
||||
* Gets or Sets the width and height of the window.
|
||||
*/
|
||||
public extern Int2 Size {get; set;}
|
||||
public extern int2 Size {get; set;}
|
||||
/**
|
||||
* Gets or Sets the width of the window.
|
||||
*/
|
||||
@@ -67,7 +67,7 @@ namespace GlitchyEngine
|
||||
/**
|
||||
* Gets or Sets the position of the upper-left corner of the client area of the window.
|
||||
*/
|
||||
public extern Int2 Position {get; set;}
|
||||
public extern int2 Position {get; set;}
|
||||
|
||||
/**
|
||||
* Gets or Sets the x-coordinate of the upper-left corner of the client area of the window.
|
||||
|
||||
@@ -260,7 +260,7 @@ namespace GlitchyEngine.World
|
||||
|
||||
var mouseDelta = Input.GetMouseMovement();
|
||||
|
||||
if (MouseCooldown == 0 && Input.IsMouseButtonPressed(.LeftButton) && mouseDelta != .())
|
||||
if (MouseCooldown == 0 && Input.IsMouseButtonPressed(.LeftButton) && any(mouseDelta != .Zero))
|
||||
{
|
||||
float2 movement = .(
|
||||
-mouseDelta.X,
|
||||
@@ -275,7 +275,7 @@ namespace GlitchyEngine.World
|
||||
transformChanged = true;
|
||||
}
|
||||
|
||||
if (MouseCooldown == 0 && Input.IsMouseButtonPressed(.RightButton) && mouseDelta != .())
|
||||
if (MouseCooldown == 0 && Input.IsMouseButtonPressed(.RightButton) && any(mouseDelta != .()))
|
||||
{
|
||||
float rotY = mouseDelta.X * _cameraRotationSpeedX;
|
||||
float rotX = mouseDelta.Y * _cameraRotationSpeedY;
|
||||
|
||||
@@ -157,7 +157,7 @@ namespace Sandbox
|
||||
|
||||
if(_moving)
|
||||
{
|
||||
Int2 movement = Input.GetMouseMovement();
|
||||
int2 movement = Input.GetMouseMovement();
|
||||
|
||||
_position.X += movement.X;
|
||||
_position.Y += movement.Y;
|
||||
|
||||
Reference in New Issue
Block a user