mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 21:01:52 +00:00
Compare commits
20
Commits
3d
..
asset_handle
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81ae5f1135 | ||
|
|
b76d4cd558 | ||
|
|
5893cfb74a | ||
|
|
ed952155b6 | ||
|
|
d54cdf43ee | ||
|
|
f16fbc3984 | ||
|
|
184480243f | ||
|
|
fc1875ed96 | ||
|
|
5733166b74 | ||
|
|
2ba4b68e09 | ||
|
|
edcec02e94 | ||
|
|
c164aeecaa | ||
|
|
793aa40975 | ||
|
|
50714976e9 | ||
|
|
7b6662cbc4 | ||
|
|
cfa046d2ea | ||
|
|
b22f73a156 | ||
|
|
c3fb9bbd5d | ||
|
|
c22d122921 | ||
|
|
ad14c9f6ed |
@@ -1,5 +1,6 @@
|
|||||||
FileVersion = 1
|
FileVersion = 1
|
||||||
Projects = {Sandbox = {Path = "Sandbox"}, GlitchyEngine = {Path = "GlitchyEngine"}, GlitchLog = {Path = "GlitchLog"}, DirectX = {Path = "GlitchyEngine/vendor/directx/DirectX"}, LodePng = {Path = "vendor/lodepng-beef/lodepng-beef"}, FreeType = {Path = "GlitchyEngine/vendor/freetype"}, cgltf-beef = {Path = "GlitchyEngine/vendor/gltf/cgltf-beef"}, GlitchyEditor = {Path = "GlitchyEditor"}, msdfgen-beef = {Path = "GlitchyEngine/vendor/msdfgen/msdfgen-beef"}, ImGui = {Path = "GlitchyEngine/vendor/imgui/ImGui"}, ImGuiImplDX11 = {Path = "GlitchyEngine/vendor/imgui/ImGuiImplDX11"}, ImGuiImplWin32 = {Path = "GlitchyEngine/vendor/imgui/ImGuiImplWin32"}, ImGuizmo = {Path = "GlitchyEngine/vendor/imgui/ImGuizmo"}, GlitchyEngineHelper = {Path = "GlitchyEngineHelper"}, bon = {Path = "GlitchyEngine/vendor/bon"}, box2d-beef = {Path = "GlitchyEngine/vendor/box2D"}, "Beef.Linq" = {Path = "GlitchyEngine/vendor/Beef.Linq/src"}}
|
Projects = {Sandbox = {Path = "Sandbox"}, GlitchyEngine = {Path = "GlitchyEngine"}, GlitchLog = {Path = "GlitchLog"}, DirectX = {Path = "GlitchyEngine/vendor/directx/DirectX"}, LodePng = {Path = "vendor/lodepng-beef/lodepng-beef"}, FreeType = {Path = "GlitchyEngine/vendor/freetype"}, cgltf-beef = {Path = "GlitchyEngine/vendor/gltf/cgltf-beef"}, GlitchyEditor = {Path = "GlitchyEditor"}, msdfgen-beef = {Path = "GlitchyEngine/vendor/msdfgen/msdfgen-beef"}, ImGui = {Path = "GlitchyEngine/vendor/imgui/ImGui"}, ImGuiImplDX11 = {Path = "GlitchyEngine/vendor/imgui/ImGuiImplDX11"}, ImGuiImplWin32 = {Path = "GlitchyEngine/vendor/imgui/ImGuiImplWin32"}, ImGuizmo = {Path = "GlitchyEngine/vendor/imgui/ImGuizmo"}, GlitchyEngineHelper = {Path = "GlitchyEngineHelper"}, bon = {Path = "GlitchyEngine/vendor/bon"}, box2d-beef = {Path = "GlitchyEngine/vendor/box2D"}, "Beef.Linq" = {Path = "GlitchyEngine/vendor/Beef.Linq/src"}}
|
||||||
|
Unlocked = ["corlib"]
|
||||||
WorkspaceFolders = {GlitchyEngine = ["GlitchyEngine", "GlitchLog", "GlitchyEngineHelper"], "GlitchyEngine/Dependencies" = ["cgltf-beef", "DirectX", "FreeType", "ImGui", "ImGuiImplDX11", "ImGuiImplWin32", "ImGuizmo", "LodePng", "msdfgen-beef", "bon", "box2d-beef", "Beef.Linq"]}
|
WorkspaceFolders = {GlitchyEngine = ["GlitchyEngine", "GlitchLog", "GlitchyEngineHelper"], "GlitchyEngine/Dependencies" = ["cgltf-beef", "DirectX", "FreeType", "ImGui", "ImGuiImplDX11", "ImGuiImplWin32", "ImGuizmo", "LodePng", "msdfgen-beef", "bon", "box2d-beef", "Beef.Linq"]}
|
||||||
|
|
||||||
[Workspace]
|
[Workspace]
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
///
|
||||||
|
/// Loading and usage of an asset.
|
||||||
|
///
|
||||||
|
// Shows the usage of the Content Manager.
|
||||||
|
// An asset is loaded with Content.LoadAsset(AssetName)
|
||||||
|
// Loading an asset returns an AssetHandle.
|
||||||
|
// Usually you want to hold on to the AssetHandle.
|
||||||
|
// If you need the actual asset you can use Content.GetAsset<AssetType>(AssetHandle) to retrieve the actual asset.
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only hold on to AssetHandle.
|
||||||
|
* Do NOT hold actual Assets! The Asset might get invalidated
|
||||||
|
* (e.g. reloading after the source-file changed).
|
||||||
|
*/
|
||||||
|
AssetHandle _lineEffect;
|
||||||
|
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Loading an asset returns a handle to that asset.
|
||||||
|
*/
|
||||||
|
_lineEffect = Content.LoadAsset("Shaders\\LineEffect.hlsl");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
// Use case 1:
|
||||||
|
{
|
||||||
|
// Retrieve the actual asset. Note that this Asset is only guaranteed to persist
|
||||||
|
// for the current frame.
|
||||||
|
Effect fx = Content.GetAsset<Effect>(_lineEffect);
|
||||||
|
|
||||||
|
// Note: Assets are ref counted, however since they are not inteded to be held GetAsset
|
||||||
|
// does NOT increment the reference counter so you usually should NOT decrement it.
|
||||||
|
// The exception is when you manually hold on to an asset (see Example below)
|
||||||
|
|
||||||
|
// Use asset
|
||||||
|
fx.Variables["ViewProjection"].SetData(viewProjection * transform);
|
||||||
|
fx.Variables["Color"].SetData(color);
|
||||||
|
fx.ApplyChanges();
|
||||||
|
fx.Bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use case 2:
|
||||||
|
{
|
||||||
|
// Retrieve the actual asset.
|
||||||
|
Effect fx = _lineEffect.Get<Effect>();
|
||||||
|
|
||||||
|
// ...
|
||||||
|
// Same as case 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Holding on to an actual asset.
|
||||||
|
///
|
||||||
|
// Shows the usage of the Content Manager when you hold a reference to the actual Asset instead of the handle.
|
||||||
|
// This should usually not be done. Eventhough it is technically fine, it has the implication, that if the
|
||||||
|
// content manager decides to reload the asset the changes will not be reflected in the held reference
|
||||||
|
// (which they would if you used GetAsset before every usage.)
|
||||||
|
// Also the content manager can't unload the asset because the reference counter wouldn't be zero.
|
||||||
|
// Though there currently is no way for the content manager to unload an asset unless it is specifically told to do so.
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Field to hold the asset.
|
||||||
|
*/
|
||||||
|
Effect _lineEffect;
|
||||||
|
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
// Load the Asset.
|
||||||
|
AssetHandle handle = Content.LoadAsset("Shaders\\LineEffect.hlsl");
|
||||||
|
// Get the actual asset.
|
||||||
|
_lineEffect = Content.GetAsset<Effect>(handle); // Alternative: _lineEffect = handle.Get<Effect>();
|
||||||
|
// Increment the reference counter so that the asset doesn't get unloaded.
|
||||||
|
_lineEffect.AddRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Destroy()
|
||||||
|
{
|
||||||
|
// Make sure to release the asset once you don't need it anymore. Otherwise it will leak.
|
||||||
|
_lineEffect.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
_lineEffect.Variables["ViewProjection"].SetData(viewProjection * transform);
|
||||||
|
_lineEffect.Variables["Color"].SetData(color);
|
||||||
|
_lineEffect.ApplyChanges();
|
||||||
|
_lineEffect.Bind();
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
///
|
||||||
|
/// This shows the usage of a smart/typed Asset Handle.
|
||||||
|
///
|
||||||
|
// In the basic usage-patterns the user has two options:
|
||||||
|
// Either he/she holds a handle and has to query for the actual asset every time
|
||||||
|
// or he/she hold the actual asset and loses reloading capabilities.
|
||||||
|
// The idea of the auto asset is to provide a way that can provide both.
|
||||||
|
|
||||||
|
AssetHandle<Effect> _lineEffect;
|
||||||
|
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Loading an asset returns a handle to that asset.
|
||||||
|
* The asset handle is implicitly converted to a smart AssetHandle.
|
||||||
|
*/
|
||||||
|
_lineEffect = Content.LoadAsset("Shaders\\LineEffect.hlsl");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
// Use case 1 (Convenience)
|
||||||
|
{
|
||||||
|
_lineEffect.Variables["ViewProjection"].SetData(viewProjection * transform);
|
||||||
|
_lineEffect.Variables["Color"].SetData(color);
|
||||||
|
_lineEffect.ApplyChanges();
|
||||||
|
_lineEffect.Bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use case 2 (Technically more efficient)
|
||||||
|
{
|
||||||
|
Effect fx = _lineEffect.Get();
|
||||||
|
fx.Variables["ViewProjection"].SetData(viewProjection * transform);
|
||||||
|
fx.Variables["Color"].SetData(color);
|
||||||
|
fx.ApplyChanges();
|
||||||
|
fx.Bind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Auto Assets use comp time to expose all the fields, Methods and properties of the actual asset.
|
||||||
|
// They will automatically check if the asset for the handle changed and update accordingly.
|
||||||
|
// This means it is more convenient to use than both basic patterns and has all benefits of both.
|
||||||
|
//
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# Design Code Examples
|
||||||
|
|
||||||
|
This directory (and its subdirectories) contains non functional code snippets showing the intended usage of certain systems of the engine.
|
||||||
@@ -30,10 +30,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
MeshComponent = {
|
MeshComponent = {
|
||||||
Mesh = "Models\\sphere.glb"
|
Mesh = "Models/sphere.glb"
|
||||||
},
|
},
|
||||||
MeshRendererComponent = {
|
MeshRendererComponent = {
|
||||||
Material = "Textures\\TestMaterial.mat"
|
Material = "Textures/TestMaterial.mat"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -48,20 +48,20 @@
|
|||||||
Z = -4
|
Z = -4
|
||||||
},
|
},
|
||||||
Rotation = {
|
Rotation = {
|
||||||
X = 0.614328,
|
X = 0.614328027,
|
||||||
Y = 0.239776,
|
Y = 0.239776045,
|
||||||
Z = 0.031567,
|
Z = 0.0315669999,
|
||||||
W = 0.751074
|
W = 0.751073837
|
||||||
},
|
},
|
||||||
Scale = {
|
Scale = {
|
||||||
X = 0.999999,
|
X = 0.999998868,
|
||||||
Y = 1,
|
Y = 1,
|
||||||
Z = 1.000001
|
Z = 1.00000095
|
||||||
},
|
},
|
||||||
EditorEulerRotation = {
|
EditorEulerRotation = {
|
||||||
X = 1.308998,
|
X = 1.30899811,
|
||||||
Y = 0.349066,
|
Y = 0.349065989,
|
||||||
Z = 0.349066
|
Z = 0.349065989
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
LightComponent = {
|
LightComponent = {
|
||||||
@@ -69,8 +69,8 @@
|
|||||||
Illuminance = 10,
|
Illuminance = 10,
|
||||||
Color = {
|
Color = {
|
||||||
R = 1,
|
R = 1,
|
||||||
G = 0.991772,
|
G = 0.991771996,
|
||||||
B = 0.740862
|
B = 0.74086225
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -103,10 +103,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
MeshComponent = {
|
MeshComponent = {
|
||||||
Mesh = "Models\\plane.glb"
|
Mesh = "Models/plane.glb"
|
||||||
},
|
},
|
||||||
MeshRendererComponent = {
|
MeshRendererComponent = {
|
||||||
Material = "Textures\\TestMaterial.mat"
|
Material = "Textures/TestMaterial.mat"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -121,10 +121,10 @@
|
|||||||
Z = -5
|
Z = -5
|
||||||
},
|
},
|
||||||
Rotation = {
|
Rotation = {
|
||||||
X = 0.21644,
|
X = 0.216440007,
|
||||||
Y = 0,
|
Y = 0,
|
||||||
Z = 0,
|
Z = 0,
|
||||||
W = 0.976296
|
W = 0.976296008
|
||||||
},
|
},
|
||||||
Scale = {
|
Scale = {
|
||||||
X = 1,
|
X = 1,
|
||||||
@@ -132,7 +132,7 @@
|
|||||||
Z = 1
|
Z = 1
|
||||||
},
|
},
|
||||||
EditorEulerRotation = {
|
EditorEulerRotation = {
|
||||||
X = 0.436332,
|
X = 0.436332017,
|
||||||
Y = 0,
|
Y = 0,
|
||||||
Z = 0
|
Z = 0
|
||||||
}
|
}
|
||||||
@@ -140,15 +140,85 @@
|
|||||||
CameraComponent = {
|
CameraComponent = {
|
||||||
Primary = true,
|
Primary = true,
|
||||||
ProjectionType = .InfinitePerspective,
|
ProjectionType = .InfinitePerspective,
|
||||||
PerspectiveFovY = 1.047198,
|
PerspectiveFovY = 1.30899692,
|
||||||
PerspectiveNearPlane = 0.1,
|
PerspectiveNearPlane = 0.100000001,
|
||||||
PerspectiveFarPlane = 10000,
|
PerspectiveFarPlane = 10000,
|
||||||
OrthographicHeight = 10,
|
OrthographicHeight = 10,
|
||||||
OrthographicNearPlane = 0,
|
OrthographicNearPlane = 0,
|
||||||
OrthographicFarPlane = 10,
|
OrthographicFarPlane = 10,
|
||||||
AspectRatio = 2.156692,
|
AspectRatio = 2.19888878,
|
||||||
FixedAspectRatio = false
|
FixedAspectRatio = false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Id = 420718992779301759,
|
||||||
|
NameComponent = {
|
||||||
|
Name = "Entity"
|
||||||
|
},
|
||||||
|
TransformComponent = {
|
||||||
|
Position = {
|
||||||
|
X = 3,
|
||||||
|
Y = 0.501076996,
|
||||||
|
Z = -0.669378757
|
||||||
|
},
|
||||||
|
Rotation = {
|
||||||
|
X = 0.18301262,
|
||||||
|
Y = -0.683013558,
|
||||||
|
Z = 0.683012128,
|
||||||
|
W = 0.183013007
|
||||||
|
},
|
||||||
|
Scale = {
|
||||||
|
X = 1,
|
||||||
|
Y = 1,
|
||||||
|
Z = 1
|
||||||
|
},
|
||||||
|
EditorEulerRotation = {
|
||||||
|
X = 1.57079446,
|
||||||
|
Y = -2.61799312,
|
||||||
|
Z = 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MeshComponent = {
|
||||||
|
Mesh = "Models/plane.glb"
|
||||||
|
},
|
||||||
|
MeshRendererComponent = {
|
||||||
|
Material = ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Id = 8080288871271083510,
|
||||||
|
NameComponent = {
|
||||||
|
Name = "Rocket"
|
||||||
|
},
|
||||||
|
TransformComponent = {
|
||||||
|
Position = {
|
||||||
|
X = 2.37353587,
|
||||||
|
Y = 0.629615188,
|
||||||
|
Z = -1.34831977
|
||||||
|
},
|
||||||
|
Rotation = {
|
||||||
|
X = 0.270598024,
|
||||||
|
Y = -0.65328145,
|
||||||
|
Z = 0.65328151,
|
||||||
|
W = 0.270598054
|
||||||
|
},
|
||||||
|
Scale = {
|
||||||
|
X = 0.999999881,
|
||||||
|
Y = 0.999999821,
|
||||||
|
Z = 0.999999702
|
||||||
|
},
|
||||||
|
EditorEulerRotation = {
|
||||||
|
X = 1.57079637,
|
||||||
|
Y = -2.3561945,
|
||||||
|
Z = 8.94069743e-08
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MeshComponent = {
|
||||||
|
Mesh = "Models/plane.glb"
|
||||||
|
},
|
||||||
|
MeshRendererComponent = {
|
||||||
|
Material = "Textures/RocketMaterial.mat"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -6,15 +6,14 @@
|
|||||||
NameComponent = {
|
NameComponent = {
|
||||||
Name = "Quad"
|
Name = "Quad"
|
||||||
},
|
},
|
||||||
SpriterRendererComponent = {
|
SpriteRendererComponent = {
|
||||||
Color = {
|
Color = {
|
||||||
R = 0,
|
R = 0,
|
||||||
G = 0.551178,
|
G = 0.55117774,
|
||||||
B = 0.328787,
|
B = 0.32878688,
|
||||||
A = 1
|
A = 1
|
||||||
},
|
},
|
||||||
IsCircle = false,
|
Sprite = "Textures/TestMat/rustediron2_albedo.png",
|
||||||
Sprite = "\\Textures\\TestMat\\rustediron2_albedo.png",
|
|
||||||
UvTransform = {
|
UvTransform = {
|
||||||
X = 0,
|
X = 0,
|
||||||
Y = 0,
|
Y = 0,
|
||||||
@@ -69,15 +68,14 @@
|
|||||||
NameComponent = {
|
NameComponent = {
|
||||||
Name = "Floor"
|
Name = "Floor"
|
||||||
},
|
},
|
||||||
SpriterRendererComponent = {
|
SpriteRendererComponent = {
|
||||||
Color = {
|
Color = {
|
||||||
R = 1,
|
R = 1,
|
||||||
G = 0.941886,
|
G = 0.941886365,
|
||||||
B = 0.401485,
|
B = 0.401484847,
|
||||||
A = 1
|
A = 1
|
||||||
},
|
},
|
||||||
IsCircle = false,
|
Sprite = "",
|
||||||
Sprite = null,
|
|
||||||
UvTransform = {
|
UvTransform = {
|
||||||
X = 0,
|
X = 0,
|
||||||
Y = 0,
|
Y = 0,
|
||||||
@@ -158,13 +156,13 @@
|
|||||||
CameraComponent = {
|
CameraComponent = {
|
||||||
Primary = true,
|
Primary = true,
|
||||||
ProjectionType = .InfinitePerspective,
|
ProjectionType = .InfinitePerspective,
|
||||||
PerspectiveFovY = 1.308997,
|
PerspectiveFovY = 1.30899692,
|
||||||
PerspectiveNearPlane = 0.1,
|
PerspectiveNearPlane = 0.100000001,
|
||||||
PerspectiveFarPlane = 10000,
|
PerspectiveFarPlane = 10000,
|
||||||
OrthographicHeight = 10,
|
OrthographicHeight = 10,
|
||||||
OrthographicNearPlane = 0,
|
OrthographicNearPlane = 0,
|
||||||
OrthographicFarPlane = 10,
|
OrthographicFarPlane = 10,
|
||||||
AspectRatio = 2.969697,
|
AspectRatio = 3.22169805,
|
||||||
FixedAspectRatio = false
|
FixedAspectRatio = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -173,15 +171,15 @@
|
|||||||
NameComponent = {
|
NameComponent = {
|
||||||
Name = "Circle"
|
Name = "Circle"
|
||||||
},
|
},
|
||||||
SpriterRendererComponent = {
|
CircleRendererComponent = {
|
||||||
Color = {
|
Color = {
|
||||||
R = 1,
|
R = 1,
|
||||||
G = 1,
|
G = 0,
|
||||||
B = 1,
|
B = 0,
|
||||||
A = 1
|
A = 1
|
||||||
},
|
},
|
||||||
IsCircle = true,
|
InnerRadius = 0.300000012,
|
||||||
Sprite = "\\Textures\\rocket.png",
|
Sprite = "",
|
||||||
UvTransform = {
|
UvTransform = {
|
||||||
X = 0,
|
X = 0,
|
||||||
Y = 0,
|
Y = 0,
|
||||||
@@ -191,8 +189,8 @@
|
|||||||
},
|
},
|
||||||
TransformComponent = {
|
TransformComponent = {
|
||||||
Position = {
|
Position = {
|
||||||
X = -0.121203,
|
X = -0.12120308,
|
||||||
Y = 0.66016,
|
Y = 0.660160363,
|
||||||
Z = 0
|
Z = 0
|
||||||
},
|
},
|
||||||
Rotation = {
|
Rotation = {
|
||||||
@@ -235,34 +233,34 @@
|
|||||||
},
|
},
|
||||||
TransformComponent = {
|
TransformComponent = {
|
||||||
Position = {
|
Position = {
|
||||||
X = 3.883276,
|
X = 3.88327599,
|
||||||
Y = 0,
|
Y = 0,
|
||||||
Z = -0.808795
|
Z = -0.808795214
|
||||||
},
|
},
|
||||||
Rotation = {
|
Rotation = {
|
||||||
X = 0.497987,
|
X = 0.497987002,
|
||||||
Y = -0.103421,
|
Y = -0.103420995,
|
||||||
Z = 0.15538,
|
Z = 0.155380026,
|
||||||
W = 0.846859
|
W = 0.846859217
|
||||||
},
|
},
|
||||||
Scale = {
|
Scale = {
|
||||||
X = 0.999998,
|
X = 0.999997795,
|
||||||
Y = 1,
|
Y = 1,
|
||||||
Z = 1
|
Z = 1
|
||||||
},
|
},
|
||||||
EditorEulerRotation = {
|
EditorEulerRotation = {
|
||||||
X = 1.090894,
|
X = 1.0908947,
|
||||||
Y = -0.340794,
|
Y = -0.340793997,
|
||||||
Z = 0.160858
|
Z = 0.160857916
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
LightComponent = {
|
LightComponent = {
|
||||||
LightType = .Directional,
|
LightType = .Directional,
|
||||||
Illuminance = 12.9,
|
Illuminance = 12.8999996,
|
||||||
Color = {
|
Color = {
|
||||||
R = 0.985467,
|
R = 0.985467017,
|
||||||
G = 1,
|
G = 1,
|
||||||
B = 0.569979
|
B = 0.569978654
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -275,7 +273,7 @@
|
|||||||
Position = {
|
Position = {
|
||||||
X = 0,
|
X = 0,
|
||||||
Y = 0,
|
Y = 0,
|
||||||
Z = -1.523338
|
Z = -1.47202551
|
||||||
},
|
},
|
||||||
Rotation = {
|
Rotation = {
|
||||||
X = 0,
|
X = 0,
|
||||||
@@ -295,10 +293,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
MeshComponent = {
|
MeshComponent = {
|
||||||
Mesh = "\\Models\\sphere.glb"
|
Mesh = "Models/sphere.glb"
|
||||||
},
|
},
|
||||||
MeshRendererComponent = {
|
MeshRendererComponent = {
|
||||||
Material = "\\Textures\\TestMaterial.mat"
|
Material = "Textures/TestMaterial.mat"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
#define EDITOR
|
||||||
|
|
||||||
|
cbuffer Constants : register(b0)
|
||||||
|
{
|
||||||
|
float4x4 ViewProjection;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VS_Input
|
||||||
|
{
|
||||||
|
float4 Position : POSITION;
|
||||||
|
float4 Color : COLOR;
|
||||||
|
#ifdef EDITOR
|
||||||
|
uint EntityId : ENTITYID;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct PS_Input
|
||||||
|
{
|
||||||
|
float4 Position : SV_Position;
|
||||||
|
float4 Color : COLOR;
|
||||||
|
#ifdef EDITOR
|
||||||
|
nointerpolation uint EntityId : ENTITYID;
|
||||||
|
#endif
|
||||||
|
} VS_Output;
|
||||||
|
|
||||||
|
VS_Output VS(VS_Input input)
|
||||||
|
{
|
||||||
|
VS_Output output;
|
||||||
|
|
||||||
|
output.Position = mul(ViewProjection, input.Position);
|
||||||
|
output.Color = input.Color;
|
||||||
|
|
||||||
|
#ifdef EDITOR
|
||||||
|
output.EntityId = input.EntityId;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PS_Output
|
||||||
|
{
|
||||||
|
float4 Color : SV_TARGET0;
|
||||||
|
#ifdef EDITOR
|
||||||
|
uint EntityId : SV_TARGET1;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
PS_Output PS(PS_Input input)
|
||||||
|
{
|
||||||
|
PS_Output output;
|
||||||
|
|
||||||
|
output.Color = input.Color;
|
||||||
|
|
||||||
|
#ifdef EDITOR
|
||||||
|
output.EntityId = input.EntityId;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
Effect = "Shaders/myEffect.hlsl",
|
||||||
|
Textures = [
|
||||||
|
"AlbedoTexture": "Textures/rocket.png",
|
||||||
|
"NormalTexture": "Textures/TestMat/rustediron2_normal.png",
|
||||||
|
"MetallicTexture": "Textures/TestMat/rustediron2_metallic.png",
|
||||||
|
"RoughnessTexture": "Textures/TestMat/rustediron2_roughness.png"
|
||||||
|
],
|
||||||
|
Variables = [
|
||||||
|
"AlbedoColor": .ColorRGBA{
|
||||||
|
Value = {
|
||||||
|
R = 1,
|
||||||
|
G = 1,
|
||||||
|
B = 1,
|
||||||
|
A = 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NormalScaling": .Float2{
|
||||||
|
Value = {
|
||||||
|
X = 1,
|
||||||
|
Y = 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MetallicFactor": .Float{
|
||||||
|
Value = 0
|
||||||
|
},
|
||||||
|
"RoughnessFactor": .Float{
|
||||||
|
Value = 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
AssetLoader = "MaterialAssetLoader",
|
||||||
|
Config = (GlitchyEditor.Assets.ModelAssetLoaderConfig){}/* No reflection data for GlitchyEditor.Assets.ModelAssetLoaderConfig. Add [BonTarget] or force it */
|
||||||
|
}
|
||||||
@@ -7,16 +7,20 @@
|
|||||||
MinFilter = .Anisotropic,
|
MinFilter = .Anisotropic,
|
||||||
MagFilter = .Anisotropic,
|
MagFilter = .Anisotropic,
|
||||||
MipFilter = .Anisotropic,
|
MipFilter = .Anisotropic,
|
||||||
|
FilterMode = .Default,
|
||||||
ComparisonFunction = .Never,
|
ComparisonFunction = .Never,
|
||||||
AddressModeU = .Wrap,
|
AddressModeU = .Wrap,
|
||||||
AddressModeV = .Border,
|
AddressModeV = .Wrap,
|
||||||
AddressModeW = .Clamp,
|
AddressModeW = .Wrap,
|
||||||
MipMaxLOD = 160,
|
MipLODBias = 0,
|
||||||
|
MipMinLOD = 0,
|
||||||
|
MipMaxLOD = 3,
|
||||||
MaxAnisotropy = 16,
|
MaxAnisotropy = 16,
|
||||||
BorderColor = {
|
BorderColor = {
|
||||||
R = 0.756863,
|
R = 1,
|
||||||
G = 0.2,
|
G = 1,
|
||||||
A = 0.956863
|
B = 1,
|
||||||
|
A = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
{
|
{
|
||||||
AssetLoader = "EditorTextureAssetLoader",
|
AssetLoader = "EditorTextureAssetLoader",
|
||||||
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
|
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
|
||||||
|
_generateMipMaps = false,
|
||||||
|
_isSrgb = false,
|
||||||
_samplerStateDescription = {
|
_samplerStateDescription = {
|
||||||
MinFilter = .Linear,
|
MinFilter = .Linear,
|
||||||
MagFilter = .Linear,
|
MagFilter = .Linear,
|
||||||
MipFilter = .Linear,
|
MipFilter = .Linear,
|
||||||
|
FilterMode = .Default,
|
||||||
ComparisonFunction = .Never,
|
ComparisonFunction = .Never,
|
||||||
AddressModeU = .Clamp,
|
AddressModeU = .Wrap,
|
||||||
AddressModeV = .Clamp,
|
AddressModeV = .Wrap,
|
||||||
AddressModeW = .Clamp,
|
AddressModeW = .Clamp,
|
||||||
MipMinLOD = -340282346638528859811704183484516925440,
|
MipLODBias = 0,
|
||||||
MipMaxLOD = 340282346638528859811704183484516925440,
|
MipMinLOD = -3.40282347e+38,
|
||||||
|
MipMaxLOD = 3.40282347e+38,
|
||||||
MaxAnisotropy = 1,
|
MaxAnisotropy = 1,
|
||||||
BorderColor = {
|
BorderColor = {
|
||||||
R = 1,
|
R = 1,
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
{
|
{
|
||||||
AssetLoader = "EditorTextureAssetLoader",
|
AssetLoader = "EditorTextureAssetLoader",
|
||||||
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
|
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
|
||||||
|
_generateMipMaps = false,
|
||||||
|
_isSrgb = false,
|
||||||
_samplerStateDescription = {
|
_samplerStateDescription = {
|
||||||
MinFilter = .Linear,
|
MinFilter = .Linear,
|
||||||
MagFilter = .Linear,
|
MagFilter = .Linear,
|
||||||
MipFilter = .Linear,
|
MipFilter = .Linear,
|
||||||
|
FilterMode = .Default,
|
||||||
ComparisonFunction = .Never,
|
ComparisonFunction = .Never,
|
||||||
AddressModeU = .Clamp,
|
AddressModeU = .Wrap,
|
||||||
AddressModeV = .Clamp,
|
AddressModeV = .Wrap,
|
||||||
AddressModeW = .Clamp,
|
AddressModeW = .Clamp,
|
||||||
MipMinLOD = -340282346638528859811704183484516925440,
|
MipLODBias = 2.5999999,
|
||||||
MipMaxLOD = 340282346638528859811704183484516925440,
|
MipMinLOD = -Infinity,
|
||||||
|
MipMaxLOD = Infinity,
|
||||||
MaxAnisotropy = 1,
|
MaxAnisotropy = 1,
|
||||||
BorderColor = {
|
BorderColor = {
|
||||||
R = 1,
|
R = 1,
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
{
|
{
|
||||||
AssetLoader = "EditorTextureAssetLoader",
|
AssetLoader = "EditorTextureAssetLoader",
|
||||||
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
|
Config = (GlitchyEditor.Assets.EditorTextureAssetLoaderConfig){
|
||||||
|
_generateMipMaps = false,
|
||||||
_isSrgb = true,
|
_isSrgb = true,
|
||||||
_samplerStateDescription = {
|
_samplerStateDescription = {
|
||||||
MinFilter = .Linear,
|
MinFilter = .Linear,
|
||||||
MagFilter = .Linear,
|
MagFilter = .Linear,
|
||||||
MipFilter = .Linear,
|
MipFilter = .Linear,
|
||||||
|
FilterMode = .Default,
|
||||||
ComparisonFunction = .Never,
|
ComparisonFunction = .Never,
|
||||||
AddressModeU = .Clamp,
|
AddressModeU = .Wrap,
|
||||||
AddressModeV = .Clamp,
|
AddressModeV = .Wrap,
|
||||||
AddressModeW = .Clamp,
|
AddressModeW = .Clamp,
|
||||||
MipMinLOD = -340282346638528859811704183484516925440,
|
MipLODBias = 0,
|
||||||
MipMaxLOD = 340282346638528859811704183484516925440,
|
MipMinLOD = -3.40282347e+38,
|
||||||
|
MipMaxLOD = 3.40282347e+38,
|
||||||
MaxAnisotropy = 1,
|
MaxAnisotropy = 1,
|
||||||
BorderColor = {
|
BorderColor = {
|
||||||
R = 1,
|
R = 1,
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
{
|
{
|
||||||
Effect = "content/Shaders/myEffect.hlsl",
|
Effect = "Shaders\\myEffect.hlsl",
|
||||||
Textures = [
|
Textures = [
|
||||||
"AlbedoTexture": "Textures/TestMat/rustediron2_albedo.png"
|
"AlbedoTexture": "Textures\\TestMat\\rustediron2_albedo.png",
|
||||||
|
"NormalTexture": "Textures\\TestMat\\rustediron2_normal.png",
|
||||||
|
"MetallicTexture": "Textures\\TestMat\\rustediron2_metallic.png",
|
||||||
|
"RoughnessTexture": "Textures\\TestMat\\rustediron2_roughness.png"
|
||||||
],
|
],
|
||||||
Variables = [
|
Variables = [
|
||||||
"AlbedoColor": .ColorRGBA{
|
"AlbedoColor": .ColorRGBA{
|
||||||
|
|||||||
@@ -4,13 +4,14 @@
|
|||||||
_isSrgb = true,
|
_isSrgb = true,
|
||||||
_samplerStateDescription = {
|
_samplerStateDescription = {
|
||||||
MinFilter = .Linear,
|
MinFilter = .Linear,
|
||||||
|
MagFilter = .Linear,
|
||||||
MipFilter = .Linear,
|
MipFilter = .Linear,
|
||||||
ComparisonFunction = .Never,
|
ComparisonFunction = .Never,
|
||||||
AddressModeU = .Clamp,
|
AddressModeU = .Clamp,
|
||||||
AddressModeV = .Clamp,
|
AddressModeV = .Clamp,
|
||||||
AddressModeW = .Clamp,
|
AddressModeW = .Clamp,
|
||||||
MipMinLOD = -340282346638528859811704183484516925440,
|
MipMinLOD = -3.40282347e+38,
|
||||||
MipMaxLOD = 340282346638528859811704183484516925440,
|
MipMaxLOD = 3.40282347e+38,
|
||||||
MaxAnisotropy = 1,
|
MaxAnisotropy = 1,
|
||||||
BorderColor = {
|
BorderColor = {
|
||||||
R = 1,
|
R = 1,
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class AssetFile
|
|||||||
|
|
||||||
private bool _isDirectory;
|
private bool _isDirectory;
|
||||||
|
|
||||||
private Object _loadedAsset;
|
private Asset _loadedAsset;
|
||||||
|
|
||||||
public bool IsDirectory => _isDirectory;
|
public bool IsDirectory => _isDirectory;
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ class AssetFile
|
|||||||
|
|
||||||
public AssetConfig AssetConfig => _assetConfig;
|
public AssetConfig AssetConfig => _assetConfig;
|
||||||
|
|
||||||
public Object LoadedAsset => _loadedAsset;
|
public Asset LoadedAsset => _loadedAsset;
|
||||||
|
|
||||||
[AllowAppend]
|
[AllowAppend]
|
||||||
public this(EditorContentManager contentManager, StringView identifier, StringView path, bool isDirectory)
|
public this(EditorContentManager contentManager, StringView identifier, StringView path, bool isDirectory)
|
||||||
|
|||||||
@@ -34,6 +34,24 @@ public class SubAsset
|
|||||||
public Texture2D PreviewImage ~ _?.ReleaseRef();
|
public Texture2D PreviewImage ~ _?.ReleaseRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class AssetIdentifier
|
||||||
|
{
|
||||||
|
public const char8 DirectorySeparatorChar = '/';
|
||||||
|
|
||||||
|
public static void Fixup(String assetIdentifier)
|
||||||
|
{
|
||||||
|
const String DotSeperator = $".{DirectorySeparatorChar}";
|
||||||
|
const String SeperatorDot = $"{DirectorySeparatorChar}.";
|
||||||
|
|
||||||
|
assetIdentifier.Replace('\\', DirectorySeparatorChar);
|
||||||
|
assetIdentifier.Replace(DotSeperator, "");
|
||||||
|
assetIdentifier.Replace(SeperatorDot, "");
|
||||||
|
|
||||||
|
if (assetIdentifier.StartsWith(DirectorySeparatorChar))
|
||||||
|
assetIdentifier.Remove(0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class AssetHierarchy
|
class AssetHierarchy
|
||||||
{
|
{
|
||||||
FileSystemWatcher fsw ~ {
|
FileSystemWatcher fsw ~ {
|
||||||
@@ -108,7 +126,8 @@ class AssetHierarchy
|
|||||||
fsw.OnRenamed.Add(new (oldName, newName) => {
|
fsw.OnRenamed.Add(new (oldName, newName) => {
|
||||||
Log.EngineLogger.Trace($"File renamed (From \"{oldName}\" to \"{newName}\")");
|
Log.EngineLogger.Trace($"File renamed (From \"{oldName}\" to \"{newName}\")");
|
||||||
|
|
||||||
_fileSystemDirty = true;
|
//_fileSystemDirty = true;
|
||||||
|
FileRenamed(oldName, newName);
|
||||||
/*String contentFilePath = scope String();
|
/*String contentFilePath = scope String();
|
||||||
|
|
||||||
Path.InternalCombine(contentFilePath, ContentDirectory, oldName);
|
Path.InternalCombine(contentFilePath, ContentDirectory, oldName);
|
||||||
@@ -121,7 +140,7 @@ class AssetHierarchy
|
|||||||
fsw.StartRaisingEvents();
|
fsw.StartRaisingEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the tree node for the given filePath or null, if the file/directory doesn't exist.
|
/// Gets the tree node for the given filePath or .Err, if the file/directory doesn't exist.
|
||||||
/// @param filePath the path for which to return the tree node.
|
/// @param filePath the path for which to return the tree node.
|
||||||
/// @remarks Do not hold a reference to the TreeNode because it can become invalid when the file hierarchy changes.
|
/// @remarks Do not hold a reference to the TreeNode because it can become invalid when the file hierarchy changes.
|
||||||
public Result<TreeNode<AssetNode>> GetNodeFromPath(StringView filePath)
|
public Result<TreeNode<AssetNode>> GetNodeFromPath(StringView filePath)
|
||||||
@@ -161,6 +180,7 @@ class AssetHierarchy
|
|||||||
_assetHierarchy = new TreeNode<AssetNode>(new AssetNode());
|
_assetHierarchy = new TreeNode<AssetNode>(new AssetNode());
|
||||||
_assetHierarchy->Path = new String(ContentDirectory);
|
_assetHierarchy->Path = new String(ContentDirectory);
|
||||||
_assetHierarchy->Name = new String("Content");
|
_assetHierarchy->Name = new String("Content");
|
||||||
|
_assetHierarchy->IsDirectory = true;
|
||||||
|
|
||||||
Log.EngineLogger.Trace($"Created directory node for: \"{_assetHierarchy->Path}\"");
|
Log.EngineLogger.Trace($"Created directory node for: \"{_assetHierarchy->Path}\"");
|
||||||
|
|
||||||
@@ -171,6 +191,7 @@ class AssetHierarchy
|
|||||||
{
|
{
|
||||||
String identifier = scope .(node.Path.Length);
|
String identifier = scope .(node.Path.Length);
|
||||||
Path.GetRelativePath(node.Path, _contentDirectory, identifier);
|
Path.GetRelativePath(node.Path, _contentDirectory, identifier);
|
||||||
|
AssetIdentifier.Fixup(identifier);
|
||||||
|
|
||||||
node.AssetFile = new AssetFile(_contentManager, identifier, node.Path, node.IsDirectory);
|
node.AssetFile = new AssetFile(_contentManager, identifier, node.Path, node.IsDirectory);
|
||||||
}
|
}
|
||||||
@@ -333,11 +354,73 @@ class AssetHierarchy
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
OnFileContentChanged(node.Value);
|
OnFileContentChanged(node.Value);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Handle file changes (reload asset, etc...)
|
private void FileRenamed(StringView oldFilePath, StringView newFilePath)
|
||||||
|
{
|
||||||
|
var oldFilePath;
|
||||||
|
|
||||||
|
// Ignore Config files.
|
||||||
|
if (oldFilePath.EndsWith(AssetFile.ConfigFileExtension))
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
String oldFileNameWithContentRoot = scope .();
|
||||||
|
Path.InternalCombine(oldFileNameWithContentRoot, _contentDirectory, oldFilePath);
|
||||||
|
|
||||||
|
String newFileNameWithContentRoot = scope .();
|
||||||
|
Path.InternalCombine(newFileNameWithContentRoot, _contentDirectory, newFilePath);
|
||||||
|
|
||||||
|
// Rename config file
|
||||||
|
{
|
||||||
|
String oldConfigFileName = scope $"{oldFileNameWithContentRoot}{AssetFile.ConfigFileExtension}";
|
||||||
|
String newConfigFileName = scope $"{newFileNameWithContentRoot}{AssetFile.ConfigFileExtension}";
|
||||||
|
|
||||||
|
if (File.Exists(oldConfigFileName) && !File.Exists(newConfigFileName))
|
||||||
|
{
|
||||||
|
if (File.Move(oldConfigFileName, newConfigFileName) case .Err(let value))
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error($"Failed to move file {oldConfigFileName} to {newConfigFileName}. Code: {value}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var nodeResult = GetNodeFromPath(oldFileNameWithContentRoot);
|
||||||
|
|
||||||
|
TreeNode<AssetNode> node = null;
|
||||||
|
|
||||||
|
if (!(nodeResult case .Ok(out node)))
|
||||||
|
{
|
||||||
|
// This happens, when we create new files.
|
||||||
|
Log.EngineLogger.Trace($"Could not find node for file \"{oldFileNameWithContentRoot}\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_pathToAssetNode.Remove(oldFileNameWithContentRoot);
|
||||||
|
|
||||||
|
node->Path.Set(newFileNameWithContentRoot);
|
||||||
|
_pathToAssetNode.Add(node->Path, node);
|
||||||
|
|
||||||
|
node->Name.Clear();
|
||||||
|
Path.GetFileName(newFileNameWithContentRoot, node->Name);
|
||||||
|
|
||||||
|
String oldIdentifier = scope .(node->AssetFile.[Friend]_identifier);
|
||||||
|
|
||||||
|
node->AssetFile.[Friend]_path.Set(node->Path);
|
||||||
|
|
||||||
|
node->AssetFile.[Friend]_identifier.Set(newFilePath);
|
||||||
|
AssetIdentifier.Fixup(node->AssetFile.[Friend]_identifier);
|
||||||
|
|
||||||
|
node->AssetFile.[Friend]_assetConfigPath..Set(node->Path).Append(AssetFile.ConfigFileExtension);
|
||||||
|
|
||||||
|
OnFileRenamed(node.Value, oldIdentifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
public delegate void FileContentChangedFunc(AssetNode node);
|
public delegate void FileContentChangedFunc(AssetNode node);
|
||||||
|
|
||||||
public Event<FileContentChangedFunc> OnFileContentChanged ~ _.Dispose();
|
public Event<FileContentChangedFunc> OnFileContentChanged ~ _.Dispose();
|
||||||
|
|
||||||
|
public delegate void FileRenamedFunc(AssetNode node, StringView oldName);
|
||||||
|
|
||||||
|
public Event<FileRenamedFunc> OnFileRenamed ~ _.Dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,54 +48,15 @@ class EffectAssetLoader : IAssetLoader //, IReloadingAssetLoader
|
|||||||
Effect effect = new Effect(file, assetIdentifier, contentManager);
|
Effect effect = new Effect(file, assetIdentifier, contentManager);
|
||||||
|
|
||||||
return effect;
|
return effect;
|
||||||
|
}
|
||||||
|
|
||||||
/*StreamReader reader = scope .(file);
|
public Asset GetPlaceholderAsset(Type assetType)
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
String text = scope .();
|
public Asset GetErrorAsset(Type assetType)
|
||||||
|
{
|
||||||
reader.ReadToEnd(text);
|
return default;
|
||||||
|
|
||||||
MaterialFile materialFile = scope .();
|
|
||||||
|
|
||||||
var result = Bon.Deserialize<MaterialFile>(ref materialFile, text);
|
|
||||||
|
|
||||||
if (result case .Err)
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Error("Failed to load material.");
|
|
||||||
return null;
|
|
||||||
// TODO: return error material
|
|
||||||
}
|
|
||||||
|
|
||||||
Effect fx = new Effect(materialFile.Effect);
|
|
||||||
|
|
||||||
Material material = new Material(fx);
|
|
||||||
|
|
||||||
for (let (slotName, textureIdentifier) in materialFile.Textures)
|
|
||||||
{
|
|
||||||
Texture texture = contentManager.LoadAsset(textureIdentifier) as Texture;
|
|
||||||
|
|
||||||
if (texture == null)
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Error("Failed to load texture.");
|
|
||||||
// TODO: LoadAsset should return an error texture.
|
|
||||||
}
|
|
||||||
|
|
||||||
material.SetTexture(slotName, texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
fx.ReleaseRef();
|
|
||||||
|
|
||||||
/*for (let (slotName, textureIdentifier) in materialFile.Variables)
|
|
||||||
{
|
|
||||||
if (texture == null)
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Error("Failed to load texture.");
|
|
||||||
// TODO: LoadAsset should return an error texture.
|
|
||||||
}
|
|
||||||
|
|
||||||
material.SetVariable(slotName, );
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return material; //ModelLoader.LoadMesh(file, subAsset.Value, 0);*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
|
|||||||
|
|
||||||
mixin DropAssetTarget<T>() where T : Asset
|
mixin DropAssetTarget<T>() where T : Asset
|
||||||
{
|
{
|
||||||
Asset asset = null;
|
AssetHandle handle = .Invalid;
|
||||||
|
|
||||||
if (ImGui.BeginDragDropTarget())
|
if (ImGui.BeginDragDropTarget())
|
||||||
{
|
{
|
||||||
@@ -39,13 +39,13 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
|
|||||||
{
|
{
|
||||||
StringView fullpath = .((char8*)payload.Data, (int)payload.DataSize);
|
StringView fullpath = .((char8*)payload.Data, (int)payload.DataSize);
|
||||||
|
|
||||||
asset = Content.LoadAsset<Asset>(fullpath);
|
handle = Content.LoadAsset(fullpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.EndDragDropTarget();
|
ImGui.EndDragDropTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
asset
|
handle
|
||||||
}
|
}
|
||||||
|
|
||||||
public this(AssetFile asset) : base(asset)
|
public this(AssetFile asset) : base(asset)
|
||||||
@@ -84,11 +84,10 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
|
|||||||
{
|
{
|
||||||
StringView path = .((char8*)payload.Data, (int)payload.DataSize);
|
StringView path = .((char8*)payload.Data, (int)payload.DataSize);
|
||||||
|
|
||||||
using (Texture2D newTexture = Content.LoadAsset<Texture2D>(path))//new Texture2D(path, true))
|
AssetHandle<Texture2D> newTexture = Content.LoadAsset(path);
|
||||||
{
|
|
||||||
newTexture.SamplerState = SamplerStateManager.AnisotropicWrap;
|
//newTexture.Get().SamplerState = SamplerStateManager.AnisotropicWrap;
|
||||||
material.SetTexture(texture.key, newTexture);
|
material.SetTexture(texture.key, newTexture.Cast<Texture>());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.EndDragDropTarget();
|
ImGui.EndDragDropTarget();
|
||||||
@@ -98,7 +97,6 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
|
|||||||
|
|
||||||
private void ShowVariables(Material material, Effect effect)
|
private void ShowVariables(Material material, Effect effect)
|
||||||
{
|
{
|
||||||
|
|
||||||
for (let (name, arguments) in effect.[Friend]_variableDescriptions)
|
for (let (name, arguments) in effect.[Friend]_variableDescriptions)
|
||||||
{
|
{
|
||||||
let variable = effect.Variables[name];
|
let variable = effect.Variables[name];
|
||||||
@@ -341,28 +339,23 @@ class MaterialAssetLoader : IAssetLoader, IAssetSaver //, IReloadingAssetLoader
|
|||||||
Log.EngineLogger.Error("Failed to load material.");
|
Log.EngineLogger.Error("Failed to load material.");
|
||||||
Debug.SafeBreak();
|
Debug.SafeBreak();
|
||||||
return null;
|
return null;
|
||||||
// TODO: return error material
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Effect fx = new Effect(materialFile.Effect);
|
Effect fx = Content.GetAsset<Effect>(contentManager.LoadAsset(materialFile.Effect, true), contentManager);
|
||||||
|
|
||||||
Material material = new Material(fx);
|
Material material = new Material(fx);
|
||||||
|
|
||||||
for (let (slotName, textureIdentifier) in materialFile.Textures)
|
for (let (slotName, textureIdentifier) in materialFile.Textures)
|
||||||
{
|
{
|
||||||
using (Texture texture = contentManager.LoadAsset(textureIdentifier) as Texture)
|
AssetHandle<Texture> texture = contentManager.LoadAsset(textureIdentifier);
|
||||||
|
|
||||||
|
if (texture.IsInvalid)
|
||||||
{
|
{
|
||||||
if (texture == null)
|
Log.EngineLogger.Error($"Failed to load texture \"{textureIdentifier}\".");
|
||||||
{
|
|
||||||
Log.EngineLogger.Error($"Failed to load texture \"{textureIdentifier}\".");
|
|
||||||
// TODO: LoadAsset should return an error texture.
|
|
||||||
}
|
|
||||||
|
|
||||||
material.SetTexture(slotName, texture);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fx.ReleaseRef();
|
material.SetTexture(slotName, texture);
|
||||||
|
}
|
||||||
|
|
||||||
for (let (slotName, variableValue) in materialFile.Variables)
|
for (let (slotName, variableValue) in materialFile.Variables)
|
||||||
{
|
{
|
||||||
@@ -382,7 +375,7 @@ class MaterialAssetLoader : IAssetLoader, IAssetSaver //, IReloadingAssetLoader
|
|||||||
material.SetVariable(slotName, value);
|
material.SetVariable(slotName, value);
|
||||||
case .None:
|
case .None:
|
||||||
default:
|
default:
|
||||||
Log.EngineLogger.Error("Errorre");
|
Log.EngineLogger.Error($"Unknown variable type of variable {slotName}: {variableValue}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -407,12 +400,11 @@ class MaterialAssetLoader : IAssetLoader, IAssetSaver //, IReloadingAssetLoader
|
|||||||
materialFile.Textures = new .();
|
materialFile.Textures = new .();
|
||||||
materialFile.Variables = new .();
|
materialFile.Variables = new .();
|
||||||
|
|
||||||
//material.SetTexture();
|
for (let (slotName, texture) in material.[Friend]_textures)
|
||||||
|
|
||||||
for (let (slotName, textureViewBinding) in material.[Friend]_textures)
|
|
||||||
{
|
{
|
||||||
//materialFile.Textures.Add(slotName, textureViewBinding.)
|
Texture textureAsset = texture.Get();
|
||||||
|
|
||||||
|
materialFile.Textures.Add(new String(slotName), new String(textureAsset?.Identifier ?? ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
Effect effect = material.Effect;
|
Effect effect = material.Effect;
|
||||||
@@ -423,7 +415,6 @@ class MaterialAssetLoader : IAssetLoader, IAssetSaver //, IReloadingAssetLoader
|
|||||||
for (let (name, arguments) in effect.[Friend]_variableDescriptions)
|
for (let (name, arguments) in effect.[Friend]_variableDescriptions)
|
||||||
{
|
{
|
||||||
VariableValue variableValue = .None;
|
VariableValue variableValue = .None;
|
||||||
//Object variantValue = null;
|
|
||||||
|
|
||||||
let variable = effect.Variables[name];
|
let variable = effect.Variables[name];
|
||||||
|
|
||||||
@@ -449,7 +440,6 @@ class MaterialAssetLoader : IAssetLoader, IAssetSaver //, IReloadingAssetLoader
|
|||||||
value = ColorRGBA.LinearToSRGB((ColorRGBA)value);
|
value = ColorRGBA.LinearToSRGB((ColorRGBA)value);
|
||||||
|
|
||||||
variableValue = .ColorRGBA(value);
|
variableValue = .ColorRGBA(value);
|
||||||
//variantValue = new box value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (variable.Type == .Float && variable.Rows == 1)
|
else if (variable.Type == .Float && variable.Rows == 1)
|
||||||
@@ -469,51 +459,9 @@ class MaterialAssetLoader : IAssetLoader, IAssetSaver //, IReloadingAssetLoader
|
|||||||
material.GetVariable<Vector4>(variable.Name, let value);
|
material.GetVariable<Vector4>(variable.Name, let value);
|
||||||
variableValue = .Float4(value);
|
variableValue = .Float4(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*bool hasMin = TryGetValue(arguments, "Min", var min);
|
|
||||||
bool hasMax = TryGetValue(arguments, "Max", var max);
|
|
||||||
|
|
||||||
for (int r < variable.Rows)
|
|
||||||
{
|
|
||||||
switch (variable.Columns)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
material.GetVariable<float>(variable.Name, var value);
|
|
||||||
|
|
||||||
float[1] minV = hasMin ? min.Get<float[1]>() : .(float.MinValue);
|
|
||||||
float[1] maxV = hasMax ? max.Get<float[1]>() : .(float.MaxValue);
|
|
||||||
|
|
||||||
if (ImGui.EditVector<1>(displayName, ref *(float[1]*)&value, .(), 0.1f, 100.0f, minV, maxV))
|
|
||||||
material.SetVariable(variable.Name, value);
|
|
||||||
case 2:
|
|
||||||
material.GetVariable<Vector2>(variable.Name, var value);
|
|
||||||
|
|
||||||
Vector2 minV = hasMin ? min.Get<Vector2>() : .(float.MinValue);
|
|
||||||
Vector2 maxV = hasMax ? max.Get<Vector2>() : .(float.MaxValue);
|
|
||||||
|
|
||||||
if (ImGui.EditVector2(displayName, ref value, .Zero, 0.1f, 100.0f, minV, maxV))
|
|
||||||
material.SetVariable(variable.Name, value);
|
|
||||||
case 3:
|
|
||||||
material.GetVariable<Vector3>(variable.Name, var value);
|
|
||||||
|
|
||||||
Vector3 minV = hasMin ? min.Get<Vector3>() : .(float.MinValue);
|
|
||||||
Vector3 maxV = hasMax ? max.Get<Vector3>() : .(float.MaxValue);
|
|
||||||
|
|
||||||
if (ImGui.EditVector3(displayName, ref value, .Zero, 0.1f, 100.0f, minV, maxV))
|
|
||||||
material.SetVariable(variable.Name, value);
|
|
||||||
case 4:
|
|
||||||
material.GetVariable<Vector4>(variable.Name, var value);
|
|
||||||
|
|
||||||
Vector4 minV = hasMin ? min.Get<Vector4>() : .(float.MinValue);
|
|
||||||
Vector4 maxV = hasMax ? max.Get<Vector4>() : .(float.MaxValue);
|
|
||||||
|
|
||||||
if (ImGui.EditVector4(displayName, ref value, .Zero, 0.1f, 100.0f, minV, maxV))
|
|
||||||
material.SetVariable(variable.Name, value);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
materialFile.Variables.Add(name, variableValue);
|
materialFile.Variables.Add(new String(name), variableValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
String text = scope .();
|
String text = scope .();
|
||||||
@@ -527,4 +475,17 @@ class MaterialAssetLoader : IAssetLoader, IAssetSaver //, IReloadingAssetLoader
|
|||||||
|
|
||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Material _placeholder;
|
||||||
|
Material _error;
|
||||||
|
|
||||||
|
public Asset GetPlaceholderAsset(Type assetType)
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Asset GetErrorAsset(Type assetType)
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -44,8 +44,18 @@ class ModelAssetLoader : IAssetLoader //, IReloadingAssetLoader
|
|||||||
|
|
||||||
public Asset LoadAsset(Stream file, AssetLoaderConfig config, StringView assetIdentifier, StringView? subAsset, IContentManager contentManager)
|
public Asset LoadAsset(Stream file, AssetLoaderConfig config, StringView assetIdentifier, StringView? subAsset, IContentManager contentManager)
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Assert(subAsset != null);
|
//Log.EngineLogger.Assert(subAsset != null);
|
||||||
|
|
||||||
return ModelLoader.LoadMesh(file, subAsset.Value, 0);
|
return ModelLoader.LoadMesh(file, subAsset ?? assetIdentifier, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Asset GetPlaceholderAsset(Type assetType)
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Asset GetErrorAsset(Type assetType)
|
||||||
|
{
|
||||||
|
return default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,7 +164,7 @@ class EditorTextureAssetLoaderConfig : AssetLoaderConfig
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EditorTextureAssetLoader : IAssetLoader, IReloadingAssetLoader
|
class EditorTextureAssetLoader : IAssetLoader//, IReloadingAssetLoader
|
||||||
{
|
{
|
||||||
private static readonly List<StringView> _fileExtensions = new .(){".png", ".dds"} ~ delete _; // ".jpg", ".bmp"
|
private static readonly List<StringView> _fileExtensions = new .(){".png", ".dds"} ~ delete _; // ".jpg", ".bmp"
|
||||||
|
|
||||||
@@ -243,65 +243,19 @@ class EditorTextureAssetLoader : IAssetLoader, IReloadingAssetLoader
|
|||||||
case .PNG:
|
case .PNG:
|
||||||
texture = LoadPng(data, config);
|
texture = LoadPng(data, config);
|
||||||
case .Unknown:
|
case .Unknown:
|
||||||
Runtime.FatalError("Unknown image format.");
|
Log.EngineLogger.Error("Unknown texture format.");
|
||||||
|
texture = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.EngineLogger.AssertDebug(texture != null);
|
if (texture != null)
|
||||||
|
{
|
||||||
SetSampler(texture, config);
|
SetSampler(texture, config);
|
||||||
|
texture.[Friend]Complete = true;
|
||||||
|
}
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReloadAsset(AssetFile assetFile, Stream data)
|
|
||||||
{
|
|
||||||
Texture reloadingTexture = assetFile.LoadedAsset as Texture;
|
|
||||||
|
|
||||||
if (reloadingTexture == null)
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Error($"{nameof(Self)}: Requested reload of \"{assetFile.FilePath}\" but it's not a Texture!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorTextureAssetLoaderConfig config = assetFile.AssetConfig.Config as EditorTextureAssetLoaderConfig;
|
|
||||||
|
|
||||||
if (config == null)
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Error($"{nameof(Self)}: Config of asset \"{assetFile.FilePath}\" doesn't have the correct type!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(GetTextureType(data))
|
|
||||||
{
|
|
||||||
case .DDS:
|
|
||||||
ReloadDds(reloadingTexture as Texture2D, data, config);
|
|
||||||
case .PNG:
|
|
||||||
ReloadPng(reloadingTexture as Texture2D, data, config);
|
|
||||||
case .Unknown:
|
|
||||||
Runtime.FatalError("Unknown image format.");
|
|
||||||
}
|
|
||||||
|
|
||||||
SetSampler(reloadingTexture, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void SetSampler(Texture texture, EditorTextureAssetLoaderConfig config)
|
|
||||||
{
|
|
||||||
using (SamplerState samplerState = SamplerStateManager.GetSampler(config.SamplerStateDescription))
|
|
||||||
{
|
|
||||||
texture.SamplerState = samplerState;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ReloadPng(Texture2D reloadingTexture, Stream data, EditorTextureAssetLoaderConfig config)
|
|
||||||
{
|
|
||||||
Debug.Profiler.ProfileResourceFunction!();
|
|
||||||
|
|
||||||
using (Texture2D newTexture = LoadPng(data, config))
|
|
||||||
{
|
|
||||||
reloadingTexture.[Friend]SneakySwappyTexture(newTexture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Texture2D LoadPng(Stream data, EditorTextureAssetLoaderConfig config)
|
private static Texture2D LoadPng(Stream data, EditorTextureAssetLoaderConfig config)
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileResourceFunction!();
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
@@ -313,40 +267,105 @@ class EditorTextureAssetLoader : IAssetLoader, IReloadingAssetLoader
|
|||||||
if (result case .Err(let err))
|
if (result case .Err(let err))
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error($"Failed to read data from stream. Texture: Error: {err}");
|
Log.EngineLogger.Error($"Failed to read data from stream. Texture: Error: {err}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8* rawData = null;
|
||||||
|
defer
|
||||||
|
{
|
||||||
|
if (rawData != null)
|
||||||
|
LodePng.LodePng.Free(rawData);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8* rawData = ?;
|
|
||||||
uint32 width = 0, height = 0;
|
uint32 width = 0, height = 0;
|
||||||
|
|
||||||
uint32 errorCode = LodePng.LodePng.Decode32(&rawData, &width, &height, pngData.Ptr, (.)pngData.Count);
|
{
|
||||||
|
Debug.Profiler.ProfileResourceScope!("LodePng.LodePng.Decode32");
|
||||||
|
uint32 errorCode = LodePng.LodePng.Decode32(&rawData, &width, &height, pngData.Ptr, (.)pngData.Count);
|
||||||
|
if (errorCode != 0)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error($"Failed to decode PNG file {errorCode}.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Log.EngineLogger.Assert(errorCode == 0, "Failed to load png File");
|
|
||||||
|
|
||||||
// TODO: load as SRGB because PNGs are usually not stored as linear
|
|
||||||
//Texture2DDesc desc = .(width, height, srgb? .R8G8B8A8_UNorm_SRGB : .R8G8B8A8_UNorm, 1, 1, .Immutable);
|
|
||||||
Texture2DDesc desc = .(width, height, config.IsSRGB ? .R8G8B8A8_UNorm_SRGB : .R8G8B8A8_UNorm, 1, 1, .Immutable);
|
Texture2DDesc desc = .(width, height, config.IsSRGB ? .R8G8B8A8_UNorm_SRGB : .R8G8B8A8_UNorm, 1, 1, .Immutable);
|
||||||
Texture2D texture = new Texture2D(desc);
|
Texture2D texture = new Texture2D(desc);
|
||||||
texture.SetData<Color>((.)rawData);
|
texture.SetData<Color>((.)rawData);
|
||||||
|
|
||||||
// TODO: Generate mip maps
|
// TODO: Generate mip maps
|
||||||
|
|
||||||
LodePng.LodePng.Free(rawData);
|
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReloadDds(Texture2D reloadingTexture, Stream data, EditorTextureAssetLoaderConfig config)
|
|
||||||
{
|
|
||||||
using (Texture2D newTexture = new [Friend]Texture2D(data))
|
|
||||||
{
|
|
||||||
reloadingTexture.[Friend]SneakySwappyTexture(newTexture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Texture LoadDds(Stream data, EditorTextureAssetLoaderConfig config)
|
private static Texture LoadDds(Stream data, EditorTextureAssetLoaderConfig config)
|
||||||
{
|
{
|
||||||
|
// TODO: Move the loading of Dds files here.
|
||||||
Texture2D texture = new [Friend]Texture2D(data);
|
Texture2D texture = new [Friend]Texture2D(data);
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void SetSampler(Texture texture, EditorTextureAssetLoaderConfig config)
|
||||||
|
{
|
||||||
|
using (SamplerState samplerState = SamplerStateManager.GetSampler(config.SamplerStateDescription))
|
||||||
|
{
|
||||||
|
texture.SamplerState = samplerState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Texture2D _placeholder2D;
|
||||||
|
private static Texture2D _error2D;
|
||||||
|
|
||||||
|
public Asset GetPlaceholderAsset(Type assetType)
|
||||||
|
{
|
||||||
|
switch (assetType)
|
||||||
|
{
|
||||||
|
case typeof(Texture2D):
|
||||||
|
fallthrough;
|
||||||
|
default:
|
||||||
|
if (_placeholder2D == null)
|
||||||
|
{
|
||||||
|
Texture2DDesc desc = .(1, 1, .R8G8B8A8_UNorm, 1, 1, .Immutable, .None);
|
||||||
|
|
||||||
|
_placeholder2D = new Texture2D(desc);
|
||||||
|
_placeholder2D.SamplerState = SamplerStateManager.PointWrap;
|
||||||
|
Color color = Color.Cyan;
|
||||||
|
_placeholder2D.SetData<Color>(&color);
|
||||||
|
|
||||||
|
Content.ManageAsset(_placeholder2D);
|
||||||
|
_placeholder2D.ReleaseRef();
|
||||||
|
|
||||||
|
_placeholder2D.[Friend]Complete = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _placeholder2D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Asset GetErrorAsset(Type assetType)
|
||||||
|
{
|
||||||
|
switch (assetType)
|
||||||
|
{
|
||||||
|
case typeof(Texture2D):
|
||||||
|
fallthrough;
|
||||||
|
default:
|
||||||
|
if (_error2D == null)
|
||||||
|
{
|
||||||
|
Texture2DDesc desc = .(2, 2, .R8G8B8A8_UNorm, 1, 1, .Immutable, .None);
|
||||||
|
|
||||||
|
_error2D = new Texture2D(desc);
|
||||||
|
_error2D.SamplerState = SamplerStateManager.PointWrap;
|
||||||
|
Color[4] color = .(Color.HotPink, Color.Black, Color.Black, Color.HotPink);
|
||||||
|
_error2D.SetData<Color>(&color);
|
||||||
|
|
||||||
|
Content.ManageAsset(_error2D);
|
||||||
|
_error2D.ReleaseRef();
|
||||||
|
|
||||||
|
_placeholder2D.[Friend]Complete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _error2D;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
ShowComponentEditor<TransformComponent>("Transform", entity, => ShowTransformComponentEditor);
|
ShowComponentEditor<TransformComponent>("Transform", entity, => ShowTransformComponentEditor);
|
||||||
ShowComponentEditor<CameraComponent>("Camera", entity, => ShowCameraComponentEditor, => ShowComponentContextMenu<CameraComponent>);
|
ShowComponentEditor<CameraComponent>("Camera", entity, => ShowCameraComponentEditor, => ShowComponentContextMenu<CameraComponent>);
|
||||||
ShowComponentEditor<SpriterRendererComponent>("Sprite Renderer", entity, => ShowSpriteRendererComponentEditor, => ShowComponentContextMenu<SpriterRendererComponent>);
|
ShowComponentEditor<SpriteRendererComponent>("Sprite Renderer", entity, => ShowSpriteRendererComponentEditor, => ShowComponentContextMenu<SpriteRendererComponent>);
|
||||||
|
ShowComponentEditor<CircleRendererComponent>("Circle Renderer", entity, => ShowCircleRendererComponentEditor, => ShowComponentContextMenu<CircleRendererComponent>);
|
||||||
ShowComponentEditor<MeshRendererComponent>("Mesh Renderer", entity, => ShowMeshRendererComponentEditor, => ShowComponentContextMenu<MeshRendererComponent>);
|
ShowComponentEditor<MeshRendererComponent>("Mesh Renderer", entity, => ShowMeshRendererComponentEditor, => ShowComponentContextMenu<MeshRendererComponent>);
|
||||||
ShowComponentEditor<LightComponent>("Light", entity, => ShowLightComponentEditor, => ShowComponentContextMenu<LightComponent>);
|
ShowComponentEditor<LightComponent>("Light", entity, => ShowLightComponentEditor, => ShowComponentContextMenu<LightComponent>);
|
||||||
ShowComponentEditor<MeshComponent>("Mesh", entity, => ShowMeshComponentEditor, => ShowComponentContextMenu<MeshComponent>);
|
ShowComponentEditor<MeshComponent>("Mesh", entity, => ShowMeshComponentEditor, => ShowComponentContextMenu<MeshComponent>);
|
||||||
@@ -117,18 +118,18 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
private static void ShowNameComponentEditor(Entity entity)
|
private static void ShowNameComponentEditor(Entity entity)
|
||||||
{
|
{
|
||||||
if (!entity.HasComponent<DebugNameComponent>())
|
if (!entity.HasComponent<NameComponent>())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
char8[256] nameBuffer = default;
|
char8[256] nameBuffer = default;
|
||||||
|
|
||||||
DebugNameComponent* component = entity.GetComponent<DebugNameComponent>();
|
NameComponent* component = entity.GetComponent<NameComponent>();
|
||||||
|
|
||||||
String name = null;
|
StringView name = null;
|
||||||
|
|
||||||
if(component != null)
|
if(component != null)
|
||||||
{
|
{
|
||||||
name = component.DebugName;
|
name = component.Name;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -142,11 +143,10 @@ namespace GlitchyEditor.EditWindows
|
|||||||
{
|
{
|
||||||
if(component == null)
|
if(component == null)
|
||||||
{
|
{
|
||||||
component = entity.AddComponent<DebugNameComponent>();
|
component = entity.AddComponent<NameComponent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
component.DebugName.Clear();
|
component.Name = StringView(&nameBuffer);
|
||||||
component.DebugName.Append(&nameBuffer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +250,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ShowSpriteRendererComponentEditor(Entity entity, SpriterRendererComponent* spriteRendererComponent)
|
private static void ShowSpriteRendererComponentEditor(Entity entity, SpriteRendererComponent* spriteRendererComponent)
|
||||||
{
|
{
|
||||||
ColorRGBA spriteColor = ColorRGBA.LinearToSRGB(spriteRendererComponent.Color);
|
ColorRGBA spriteColor = ColorRGBA.LinearToSRGB(spriteRendererComponent.Color);
|
||||||
if (ImGui.ColorEdit4("Color", ref spriteColor))
|
if (ImGui.ColorEdit4("Color", ref spriteColor))
|
||||||
@@ -268,10 +268,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
StringView path = .((char8*)payload.Data, (int)payload.DataSize);
|
StringView path = .((char8*)payload.Data, (int)payload.DataSize);
|
||||||
|
|
||||||
using (Texture2D texture = Content.LoadAsset<Texture2D>(path))
|
spriteRendererComponent.Sprite = Content.LoadAsset(path);
|
||||||
{
|
|
||||||
spriteRendererComponent.Sprite = texture;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.EndDragDropTarget();
|
ImGui.EndDragDropTarget();
|
||||||
@@ -279,8 +276,36 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
|
|
||||||
ImGui.EditVector<4>("UV Transform", ref *(float[4]*)&spriteRendererComponent.UvTransform);
|
ImGui.EditVector<4>("UV Transform", ref *(float[4]*)&spriteRendererComponent.UvTransform);
|
||||||
|
}
|
||||||
|
|
||||||
ImGui.Checkbox("Is Circle", &spriteRendererComponent.IsCircle);
|
private static void ShowCircleRendererComponentEditor(Entity entity, CircleRendererComponent* circleRendererComponent)
|
||||||
|
{
|
||||||
|
ColorRGBA spriteColor = ColorRGBA.LinearToSRGB(circleRendererComponent.Color);
|
||||||
|
if (ImGui.ColorEdit4("Color", ref spriteColor))
|
||||||
|
circleRendererComponent.Color = ColorRGBA.SRgbToLinear(spriteColor);
|
||||||
|
|
||||||
|
ImGui.Button("Texture");
|
||||||
|
|
||||||
|
if (ImGui.BeginDragDropTarget())
|
||||||
|
{
|
||||||
|
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM");
|
||||||
|
|
||||||
|
if (payload != null)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Warning("");
|
||||||
|
|
||||||
|
StringView path = .((char8*)payload.Data, (int)payload.DataSize);
|
||||||
|
|
||||||
|
circleRendererComponent.Sprite = Content.LoadAsset(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndDragDropTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ImGui.EditVector<4>("UV Transform", ref *(float[4]*)&circleRendererComponent.UvTransform);
|
||||||
|
|
||||||
|
ImGui.DragFloat("Inner Radius", &circleRendererComponent.InnerRadius, 0.1f, 0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ShowMeshRendererComponentEditor(Entity entity, MeshRendererComponent* meshRendererComponent)
|
private static void ShowMeshRendererComponentEditor(Entity entity, MeshRendererComponent* meshRendererComponent)
|
||||||
@@ -301,10 +326,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
{
|
{
|
||||||
StringView fullpath = .((char8*)payload.Data, (int)payload.DataSize);
|
StringView fullpath = .((char8*)payload.Data, (int)payload.DataSize);
|
||||||
|
|
||||||
using (Material loadedMaterial = Content.LoadAsset<Material>(fullpath))
|
meshRendererComponent.Material = Content.LoadAsset(fullpath);
|
||||||
{
|
|
||||||
meshRendererComponent.Material = loadedMaterial;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.EndDragDropTarget();
|
ImGui.EndDragDropTarget();
|
||||||
@@ -488,10 +510,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
StringView filePath = fullpath.Substring(0, idx);
|
StringView filePath = fullpath.Substring(0, idx);
|
||||||
StringView meshName = fullpath.Substring(idx + 1);*/
|
StringView meshName = fullpath.Substring(idx + 1);*/
|
||||||
|
|
||||||
using (GeometryBinding geometry = Content.LoadAsset<GeometryBinding>(fullpath))
|
meshComponent.Mesh = Content.LoadAsset(fullpath);
|
||||||
{
|
|
||||||
meshComponent.Mesh = geometry;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: support multiple primitives (treat every primitive as a single mesh? or: mesh can have multiple primitives)
|
// TODO: support multiple primitives (treat every primitive as a single mesh? or: mesh can have multiple primitives)
|
||||||
/*using (GeometryBinding binding = ModelLoader.LoadMesh(filePath, meshName, 0))
|
/*using (GeometryBinding binding = ModelLoader.LoadMesh(filePath, meshName, 0))
|
||||||
@@ -557,7 +576,8 @@ namespace GlitchyEditor.EditWindows
|
|||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
ShowComponentButton<CameraComponent>("Camera");
|
ShowComponentButton<CameraComponent>("Camera");
|
||||||
ShowComponentButton<SpriterRendererComponent>("Sprite Renderer");
|
ShowComponentButton<SpriteRendererComponent>("Sprite Renderer");
|
||||||
|
ShowComponentButton<CircleRendererComponent>("Circle Renderer");
|
||||||
ShowComponentButton<LightComponent>("Light");
|
ShowComponentButton<LightComponent>("Light");
|
||||||
ShowComponentButton<Rigidbody2DComponent>("Rigidbody 2D");
|
ShowComponentButton<Rigidbody2DComponent>("Rigidbody 2D");
|
||||||
ShowComponentButton<BoxCollider2DComponent>("Box collider 2D");
|
ShowComponentButton<BoxCollider2DComponent>("Box collider 2D");
|
||||||
|
|||||||
@@ -14,8 +14,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
class ContentBrowserWindow : EditorWindow
|
class ContentBrowserWindow : EditorWindow
|
||||||
{
|
{
|
||||||
// TODO: Get from project
|
public const String s_WindowTitle = "Content Browser";
|
||||||
//const String ContentDirectory = "./content";
|
|
||||||
|
|
||||||
private append String _currentDirectory = .();
|
private append String _currentDirectory = .();
|
||||||
|
|
||||||
@@ -43,7 +42,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
_currentDirectory.Set(_manager.ContentDirectory);
|
_currentDirectory.Set(_manager.ContentDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ImGui.Begin("Content Browser", &_open, .None))
|
if(!ImGui.Begin(s_WindowTitle, &_open, .None))
|
||||||
{
|
{
|
||||||
ImGui.End();
|
ImGui.End();
|
||||||
return;
|
return;
|
||||||
@@ -58,12 +57,20 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
ImGui.Columns(2);
|
ImGui.Columns(2);
|
||||||
|
|
||||||
|
ImGui.BeginChild("Sidebar");
|
||||||
|
|
||||||
DrawDirectorySideBar();
|
DrawDirectorySideBar();
|
||||||
|
|
||||||
|
ImGui.EndChild();
|
||||||
|
|
||||||
ImGui.NextColumn();
|
ImGui.NextColumn();
|
||||||
|
|
||||||
|
ImGui.BeginChild("Files");
|
||||||
|
|
||||||
DrawCurrentDirectory();
|
DrawCurrentDirectory();
|
||||||
|
|
||||||
|
ImGui.EndChild();
|
||||||
|
|
||||||
ImGui.Columns(1);
|
ImGui.Columns(1);
|
||||||
|
|
||||||
ImGui.End();
|
ImGui.End();
|
||||||
@@ -149,6 +156,24 @@ namespace GlitchyEditor.EditWindows
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentDirectoryNode->Parent != null)
|
||||||
|
{
|
||||||
|
ImGui.PushID("Back");
|
||||||
|
|
||||||
|
DrawBackButton(currentDirectoryNode->Parent);
|
||||||
|
|
||||||
|
// X-Coordinate of the right side of the current entry.
|
||||||
|
float currentButtonRight = ImGui.GetItemRectMax().x;
|
||||||
|
// Expected right-Coordinate if next entry was on the same line.
|
||||||
|
float expectedButtonRight = currentButtonRight + style.ItemSpacing.x + DirectoryItemSize.X;
|
||||||
|
|
||||||
|
// If the next button won't fit on the same line we start a new line.
|
||||||
|
if (expectedButtonRight < window_visible_x2)
|
||||||
|
ImGui.SameLine();
|
||||||
|
|
||||||
|
ImGui.PopID();
|
||||||
|
}
|
||||||
|
|
||||||
for (var entry in currentDirectoryNode->Children)
|
for (var entry in currentDirectoryNode->Children)
|
||||||
{
|
{
|
||||||
ImGui.PushID(entry->Name);
|
ImGui.PushID(entry->Name);
|
||||||
@@ -168,6 +193,45 @@ namespace GlitchyEditor.EditWindows
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Renders the button for the given directory item.
|
||||||
|
private void DrawBackButton(TreeNode<AssetNode> entry)
|
||||||
|
{
|
||||||
|
ImGui.BeginChild("item", (.)DirectoryItemSize);
|
||||||
|
|
||||||
|
if (entry->Path == _selectedFile)
|
||||||
|
{
|
||||||
|
var color = ImGui.GetStyleColorVec4(.ButtonHovered);
|
||||||
|
ImGui.PushStyleColor(.Button, *color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImGui.PushStyleColor(.Button, ImGui.Vec4(0, 0, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
SubTexture2D image = s_FolderTexture;
|
||||||
|
|
||||||
|
ImGui.ImageButton(image, (.)(DirectoryItemSize - padding));
|
||||||
|
|
||||||
|
ImGui.PopStyleColor();
|
||||||
|
|
||||||
|
if (ImGui.IsItemHovered() && ImGui.IsMouseClicked(.Left))
|
||||||
|
{
|
||||||
|
if (_selectedFile != entry->Path)
|
||||||
|
{
|
||||||
|
_selectedFile.Set(entry->Path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.IsItemHovered() && ImGui.IsMouseDoubleClicked(.Left))
|
||||||
|
{
|
||||||
|
EntryDoubleClicked(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.TextUnformatted("..");
|
||||||
|
|
||||||
|
ImGui.EndChild();
|
||||||
|
}
|
||||||
|
|
||||||
/// Renders the button for the given directory item.
|
/// Renders the button for the given directory item.
|
||||||
private void DrawDirectoryItem(TreeNode<AssetNode> entry)
|
private void DrawDirectoryItem(TreeNode<AssetNode> entry)
|
||||||
{
|
{
|
||||||
|
|||||||
+45
-41
@@ -9,7 +9,7 @@ using GlitchyEngine.Events;
|
|||||||
|
|
||||||
namespace GlitchyEditor.EditWindows
|
namespace GlitchyEditor.EditWindows
|
||||||
{
|
{
|
||||||
class SceneViewportWindow : EditorWindow
|
class EditorViewportWindow : EditorWindow
|
||||||
{
|
{
|
||||||
public const String s_WindowTitle = "Scene";
|
public const String s_WindowTitle = "Scene";
|
||||||
|
|
||||||
@@ -27,6 +27,8 @@ namespace GlitchyEditor.EditWindows
|
|||||||
private float _angleSnap = 45.0f;
|
private float _angleSnap = 45.0f;
|
||||||
private bool _doSnap = false;
|
private bool _doSnap = false;
|
||||||
|
|
||||||
|
private bool _visible;
|
||||||
|
|
||||||
public uint32 SelectedEntityId {get; private set; }
|
public uint32 SelectedEntityId {get; private set; }
|
||||||
public bool SelectionChanged { get; private set; }
|
public bool SelectionChanged { get; private set; }
|
||||||
|
|
||||||
@@ -52,6 +54,8 @@ namespace GlitchyEditor.EditWindows
|
|||||||
/// Gets or sets whether the editor functionality (gizmo, picking etc.) is enabled.
|
/// Gets or sets whether the editor functionality (gizmo, picking etc.) is enabled.
|
||||||
public bool EditorMode { get; set; } = true
|
public bool EditorMode { get; set; } = true
|
||||||
|
|
||||||
|
public bool Visible => _visible;
|
||||||
|
|
||||||
public this(Editor editor)
|
public this(Editor editor)
|
||||||
{
|
{
|
||||||
_editor = editor;
|
_editor = editor;
|
||||||
@@ -65,9 +69,13 @@ namespace GlitchyEditor.EditWindows
|
|||||||
if(!ImGui.Begin(s_WindowTitle, &_open, .NoScrollbar | .MenuBar))
|
if(!ImGui.Begin(s_WindowTitle, &_open, .NoScrollbar | .MenuBar))
|
||||||
{
|
{
|
||||||
ImGui.End();
|
ImGui.End();
|
||||||
|
|
||||||
|
_visible = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_visible = true;
|
||||||
|
|
||||||
let viewportSize = ImGui.GetContentRegionAvail();
|
let viewportSize = ImGui.GetContentRegionAvail();
|
||||||
|
|
||||||
if(ImGui.IsWindowHovered() && Input.IsMouseButtonPressing(.RightButton))
|
if(ImGui.IsWindowHovered() && Input.IsMouseButtonPressing(.RightButton))
|
||||||
@@ -78,30 +86,27 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
_hasFocus = ImGui.IsWindowFocused();
|
_hasFocus = ImGui.IsWindowFocused();
|
||||||
|
|
||||||
if (EditorMode)
|
ShowMenuBar();
|
||||||
|
|
||||||
|
if (_editor.CurrentCamera.[Friend]BindMouse && _hasFocus)
|
||||||
|
WrapMouseInViewport();
|
||||||
|
|
||||||
|
// If we wrapped this frame we weren't hovering because the cursor has to be be out of bounds to wrap
|
||||||
|
_editor.CurrentCamera.AllowMove = _hasFocus && (ImGui.IsWindowHovered() || _wrappedCursor);
|
||||||
|
|
||||||
|
if (_hasFocus && !_editor.CurrentCamera.InUse)
|
||||||
{
|
{
|
||||||
ShowMenuBar();
|
if (Input.IsKeyPressing(.Q))
|
||||||
|
_gizmoType = .TRANSLATE;
|
||||||
if (_editor.CurrentCamera.[Friend]BindMouse && _hasFocus)
|
if (Input.IsKeyPressing(.W))
|
||||||
WrapMouseInViewport();
|
_gizmoType = .ROTATE;
|
||||||
|
if (Input.IsKeyPressing(.E))
|
||||||
|
_gizmoType = .SCALE;
|
||||||
|
|
||||||
// If we wrapped this frame we weren't hovering because the cursor has to be be out of bounds to wrap
|
if (Input.IsKeyPressing(.G))
|
||||||
_editor.CurrentCamera.AllowMove = _hasFocus && (ImGui.IsWindowHovered() || _wrappedCursor);
|
_gizmoMode = .WORLD;
|
||||||
|
if (Input.IsKeyPressing(.L))
|
||||||
if (_hasFocus && !_editor.CurrentCamera.InUse)
|
_gizmoMode = .LOCAL;
|
||||||
{
|
|
||||||
if (Input.IsKeyPressing(.Q))
|
|
||||||
_gizmoType = .TRANSLATE;
|
|
||||||
if (Input.IsKeyPressing(.W))
|
|
||||||
_gizmoType = .ROTATE;
|
|
||||||
if (Input.IsKeyPressing(.E))
|
|
||||||
_gizmoType = .SCALE;
|
|
||||||
|
|
||||||
if (Input.IsKeyPressing(.G))
|
|
||||||
_gizmoMode = .WORLD;
|
|
||||||
if (Input.IsKeyPressing(.L))
|
|
||||||
_gizmoMode = .LOCAL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_renderTarget != null)
|
if(_renderTarget != null)
|
||||||
@@ -111,14 +116,11 @@ namespace GlitchyEditor.EditWindows
|
|||||||
//ImGui.Image(_editor.CurrentScene.[Friend]_compositeTarget.GetViewBinding(0), viewportSize);
|
//ImGui.Image(_editor.CurrentScene.[Friend]_compositeTarget.GetViewBinding(0), viewportSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EditorMode)
|
HandleDropTarget();
|
||||||
{
|
|
||||||
HandleDropTarget();
|
bool gizmoUsed = DrawImGuizmo(viewportSize);
|
||||||
|
|
||||||
bool gizmoUsed = DrawImGuizmo(viewportSize);
|
MousePicking(viewportSize, gizmoUsed);
|
||||||
|
|
||||||
MousePicking(viewportSize, gizmoUsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.End();
|
ImGui.End();
|
||||||
|
|
||||||
@@ -156,25 +158,27 @@ namespace GlitchyEditor.EditWindows
|
|||||||
let winPos = (Vector2)ImGui.GetWindowPos();
|
let winPos = (Vector2)ImGui.GetWindowPos();
|
||||||
let regionMin = winPos + (Vector2)ImGui.GetWindowContentRegionMin();
|
let regionMin = winPos + (Vector2)ImGui.GetWindowContentRegionMin();
|
||||||
let regionMax = winPos + (Vector2)ImGui.GetWindowContentRegionMax();
|
let regionMax = winPos + (Vector2)ImGui.GetWindowContentRegionMax();
|
||||||
|
|
||||||
|
ImGui.DrawRect((.)regionMin, (.)regionMax, .(0, 255, 0));
|
||||||
|
|
||||||
Vector2 newMousePos = mousePos;
|
Vector2 newMousePos = mousePos;
|
||||||
|
|
||||||
if (mousePos.X < regionMin.X)
|
if (mousePos.X < regionMin.X + 1)
|
||||||
{
|
{
|
||||||
newMousePos.X = regionMax.X - 1;
|
newMousePos.X = regionMax.X - 2;
|
||||||
}
|
}
|
||||||
else if (mousePos.X > regionMax.X - 1)
|
else if (mousePos.X > regionMax.X - 1)
|
||||||
{
|
{
|
||||||
newMousePos.X = regionMin.X + 1;
|
newMousePos.X = regionMin.X + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mousePos.Y < regionMin.Y)
|
if (mousePos.Y < regionMin.Y + 1)
|
||||||
{
|
{
|
||||||
newMousePos.Y = regionMax.Y - 1;
|
newMousePos.Y = regionMax.Y - 100;
|
||||||
}
|
}
|
||||||
else if (mousePos.Y > regionMax.Y - 1)
|
else if (mousePos.Y > regionMax.Y - 1)
|
||||||
{
|
{
|
||||||
newMousePos.Y = regionMin.Y + 1;
|
newMousePos.Y = regionMin.Y + 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newMousePos != mousePos)
|
if (newMousePos != mousePos)
|
||||||
@@ -193,8 +197,8 @@ namespace GlitchyEditor.EditWindows
|
|||||||
{
|
{
|
||||||
Vector2 relativeMouse = (Vector2)ImGui.GetMousePos() - (Vector2)ImGui.GetItemRectMin();
|
Vector2 relativeMouse = (Vector2)ImGui.GetMousePos() - (Vector2)ImGui.GetItemRectMin();
|
||||||
|
|
||||||
int rtWidth = _editor.CurrentScene.[Friend]_compositeTarget.Width;
|
int rtWidth = _editor.EditorSceneRenderer.CompositeTarget.Width;
|
||||||
int rtHeight = _editor.CurrentScene.[Friend]_compositeTarget.Height;
|
int rtHeight = _editor.EditorSceneRenderer.CompositeTarget.Height;
|
||||||
|
|
||||||
if (Input.IsMouseButtonPressing(.LeftButton) &&
|
if (Input.IsMouseButtonPressing(.LeftButton) &&
|
||||||
ImGui.IsWindowHovered() && !gizmoUsed && !_editor.CurrentCamera.InUse &&
|
ImGui.IsWindowHovered() && !gizmoUsed && !_editor.CurrentCamera.InUse &&
|
||||||
@@ -204,7 +208,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
{
|
{
|
||||||
uint32 id = uint32.MaxValue;
|
uint32 id = uint32.MaxValue;
|
||||||
|
|
||||||
_editor.CurrentScene.[Friend]_compositeTarget.GetData<uint32>(&id, 1, (.)relativeMouse.X, (.)relativeMouse.Y, 1, 1);
|
_editor.EditorSceneRenderer.CompositeTarget.GetData<uint32>(&id, 1, (.)relativeMouse.X, (.)relativeMouse.Y, 1, 1);
|
||||||
|
|
||||||
SelectionChanged = true;
|
SelectionChanged = true;
|
||||||
SelectedEntityId = id;
|
SelectedEntityId = id;
|
||||||
@@ -301,11 +301,11 @@ namespace GlitchyEditor.EditWindows
|
|||||||
{
|
{
|
||||||
String name = null;
|
String name = null;
|
||||||
|
|
||||||
var nameComponent = tree.Value.GetComponent<DebugNameComponent>();
|
var nameComponent = tree.Value.GetComponent<NameComponent>();
|
||||||
|
|
||||||
if(nameComponent != null)
|
if(nameComponent != null)
|
||||||
{
|
{
|
||||||
name = nameComponent.DebugName;
|
name = scope:: .(nameComponent.Name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -501,13 +501,13 @@ namespace GlitchyEditor.EditWindows
|
|||||||
{
|
{
|
||||||
Entity entity = .(entityId, _scene);
|
Entity entity = .(entityId, _scene);
|
||||||
|
|
||||||
String name = null;
|
StringView name = null;
|
||||||
|
|
||||||
var nameComponent = entity.GetComponent<DebugNameComponent>();
|
var nameComponent = entity.GetComponent<NameComponent>();
|
||||||
|
|
||||||
if(nameComponent != null)
|
if(nameComponent != null)
|
||||||
{
|
{
|
||||||
name = nameComponent.DebugName;
|
name = nameComponent.Name;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
using System;
|
||||||
|
using ImGui;
|
||||||
|
using GlitchyEngine.Renderer;
|
||||||
|
using GlitchyEngine.Math;
|
||||||
|
using GlitchyEngine;
|
||||||
|
using GlitchyEngine.World;
|
||||||
|
using ImGuizmo;
|
||||||
|
using GlitchyEngine.Events;
|
||||||
|
|
||||||
|
namespace GlitchyEditor.EditWindows
|
||||||
|
{
|
||||||
|
class GameViewportWindow : EditorWindow
|
||||||
|
{
|
||||||
|
public const String s_WindowTitle = "Game";
|
||||||
|
|
||||||
|
private ImGui.Vec2 _oldViewportSize = .(100, 100);
|
||||||
|
private bool _viewPortChanged;
|
||||||
|
|
||||||
|
private bool _visible;
|
||||||
|
|
||||||
|
private RenderTargetGroup _renderTarget ~ _?.ReleaseRef();
|
||||||
|
|
||||||
|
public Vector2 ViewportSize => (Vector2)_oldViewportSize;
|
||||||
|
// Occurs when the viewport is resized.
|
||||||
|
public Event<EventHandler<Vector2>> ViewportSizeChanged ~ _.Dispose();
|
||||||
|
// Occurs when an entity was clicked.
|
||||||
|
public Event<EventHandler<uint32>> EntityClicked ~ _.Dispose();
|
||||||
|
|
||||||
|
/// The render target that is shown in the viewport window.
|
||||||
|
public RenderTargetGroup RenderTarget
|
||||||
|
{
|
||||||
|
get => _renderTarget;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(_renderTarget == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SetReference!(_renderTarget, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Visible => _visible;
|
||||||
|
|
||||||
|
public this(Editor editor)
|
||||||
|
{
|
||||||
|
_editor = editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void InternalShow()
|
||||||
|
{
|
||||||
|
ImGui.PushStyleVar(.WindowPadding, ImGui.Vec2(1, 1));
|
||||||
|
defer ImGui.PopStyleVar();
|
||||||
|
|
||||||
|
if(!ImGui.Begin(s_WindowTitle, &_open, .NoScrollbar | .MenuBar))
|
||||||
|
{
|
||||||
|
ImGui.End();
|
||||||
|
|
||||||
|
_visible = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_visible = true;
|
||||||
|
|
||||||
|
let viewportSize = ImGui.GetContentRegionAvail();
|
||||||
|
|
||||||
|
if(ImGui.IsWindowHovered() && Input.IsMouseButtonPressing(.RightButton))
|
||||||
|
{
|
||||||
|
let currentWindow = ImGui.GetCurrentWindow();
|
||||||
|
ImGui.FocusWindow(currentWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
_hasFocus = ImGui.IsWindowFocused();
|
||||||
|
|
||||||
|
if(_renderTarget != null)
|
||||||
|
{
|
||||||
|
ImGui.Image(_renderTarget.GetViewBinding(0), viewportSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.End();
|
||||||
|
|
||||||
|
if(_oldViewportSize != viewportSize)
|
||||||
|
{
|
||||||
|
ViewportSizeChanged.Invoke(this, (Vector2)viewportSize);
|
||||||
|
_viewPortChanged = true;
|
||||||
|
_oldViewportSize = viewportSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Provides the ImGui Drop target and handles dropped payload.
|
||||||
|
private void HandleDropTarget()
|
||||||
|
{
|
||||||
|
if (ImGui.BeginDragDropTarget())
|
||||||
|
{
|
||||||
|
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM");
|
||||||
|
|
||||||
|
if (payload != null)
|
||||||
|
{
|
||||||
|
StringView path = .((char8*)payload.Data, (int)payload.DataSize);
|
||||||
|
_editor.RequestOpenScene(this, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndDragDropTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,8 @@ namespace GlitchyEditor.EditWindows;
|
|||||||
|
|
||||||
class PropertiesWindow : EditorWindow
|
class PropertiesWindow : EditorWindow
|
||||||
{
|
{
|
||||||
|
public const String s_WindowTitle = "Properties";
|
||||||
|
|
||||||
private AssetPropertiesEditor _currentPropertiesEditor ~ delete _;
|
private AssetPropertiesEditor _currentPropertiesEditor ~ delete _;
|
||||||
|
|
||||||
private bool _lockCurrentAsset;
|
private bool _lockCurrentAsset;
|
||||||
@@ -18,7 +20,7 @@ class PropertiesWindow : EditorWindow
|
|||||||
|
|
||||||
private append String _selectedFileName = .();
|
private append String _selectedFileName = .();
|
||||||
|
|
||||||
private Asset _currentAsset ~ _?.ReleaseRef();
|
private AssetHandle _currentAssetHandle;
|
||||||
|
|
||||||
public this(Editor editor)
|
public this(Editor editor)
|
||||||
{
|
{
|
||||||
@@ -28,7 +30,7 @@ class PropertiesWindow : EditorWindow
|
|||||||
protected override void InternalShow()
|
protected override void InternalShow()
|
||||||
{
|
{
|
||||||
defer { ImGui.End(); }
|
defer { ImGui.End(); }
|
||||||
if(!ImGui.Begin("Properties", &_open, .None))
|
if(!ImGui.Begin(s_WindowTitle, &_open, .None))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: make a little button in title bar?
|
// TODO: make a little button in title bar?
|
||||||
@@ -73,12 +75,13 @@ class PropertiesWindow : EditorWindow
|
|||||||
|
|
||||||
if (assetFile == null)
|
if (assetFile == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Asset asset = _editor.ContentManager.GetAsset(null, _currentAssetHandle);
|
||||||
|
|
||||||
// We need the actual asset for preview and sometimes for editing
|
// We need the actual asset for preview and sometimes for editing
|
||||||
if (_currentAsset?.Identifier != assetFile.Identifier)
|
if (asset?.Identifier != assetFile.Identifier)
|
||||||
{
|
{
|
||||||
_currentAsset?.ReleaseRef();
|
_currentAssetHandle = _editor.ContentManager.LoadAsset(assetFile.Identifier);
|
||||||
_currentAsset = _editor.ContentManager.LoadAsset(assetFile.Identifier);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: allow changing AssetLoader
|
// TODO: allow changing AssetLoader
|
||||||
@@ -106,7 +109,8 @@ class PropertiesWindow : EditorWindow
|
|||||||
|
|
||||||
if (ImGui.Button("Save Asset"))
|
if (ImGui.Button("Save Asset"))
|
||||||
{
|
{
|
||||||
_editor.ContentManager.SaveAsset(_currentAsset);
|
Asset asset = _editor.ContentManager.GetAsset(null, _currentAssetHandle);
|
||||||
|
_editor.ContentManager.SaveAsset(asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!assetFile.AssetConfig.Config.Changed)
|
if (!assetFile.AssetConfig.Config.Changed)
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ namespace GlitchyEditor
|
|||||||
|
|
||||||
private EntityHierarchyWindow _entityHierarchyWindow ~ delete _;
|
private EntityHierarchyWindow _entityHierarchyWindow ~ delete _;
|
||||||
private ComponentEditWindow _componentEditWindow ~ delete _;
|
private ComponentEditWindow _componentEditWindow ~ delete _;
|
||||||
private SceneViewportWindow _sceneViewportWindow~ delete _;
|
private EditorViewportWindow _sceneViewportWindow ~ delete _;
|
||||||
|
private GameViewportWindow _gameViewportWindow ~ delete _;
|
||||||
private ContentBrowserWindow _contentBrowserWindow ~ delete _;
|
private ContentBrowserWindow _contentBrowserWindow ~ delete _;
|
||||||
private PropertiesWindow _propertiesWindow ~ delete _;
|
private PropertiesWindow _propertiesWindow ~ delete _;
|
||||||
|
|
||||||
@@ -26,6 +27,9 @@ namespace GlitchyEditor
|
|||||||
get => _scene;
|
get => _scene;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
if (_scene == value)
|
||||||
|
return;
|
||||||
|
|
||||||
_scene = value;
|
_scene = value;
|
||||||
_entityHierarchyWindow.SetContext(_scene);
|
_entityHierarchyWindow.SetContext(_scene);
|
||||||
}
|
}
|
||||||
@@ -35,7 +39,8 @@ namespace GlitchyEditor
|
|||||||
|
|
||||||
public EntityHierarchyWindow EntityHierarchyWindow => _entityHierarchyWindow;
|
public EntityHierarchyWindow EntityHierarchyWindow => _entityHierarchyWindow;
|
||||||
public ComponentEditWindow ComponentEditWindow => _componentEditWindow;
|
public ComponentEditWindow ComponentEditWindow => _componentEditWindow;
|
||||||
public SceneViewportWindow SceneViewportWindow => _sceneViewportWindow;
|
public EditorViewportWindow SceneViewportWindow => _sceneViewportWindow;
|
||||||
|
public GameViewportWindow GameViewportWindow => _gameViewportWindow;
|
||||||
public ContentBrowserWindow ContentBrowserWindow => _contentBrowserWindow;
|
public ContentBrowserWindow ContentBrowserWindow => _contentBrowserWindow;
|
||||||
public PropertiesWindow PropertiesWindow => _propertiesWindow;
|
public PropertiesWindow PropertiesWindow => _propertiesWindow;
|
||||||
|
|
||||||
@@ -43,6 +48,9 @@ namespace GlitchyEditor
|
|||||||
|
|
||||||
public Event<EventHandler<StringView>> RequestOpenScene ~ _.Dispose();
|
public Event<EventHandler<StringView>> RequestOpenScene ~ _.Dispose();
|
||||||
|
|
||||||
|
public SceneRenderer GameSceneRenderer {get; set;}
|
||||||
|
public SceneRenderer EditorSceneRenderer {get; set;}
|
||||||
|
|
||||||
/// Creates a new editor for the given world
|
/// Creates a new editor for the given world
|
||||||
public this(Scene scene, EditorContentManager contentManager)
|
public this(Scene scene, EditorContentManager contentManager)
|
||||||
{
|
{
|
||||||
@@ -54,7 +62,8 @@ namespace GlitchyEditor
|
|||||||
|
|
||||||
private void InitWindows()
|
private void InitWindows()
|
||||||
{
|
{
|
||||||
_sceneViewportWindow = new SceneViewportWindow(this);
|
_sceneViewportWindow = new EditorViewportWindow(this);
|
||||||
|
_gameViewportWindow = new GameViewportWindow(this);
|
||||||
_entityHierarchyWindow = new EntityHierarchyWindow(this, _scene);
|
_entityHierarchyWindow = new EntityHierarchyWindow(this, _scene);
|
||||||
_componentEditWindow = new ComponentEditWindow(_entityHierarchyWindow);
|
_componentEditWindow = new ComponentEditWindow(_entityHierarchyWindow);
|
||||||
_contentBrowserWindow = new ContentBrowserWindow((.)Application.Get().ContentManager);
|
_contentBrowserWindow = new ContentBrowserWindow((.)Application.Get().ContentManager);
|
||||||
@@ -64,6 +73,7 @@ namespace GlitchyEditor
|
|||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
_sceneViewportWindow.Show();
|
_sceneViewportWindow.Show();
|
||||||
|
_gameViewportWindow.Show();
|
||||||
_entityHierarchyWindow.Show();
|
_entityHierarchyWindow.Show();
|
||||||
_componentEditWindow.Show();
|
_componentEditWindow.Show();
|
||||||
_contentBrowserWindow.Show();
|
_contentBrowserWindow.Show();
|
||||||
|
|||||||
@@ -8,71 +8,11 @@ using GlitchyEngine.Content;
|
|||||||
using GlitchyEditor.Assets;
|
using GlitchyEditor.Assets;
|
||||||
using GlitchyEngine;
|
using GlitchyEngine;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using internal GlitchyEngine.Content.Asset;
|
||||||
|
|
||||||
namespace GlitchyEditor;
|
namespace GlitchyEditor;
|
||||||
|
|
||||||
/*class PreviewImageManager
|
|
||||||
{
|
|
||||||
/// Thread that loads/generates preview images in the background
|
|
||||||
//private Thread _loaderThread;
|
|
||||||
|
|
||||||
/// Set to true to notify the loader to stop
|
|
||||||
//private bool _stopLoader;
|
|
||||||
|
|
||||||
private append Dictionary<String, Texture2D> _previewImages = .() ~ {
|
|
||||||
for (var v in _)
|
|
||||||
{
|
|
||||||
delete v.key;
|
|
||||||
v.value.ReleaseRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
delete _;
|
|
||||||
};
|
|
||||||
|
|
||||||
public Texture2D GetPreviewImage(String assetName)
|
|
||||||
{
|
|
||||||
if (_previewImages.TryGetValue(assetName, let image))
|
|
||||||
{
|
|
||||||
return image..AddRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (assetName.EndsWith(".png", .OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
/*using (Texture2D texture = new Texture2D(assetName, true))
|
|
||||||
{
|
|
||||||
Texture2DDesc desc = .(128, 128, .R8G8B8A8_UNorm_SRGB)
|
|
||||||
{
|
|
||||||
Usage = .Immutable
|
|
||||||
};
|
|
||||||
|
|
||||||
Texture2D myActualTexture = new Texture2D(desc);
|
|
||||||
|
|
||||||
// TODO: Scale down texture (on GPU?)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
Texture2D texture = new Texture2D(assetName, true);
|
|
||||||
|
|
||||||
if (texture.Width <= 128 && texture.Height <= 128)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( texture.MipLevels > 1)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
_previewImages.Add(new String(assetName), texture);
|
|
||||||
|
|
||||||
return texture..AddRef();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Runtime.NotImplemented();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
class EditorContentManager : IContentManager
|
class EditorContentManager : IContentManager
|
||||||
{
|
{
|
||||||
private append String _contentDirectory = .();
|
private append String _contentDirectory = .();
|
||||||
@@ -81,15 +21,20 @@ class EditorContentManager : IContentManager
|
|||||||
|
|
||||||
//private append List<String> _identifiers = .() ~ _.ClearAndDeleteItems();
|
//private append List<String> _identifiers = .() ~ _.ClearAndDeleteItems();
|
||||||
|
|
||||||
private append Dictionary<StringView, Asset> _loadedAssets = .(); // Check if all resources are unloaded
|
private append Dictionary<StringView, AssetHandle> _identiferToHandle = .(); // TODO: Check if all resources are unloaded
|
||||||
|
|
||||||
|
private append Dictionary<AssetHandle, Asset> _handleToAsset = .();
|
||||||
|
|
||||||
private append AssetHierarchy _assetHierarchy = .(this);
|
private append AssetHierarchy _assetHierarchy = .(this);
|
||||||
|
|
||||||
public AssetHierarchy AssetHierarchy => _assetHierarchy;
|
public AssetHierarchy AssetHierarchy => _assetHierarchy;
|
||||||
|
|
||||||
|
private append List<AssetHandle> _reloadQueue = .();
|
||||||
|
|
||||||
public this()
|
public this()
|
||||||
{
|
{
|
||||||
_assetHierarchy.OnFileContentChanged.Add(new => OnFileContentChanged);
|
_assetHierarchy.OnFileContentChanged.Add(new => OnFileContentChanged);
|
||||||
|
_assetHierarchy.OnFileRenamed.Add(new => OnFileRenamed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ~this()
|
public ~this()
|
||||||
@@ -99,46 +44,24 @@ class EditorContentManager : IContentManager
|
|||||||
|
|
||||||
private void OnFileContentChanged(AssetNode assetNode)
|
private void OnFileContentChanged(AssetNode assetNode)
|
||||||
{
|
{
|
||||||
// TODO: Subassets break reloading because we can't find them when we only receive the file that changed...
|
|
||||||
|
|
||||||
// Asset isn't loaded so we don't need to reload it.
|
// Asset isn't loaded so we don't need to reload it.
|
||||||
if (assetNode.AssetFile.LoadedAsset == null)
|
if (assetNode.AssetFile.LoadedAsset == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
String neededAssetLoaderName = assetNode.AssetFile.AssetConfig?.AssetLoader;
|
_reloadQueue.Add(assetNode.AssetFile.LoadedAsset.Handle);
|
||||||
|
}
|
||||||
if (String.IsNullOrWhiteSpace(neededAssetLoaderName))
|
|
||||||
|
public void OnFileRenamed(AssetNode assetNode, StringView oldIdentifier)
|
||||||
|
{
|
||||||
|
// Asset isn't loaded so we don't need to reload it.
|
||||||
|
if (assetNode.AssetFile.LoadedAsset == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
IAssetLoader assetLoader = null;
|
Asset asset = assetNode.AssetFile.LoadedAsset;
|
||||||
|
|
||||||
String loaderNameBuffer = scope String(64);
|
_identiferToHandle.Remove(oldIdentifier);
|
||||||
|
asset.Identifier = assetNode.AssetFile.Identifier;
|
||||||
for (IAssetLoader loader in _assetLoaders)
|
_identiferToHandle.Add(asset.Identifier, asset.Handle);
|
||||||
{
|
|
||||||
loader.GetType().GetName(loaderNameBuffer..Clear());
|
|
||||||
|
|
||||||
if (loaderNameBuffer == neededAssetLoaderName)
|
|
||||||
{
|
|
||||||
assetLoader = loader;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (assetLoader == null)
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Error($"Could not find asset loader \"{neededAssetLoaderName}\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (var assetReloader = assetLoader as IReloadingAssetLoader)
|
|
||||||
{
|
|
||||||
Stream stream = GetStream(assetNode.Path);
|
|
||||||
|
|
||||||
assetReloader.ReloadAsset(assetNode.AssetFile, stream);
|
|
||||||
|
|
||||||
delete stream;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetContentDirectory(StringView contentDirectory)
|
public void SetContentDirectory(StringView contentDirectory)
|
||||||
@@ -152,9 +75,54 @@ class EditorContentManager : IContentManager
|
|||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
|
SwapInLoadedAssets();
|
||||||
|
|
||||||
|
if (!_reloadQueue.IsEmpty)
|
||||||
|
{
|
||||||
|
for (AssetHandle handle in _reloadQueue)
|
||||||
|
{
|
||||||
|
ReloadAsset(handle);
|
||||||
|
}
|
||||||
|
_reloadQueue.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
_assetHierarchy.Update();
|
_assetHierarchy.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Replaces placeholders with the loaded assets
|
||||||
|
private void SwapInLoadedAssets()
|
||||||
|
{
|
||||||
|
// Don't take the lock if we have nothing to do.
|
||||||
|
if (_finishedEntries.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
using (_finishedEntriesLock.Enter())
|
||||||
|
{
|
||||||
|
while (_finishedEntries.Count > 0)
|
||||||
|
{
|
||||||
|
let (placeholder, asset) = _finishedEntries[0];
|
||||||
|
|
||||||
|
delete placeholder.LoadingTask;
|
||||||
|
|
||||||
|
if (asset == null)
|
||||||
|
placeholder.PlaceholderType = .Error;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: I'm not sure whether AssetFiles are guaranteed to persist.
|
||||||
|
// Get the reference here because placeholder wont survive SwapAsset.
|
||||||
|
AssetFile file = placeholder.AssetFile;
|
||||||
|
file.[Friend]_loadedAsset = asset;
|
||||||
|
|
||||||
|
SwapAsset(placeholder, asset);
|
||||||
|
// SwapAsset increases RefCount, but this scope also holds a reference.
|
||||||
|
asset.ReleaseRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
_finishedEntries.RemoveAtFast(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public IAssetLoader GetDefaultAssetLoader(StringView fileExtension)
|
public IAssetLoader GetDefaultAssetLoader(StringView fileExtension)
|
||||||
{
|
{
|
||||||
if (_defaultAssetLoaders.TryGetValue(fileExtension, let value))
|
if (_defaultAssetLoaders.TryGetValue(fileExtension, let value))
|
||||||
@@ -174,9 +142,11 @@ class EditorContentManager : IContentManager
|
|||||||
|
|
||||||
public void RegisterAssetLoader<T>() where T : new, class, IAssetLoader
|
public void RegisterAssetLoader<T>() where T : new, class, IAssetLoader
|
||||||
{
|
{
|
||||||
//Log.EngineLogger.AssertDebug(!_assetLoaders.Any((l) => l.GetType() == typeof(T)), "Asset loader already registered.");
|
// Log.EngineLogger.AssertDebug(!_assetLoaders.Any((l) => l.GetType() == typeof(T)), "Asset loader already registered.");
|
||||||
|
|
||||||
_assetLoaders.Add(new T());
|
T assetLoader = new T();
|
||||||
|
|
||||||
|
_assetLoaders.Add(assetLoader);
|
||||||
|
|
||||||
for (StringView ext in T.FileExtensions)
|
for (StringView ext in T.FileExtensions)
|
||||||
_supportedExtensions.Add(new String(ext));
|
_supportedExtensions.Add(new String(ext));
|
||||||
@@ -237,99 +207,230 @@ class EditorContentManager : IContentManager
|
|||||||
|
|
||||||
public bool IsLoaded(StringView identifier)
|
public bool IsLoaded(StringView identifier)
|
||||||
{
|
{
|
||||||
return _loadedAssets.ContainsKey(identifier);
|
return _identiferToHandle.ContainsKey(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Asset LoadAsset(StringView identifier)
|
public Asset GetAsset(Type assetType, AssetHandle handle)
|
||||||
{
|
{
|
||||||
if (_loadedAssets.TryGetValue(identifier, let asset))
|
Asset asset = null;
|
||||||
|
|
||||||
|
_handleToAsset.TryGetValue(handle, out asset);
|
||||||
|
|
||||||
|
if (var placeholder = asset as PlaceholderAsset)
|
||||||
{
|
{
|
||||||
return asset..AddRef();
|
if (placeholder.PlaceholderType == .Loading)
|
||||||
|
return placeholder.AssetLoader.GetPlaceholderAsset(assetType);
|
||||||
|
else if (placeholder.PlaceholderType == .Error)
|
||||||
|
return placeholder.AssetLoader.GetErrorAsset(assetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find subasset name
|
if (assetType == null)
|
||||||
int poundIndex = identifier.IndexOf('#');
|
{
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
else if (asset?.GetType().IsSubtypeOf(assetType) ?? false)
|
||||||
|
{
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: get default asset
|
||||||
|
|
||||||
StringView resourceName = poundIndex == -1 ? identifier : identifier.Substring(0, poundIndex);
|
return null;
|
||||||
StringView? subassetName = identifier.Substring(poundIndex + 1);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String filePath = scope String(resourceName.Length + _contentDirectory.Length + 2);
|
private void ReloadAsset(AssetHandle handle)
|
||||||
Path.Combine(filePath, _contentDirectory, resourceName);
|
{
|
||||||
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
|
Asset oldAsset = null;
|
||||||
|
|
||||||
Path.Fixup(filePath);
|
if (!_handleToAsset.TryGetValue(handle, out oldAsset))
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error("Can't reload! No asset exists for handle.");
|
||||||
|
|
||||||
//filePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.EngineLogger.AssertDebug(oldAsset != null);
|
||||||
|
|
||||||
|
StringView oldIdentifier = oldAsset.Identifier;
|
||||||
|
|
||||||
|
GetResourceAndSubassetName(oldIdentifier, let resourceName, let subassetName);
|
||||||
|
|
||||||
|
String filePath = scope .();
|
||||||
|
GetResourceFilePath(resourceName, filePath);
|
||||||
|
|
||||||
Result<TreeNode<AssetNode>> resultNode = AssetHierarchy.GetNodeFromPath(filePath);
|
Result<TreeNode<AssetNode>> resultNode = AssetHierarchy.GetNodeFromPath(filePath);
|
||||||
|
|
||||||
if (resultNode case .Err)
|
if (resultNode case .Err)
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error($"Could not find asset \"{filePath}\".");
|
Log.EngineLogger.Error($"Could not find asset \"{filePath}\".");
|
||||||
return null;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetFile file = resultNode->Value.AssetFile;
|
AssetFile file = resultNode->Value.AssetFile;
|
||||||
|
|
||||||
IAssetLoader assetLoader = null;
|
IAssetLoader assetLoader = GetAssetLoader(file);
|
||||||
|
|
||||||
String loaderTypeName = scope .(128);
|
|
||||||
|
|
||||||
for (IAssetLoader loader in _assetLoaders)
|
|
||||||
{
|
|
||||||
loader.GetType().GetName(loaderTypeName..Clear());
|
|
||||||
|
|
||||||
if (loaderTypeName == file.AssetConfig.AssetLoader)
|
|
||||||
{
|
|
||||||
assetLoader = loader;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.EngineLogger.AssertDebug(assetLoader != null);
|
|
||||||
|
|
||||||
Stream stream = GetStream(filePath);
|
Stream stream = GetStream(filePath);
|
||||||
|
|
||||||
|
// TODO: Add async loading!
|
||||||
Asset loadedAsset = assetLoader.LoadAsset(stream, file.AssetConfig.Config, resourceName, subassetName, this);
|
Asset loadedAsset = assetLoader.LoadAsset(stream, file.AssetConfig.Config, resourceName, subassetName, this);
|
||||||
|
|
||||||
delete stream;
|
delete stream;
|
||||||
|
|
||||||
if (loadedAsset == null)
|
if (loadedAsset == null)
|
||||||
return null;
|
return;
|
||||||
|
|
||||||
//String identifierString = new .(identifier);
|
|
||||||
//_identifiers.Add(identifierString);
|
|
||||||
|
|
||||||
//_loadedAssets[identifierString] = loadedAsset;
|
|
||||||
|
|
||||||
|
|
||||||
loadedAsset.Identifier = identifier;
|
|
||||||
ManageAsset(loadedAsset);
|
|
||||||
|
|
||||||
file.[Friend]_loadedAsset = loadedAsset;
|
file.[Friend]_loadedAsset = loadedAsset;
|
||||||
|
|
||||||
return loadedAsset;
|
SwapAsset(oldAsset, loadedAsset);
|
||||||
|
// SwapAsset increases RefCount, but this scope also holds a reference.
|
||||||
|
loadedAsset.ReleaseRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Saves the asset.
|
/// Returns the resource name and, if it exists, the subasset name.
|
||||||
public Result<void> SaveAsset(Asset asset)
|
private void GetResourceAndSubassetName(StringView identifier, out StringView resourceName, out StringView? subassetName)
|
||||||
{
|
{
|
||||||
// Find subasset name
|
int poundIndex = identifier.IndexOf('#');
|
||||||
int poundIndex = asset.Identifier.IndexOf('#');
|
|
||||||
|
|
||||||
StringView resourceName = poundIndex == -1 ? asset.Identifier : asset.Identifier.Substring(0, poundIndex);
|
resourceName = (poundIndex != -1) ? identifier.Substring(0, poundIndex) : identifier;
|
||||||
StringView? subassetName = asset.Identifier.Substring(poundIndex + 1);
|
subassetName = (poundIndex != -1) ? identifier.Substring(poundIndex + 1) : null;
|
||||||
|
}
|
||||||
|
|
||||||
String filePath = scope String(resourceName.Length + _contentDirectory.Length + 2);
|
private void GetResourceFilePath(StringView resourceName, String filePath)
|
||||||
|
{
|
||||||
Path.Combine(filePath, _contentDirectory, resourceName);
|
Path.Combine(filePath, _contentDirectory, resourceName);
|
||||||
|
|
||||||
Path.Fixup(filePath);
|
Path.Fixup(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
//filePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
private enum PlaceholderType
|
||||||
|
{
|
||||||
|
Loading,
|
||||||
|
Error
|
||||||
|
}
|
||||||
|
|
||||||
TreeNode<AssetNode> assetNode = Try!(AssetHierarchy.GetNodeFromPath(filePath));
|
private class PlaceholderAsset : Asset
|
||||||
|
{
|
||||||
|
public AssetFile AssetFile {get; private set;}
|
||||||
|
public Task LoadingTask {get;set;}
|
||||||
|
public IAssetLoader AssetLoader {get; private set;}
|
||||||
|
public PlaceholderType PlaceholderType {get; set;}
|
||||||
|
|
||||||
|
public this(AssetFile assetFile, IAssetLoader assetLoader, PlaceholderType placeholderType)
|
||||||
|
{
|
||||||
|
AssetFile = assetFile;
|
||||||
|
AssetLoader = assetLoader;
|
||||||
|
PlaceholderType = placeholderType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private append Monitor _finishedEntriesLock = .();
|
||||||
|
private append List<(PlaceholderAsset placeholder, Asset newAsset)> _finishedEntries = .();
|
||||||
|
|
||||||
|
private class MissingAsset : Asset {}
|
||||||
|
|
||||||
|
public AssetHandle LoadAsset(StringView identifier, bool blocking = false)
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
AssetFile file = assetNode->AssetFile;
|
// Todo: How strict should we be on paths?
|
||||||
|
String fixedIdentifier = scope String(identifier);
|
||||||
|
AssetIdentifier.Fixup(fixedIdentifier);
|
||||||
|
|
||||||
|
if (_identiferToHandle.TryGetValue(fixedIdentifier, let asset))
|
||||||
|
return asset;
|
||||||
|
|
||||||
|
GetResourceAndSubassetName(fixedIdentifier, let resourceName, let subassetName);
|
||||||
|
|
||||||
|
String filePath = scope .();
|
||||||
|
GetResourceFilePath(resourceName, filePath);
|
||||||
|
|
||||||
|
Result<TreeNode<AssetNode>> resultNode = AssetHierarchy.GetNodeFromPath(filePath);
|
||||||
|
|
||||||
|
if (resultNode case .Err)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error($"Could not find asset \"{filePath}\".");
|
||||||
|
return .Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetFile file = resultNode->Value.AssetFile;
|
||||||
|
|
||||||
|
IAssetLoader assetLoader = GetAssetLoader(file);
|
||||||
|
|
||||||
|
// TODO: what are we supposed to do if we don't find a loader? Sure not crash...
|
||||||
|
Log.EngineLogger.AssertDebug(assetLoader != null);
|
||||||
|
|
||||||
|
Asset loadedAsset;
|
||||||
|
|
||||||
|
// TODO: Support lazy loading for all asset types
|
||||||
|
if (!(assetLoader is EditorTextureAssetLoader) || blocking)
|
||||||
|
{
|
||||||
|
Stream stream = GetStream(filePath);
|
||||||
|
|
||||||
|
loadedAsset = assetLoader.LoadAsset(stream, file.AssetConfig.Config, resourceName, subassetName, this);
|
||||||
|
|
||||||
|
delete stream;
|
||||||
|
|
||||||
|
if (loadedAsset == null)
|
||||||
|
return .Invalid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PlaceholderAsset placeholder = new PlaceholderAsset(file, assetLoader, .Loading);
|
||||||
|
|
||||||
|
String filePath2 = new String(filePath);
|
||||||
|
String newResourceName = new String(resourceName);
|
||||||
|
String newSesourceName = subassetName == null ? null : new String(subassetName.Value);
|
||||||
|
|
||||||
|
placeholder.LoadingTask = new Task(new () => {
|
||||||
|
AsyncLoadAsset(placeholder, filePath2, assetLoader, file,
|
||||||
|
newResourceName, newSesourceName);
|
||||||
|
});
|
||||||
|
|
||||||
|
ThreadPool.QueueUserWorkItem(placeholder.LoadingTask);
|
||||||
|
|
||||||
|
loadedAsset = placeholder;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadedAsset.Identifier = fixedIdentifier;
|
||||||
|
AssetHandle handle = ManageAsset(loadedAsset);
|
||||||
|
// ManageAsset increases RefCount, but this scope also holds a reference.
|
||||||
|
loadedAsset.ReleaseRef();
|
||||||
|
|
||||||
|
// Add to Identifier -> Handle map
|
||||||
|
_identiferToHandle.Add(loadedAsset.Identifier, handle);
|
||||||
|
|
||||||
|
file.[Friend]_loadedAsset = loadedAsset;
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AsyncLoadAsset(PlaceholderAsset placeholder, String filePath, IAssetLoader assetLoader, AssetFile file, String resourceName, String subassetName)
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileResourceFunction!();
|
||||||
|
|
||||||
|
Stream stream = GetStream(filePath);
|
||||||
|
|
||||||
|
Asset loadedAsset = assetLoader.LoadAsset(stream, file.AssetConfig.Config, resourceName, subassetName, this);
|
||||||
|
|
||||||
|
delete stream;
|
||||||
|
delete filePath;
|
||||||
|
delete resourceName;
|
||||||
|
delete subassetName;
|
||||||
|
|
||||||
|
using (_finishedEntriesLock.Enter())
|
||||||
|
{
|
||||||
|
_finishedEntries.Add((placeholder, loadedAsset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the asset loader that has to be used for the given file.
|
||||||
|
IAssetLoader GetAssetLoader(AssetFile file)
|
||||||
|
{
|
||||||
IAssetLoader assetLoader = null;
|
IAssetLoader assetLoader = null;
|
||||||
|
|
||||||
String loaderTypeName = scope .(128);
|
String loaderTypeName = scope .(128);
|
||||||
@@ -345,24 +446,67 @@ class EditorContentManager : IContentManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return assetLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SaveAssetError
|
||||||
|
{
|
||||||
|
case Unknown;
|
||||||
|
case Unsavable;
|
||||||
|
case PathNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Saves the asset.
|
||||||
|
public Result<void, SaveAssetError> SaveAsset(Asset asset)
|
||||||
|
{
|
||||||
|
if (asset == null)
|
||||||
|
return .Err(.Unknown);
|
||||||
|
|
||||||
|
if (asset.Identifier.IsWhiteSpace)
|
||||||
|
return .Err(.Unsavable);
|
||||||
|
|
||||||
|
GetResourceAndSubassetName(asset.Identifier, let resourceName, let subassetName);
|
||||||
|
|
||||||
|
if (subassetName != null)
|
||||||
|
{
|
||||||
|
// TODO: should this ever be allowed? Couldn't we just save the entire asset?
|
||||||
|
// Would this ever be necessary?
|
||||||
|
Runtime.NotImplemented("Saving subassets is not currently allowed");
|
||||||
|
}
|
||||||
|
|
||||||
|
String filePath = scope String();
|
||||||
|
GetResourceFilePath(resourceName, filePath);
|
||||||
|
|
||||||
|
Result<TreeNode<AssetNode>> assetNode = AssetHierarchy.GetNodeFromPath(filePath);
|
||||||
|
|
||||||
|
if (assetNode case .Err)
|
||||||
|
return .Err(.PathNotFound);
|
||||||
|
|
||||||
|
AssetFile file = assetNode.Get()->AssetFile;
|
||||||
|
|
||||||
|
IAssetLoader assetLoader = GetAssetLoader(file);
|
||||||
|
|
||||||
IAssetSaver assetSaver = assetLoader as IAssetSaver;
|
IAssetSaver assetSaver = assetLoader as IAssetSaver;
|
||||||
|
|
||||||
if (assetSaver == null)
|
if (assetSaver == null)
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error("The asset loader can't save!");
|
Log.EngineLogger.Error("The asset loader can't save!");
|
||||||
return .Err;
|
return .Err(.Unsavable);
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream stream = OpenStream(filePath, false, true);
|
Stream stream = OpenStream(filePath, false);
|
||||||
|
|
||||||
assetSaver.EditorSaveAsset(stream, asset, file.AssetConfig.Config, resourceName, subassetName, this);
|
assetSaver.EditorSaveAsset(stream, asset, file.AssetConfig.Config, resourceName, subassetName, this);
|
||||||
|
|
||||||
|
// Trim off the end of the file.
|
||||||
|
stream.SetLength(stream.Position);
|
||||||
|
|
||||||
delete stream;
|
delete stream;
|
||||||
|
|
||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Stream OpenStream(StringView assetIdentifier, bool openOnly, bool truncate = false)
|
private Stream OpenStream(StringView assetIdentifier, bool openOnly)
|
||||||
{
|
{
|
||||||
var assetIdentifier;
|
var assetIdentifier;
|
||||||
|
|
||||||
@@ -378,9 +522,6 @@ class EditorContentManager : IContentManager
|
|||||||
|
|
||||||
FileMode fileMode = openOnly ? FileMode.Open : FileMode.OpenOrCreate;
|
FileMode fileMode = openOnly ? FileMode.Open : FileMode.OpenOrCreate;
|
||||||
|
|
||||||
if (truncate)
|
|
||||||
fileMode |= .Truncate;
|
|
||||||
|
|
||||||
var result = fs.Open(assetIdentifier, fileMode, openOnly ? .Read : .ReadWrite, .ReadWrite);
|
var result = fs.Open(assetIdentifier, fileMode, openOnly ? .Read : .ReadWrite, .ReadWrite);
|
||||||
|
|
||||||
if (result case .Err)
|
if (result case .Err)
|
||||||
@@ -413,37 +554,86 @@ class EditorContentManager : IContentManager
|
|||||||
return fs;*/
|
return fs;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ManageAsset(Asset asset)
|
public AssetHandle ManageAsset(Asset asset)
|
||||||
{
|
{
|
||||||
_loadedAssets.Add(asset.Identifier, asset);
|
Log.EngineLogger.AssertDebug(asset.Handle == .Invalid, "Asset is already managed.");
|
||||||
|
Log.EngineLogger.AssertDebug(asset.ContentManager == null, "Asset is already managed.");
|
||||||
|
|
||||||
|
AssetHandle handle = .();
|
||||||
|
|
||||||
|
// Generate until we find a unique key (shouldn't happen too often)
|
||||||
|
while (handle.IsInvalid || _handleToAsset.ContainsKey(handle))
|
||||||
|
{
|
||||||
|
handle = .();
|
||||||
|
Log.EngineLogger.Trace("Handle was invalid or already taken.");
|
||||||
|
// TODO: perhaps test how often this happens.
|
||||||
|
// If this happens too often we could use a different random generator
|
||||||
|
}
|
||||||
|
|
||||||
|
//_handles.Add(asset.Identifier, handle);
|
||||||
|
_handleToAsset.Add(handle, asset);
|
||||||
|
|
||||||
asset.[Friend]_contentManager = this;
|
asset.[Friend]_contentManager = this;
|
||||||
|
asset.[Friend]_handle = handle;
|
||||||
|
asset.AddRef();
|
||||||
|
|
||||||
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UnmanageAsset(Asset asset)
|
private void SwapAsset(Asset oldAsset, Asset newAsset)
|
||||||
{
|
{
|
||||||
_loadedAssets.Remove(asset.Identifier);
|
newAsset.Identifier = oldAsset.Identifier;
|
||||||
|
newAsset._contentManager = this;
|
||||||
|
newAsset._handle = oldAsset.Handle;
|
||||||
|
|
||||||
|
_handleToAsset[oldAsset.Handle] = newAsset;
|
||||||
|
|
||||||
|
if (_identiferToHandle.ContainsKey(oldAsset.Identifier))
|
||||||
|
{
|
||||||
|
_identiferToHandle.Remove(oldAsset.Identifier);
|
||||||
|
_identiferToHandle.Add(newAsset.Identifier, newAsset.Handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
newAsset.AddRef();
|
||||||
|
oldAsset.ReleaseRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnmanageAsset(AssetHandle handle)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.AssertDebug(_handleToAsset.ContainsKey(handle), "Handle doesn't correspond to an asset.");
|
||||||
|
|
||||||
|
Asset asset = _handleToAsset[handle];
|
||||||
|
|
||||||
|
if (_identiferToHandle.ContainsKey(asset.Identifier))
|
||||||
|
_identiferToHandle.Remove(asset.Identifier);
|
||||||
|
|
||||||
|
_handleToAsset.Remove(handle);
|
||||||
asset.[Friend]_contentManager = null;
|
asset.[Friend]_contentManager = null;
|
||||||
|
|
||||||
|
asset.ReleaseRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This will unregister all assets from this content manager.
|
/// This will unregister all assets from this content manager.
|
||||||
/// Note: This will not release any assets.
|
/// Note: This will not release any assets.
|
||||||
private void UnmanageAllAssets()
|
private void UnmanageAllAssets()
|
||||||
{
|
{
|
||||||
for (let (_, asset) in _loadedAssets)
|
for (let (handle, _) in _handleToAsset)
|
||||||
{
|
{
|
||||||
UnmanageAsset(asset);
|
UnmanageAsset(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateAssetIdentifier(Asset asset, StringView oldIdentifier, StringView newIdentifier)
|
public void AssetMoved(Asset asset, StringView oldIdentifier, StringView newIdentifier)
|
||||||
{
|
{
|
||||||
|
Runtime.NotImplemented();
|
||||||
|
|
||||||
if (oldIdentifier == newIdentifier)
|
if (oldIdentifier == newIdentifier)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Log.EngineLogger.Assert(_loadedAssets.ContainsKey(newIdentifier), "An asset with the same identifier is already managed by this content manager.");
|
Log.EngineLogger.Assert(_identiferToHandle.ContainsKey(newIdentifier), "An asset with the same identifier is already managed by this content manager.");
|
||||||
|
|
||||||
// Since all we do in order to track assets is add them to a dictionary we can simply unmanage and manage it again.
|
// Since all we do in order to track assets is add them to a dictionary we can simply unmanage and manage it again.
|
||||||
UnmanageAsset(asset);
|
//UnmanageAsset(asset);
|
||||||
ManageAsset(asset);
|
//ManageAsset(asset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,12 +2,13 @@ using System;
|
|||||||
using GlitchyEngine.Renderer;
|
using GlitchyEngine.Renderer;
|
||||||
using GlitchyEngine.Math;
|
using GlitchyEngine.Math;
|
||||||
using GlitchyEngine;
|
using GlitchyEngine;
|
||||||
|
using GlitchyEngine.Content;
|
||||||
|
|
||||||
namespace GlitchyEditor
|
namespace GlitchyEditor
|
||||||
{
|
{
|
||||||
class EditorIcons : RefCounted
|
class EditorIcons : RefCounted
|
||||||
{
|
{
|
||||||
Texture2D _texture ~ _.ReleaseRef();
|
AssetHandle<Texture2D> _texture;
|
||||||
|
|
||||||
public SubTexture2D DirectionalLight ~ _.ReleaseRef();
|
public SubTexture2D DirectionalLight ~ _.ReleaseRef();
|
||||||
public SubTexture2D Camera ~ _.ReleaseRef();
|
public SubTexture2D Camera ~ _.ReleaseRef();
|
||||||
@@ -15,16 +16,18 @@ namespace GlitchyEditor
|
|||||||
public SubTexture2D File ~ _.ReleaseRef();
|
public SubTexture2D File ~ _.ReleaseRef();
|
||||||
public SubTexture2D Play ~ _.ReleaseRef();
|
public SubTexture2D Play ~ _.ReleaseRef();
|
||||||
public SubTexture2D Stop ~ _.ReleaseRef();
|
public SubTexture2D Stop ~ _.ReleaseRef();
|
||||||
|
public SubTexture2D Simulate ~ _.ReleaseRef();
|
||||||
|
public SubTexture2D Pause ~ _.ReleaseRef();
|
||||||
|
|
||||||
public SamplerState SamplerState
|
public SamplerState SamplerState
|
||||||
{
|
{
|
||||||
get => _texture.SamplerState;
|
get => _texture.Get().SamplerState;
|
||||||
set => _texture.SamplerState = value;
|
set => _texture.Get().SamplerState = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public this(String texturePath, Vector2 iconSize)
|
public this(String texturePath, Vector2 iconSize)
|
||||||
{
|
{
|
||||||
_texture = Content.LoadAsset<Texture2D>(texturePath);//new Texture2D(texturePath);
|
_texture = Content.LoadAsset(texturePath, null, true);
|
||||||
|
|
||||||
Vector2 pen = .();
|
Vector2 pen = .();
|
||||||
|
|
||||||
@@ -34,6 +37,8 @@ namespace GlitchyEditor
|
|||||||
File = GetNextGridTexture(ref pen, iconSize);
|
File = GetNextGridTexture(ref pen, iconSize);
|
||||||
Play = GetNextGridTexture(ref pen, iconSize);
|
Play = GetNextGridTexture(ref pen, iconSize);
|
||||||
Stop = GetNextGridTexture(ref pen, iconSize);
|
Stop = GetNextGridTexture(ref pen, iconSize);
|
||||||
|
Simulate = GetNextGridTexture(ref pen, iconSize);
|
||||||
|
Pause = GetNextGridTexture(ref pen, iconSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SubTexture2D GetNextGridTexture(ref Vector2 pen, Vector2 iconSize)
|
private SubTexture2D GetNextGridTexture(ref Vector2 pen, Vector2 iconSize)
|
||||||
|
|||||||
+324
-260
@@ -18,67 +18,84 @@ namespace GlitchyEditor
|
|||||||
{
|
{
|
||||||
class EditorLayer : Layer
|
class EditorLayer : Layer
|
||||||
{
|
{
|
||||||
|
enum SceneState
|
||||||
|
{
|
||||||
|
Edit,
|
||||||
|
Play,
|
||||||
|
Simulate
|
||||||
|
}
|
||||||
|
|
||||||
RasterizerState _rasterizerState ~ _?.ReleaseRef();
|
RasterizerState _rasterizerState ~ _?.ReleaseRef();
|
||||||
RasterizerState _rasterizerStateClockWise ~ _?.ReleaseRef();
|
RasterizerState _rasterizerStateClockWise ~ _?.ReleaseRef();
|
||||||
|
|
||||||
|
// TODO: we shouldn't hold a reference to the context
|
||||||
GraphicsContext _context ~ _.ReleaseRef();
|
GraphicsContext _context ~ _.ReleaseRef();
|
||||||
|
|
||||||
BlendState _alphaBlendState ~ _.ReleaseRef();
|
BlendState _alphaBlendState ~ _.ReleaseRef();
|
||||||
BlendState _opaqueBlendState ~ _.ReleaseRef();
|
BlendState _opaqueBlendState ~ _.ReleaseRef();
|
||||||
DepthStencilState _depthStencilState ~ _.ReleaseRef();
|
DepthStencilState _depthStencilState ~ _.ReleaseRef();
|
||||||
|
|
||||||
Scene _scene ~ delete _;
|
|
||||||
String _sceneFilePath = new String() ~ delete _;
|
|
||||||
|
|
||||||
public String SceneFilePath
|
/// Reference to the scene that is currently being played and worked on.
|
||||||
|
Scene _activeScene ~ _?.ReleaseRef();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Referece to the editor scene.
|
||||||
|
* We hold a reference to the editor scene because we need it in order
|
||||||
|
* to restore the original state once we stop the game/simulation.
|
||||||
|
* Before starting the simulation the editor scene will be copied and
|
||||||
|
* the reference in _activeScene will be replaced with the new scene.
|
||||||
|
*/
|
||||||
|
Scene _editorScene ~ _?.ReleaseRef();
|
||||||
|
|
||||||
|
SceneRenderer _gameSceneRenderer ~ delete _;
|
||||||
|
SceneRenderer _editorSceneRenderer ~ delete _;
|
||||||
|
|
||||||
|
/// Path of the current scene.
|
||||||
|
append String _sceneFilePath = .();
|
||||||
|
|
||||||
|
Editor _editor ~ delete _;
|
||||||
|
|
||||||
|
RenderTargetGroup _cameraTarget ~ _.ReleaseRef();
|
||||||
|
RenderTargetGroup _editorViewportTarget ~ _.ReleaseRef();
|
||||||
|
RenderTargetGroup _gameViewportTarget ~ _.ReleaseRef();
|
||||||
|
|
||||||
|
SettingsWindow _settingsWindow = new .() ~ delete _;
|
||||||
|
|
||||||
|
EditorCamera _camera ~ _.Dispose();
|
||||||
|
|
||||||
|
EditorIcons _editorIcons ~ _.ReleaseRef();
|
||||||
|
|
||||||
|
EditorContentManager _contentManager;
|
||||||
|
|
||||||
|
SceneState _sceneState = .Edit;
|
||||||
|
bool _isPaused = false;
|
||||||
|
|
||||||
|
/// Gets or sets the path of the current scene.
|
||||||
|
public StringView SceneFilePath
|
||||||
{
|
{
|
||||||
get => _sceneFilePath;
|
get => _sceneFilePath;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_sceneFilePath.Clear();
|
_sceneFilePath.Clear();
|
||||||
|
|
||||||
if (value != null)
|
if (!value.IsWhiteSpace)
|
||||||
_sceneFilePath.Append(value);
|
_sceneFilePath.Append(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Editor _editor ~ delete _;
|
public this(EditorContentManager contentManager) : base("Editor")
|
||||||
|
|
||||||
RenderTargetGroup _cameraTarget ~ _.ReleaseRef();
|
|
||||||
RenderTargetGroup _viewportTarget ~ _.ReleaseRef();
|
|
||||||
|
|
||||||
SettingsWindow _settingsWindow = new .() ~ delete _;
|
|
||||||
|
|
||||||
EditorCamera _camera ~ _.Dispose();
|
|
||||||
|
|
||||||
/*Texture2D _editorIcons ~ _.ReleaseRef();
|
|
||||||
SubTexture2D _iconDirectionalLight ~ _.ReleaseRef();
|
|
||||||
SubTexture2D _iconCamera ~ _.ReleaseRef();*/
|
|
||||||
|
|
||||||
EditorIcons _editorIcons ~ _.ReleaseRef();
|
|
||||||
|
|
||||||
EditorContentManager _contentManager;
|
|
||||||
|
|
||||||
enum SceneState
|
|
||||||
{
|
|
||||||
Edit,
|
|
||||||
Play,
|
|
||||||
// Pause,
|
|
||||||
// Simulate
|
|
||||||
}
|
|
||||||
|
|
||||||
SceneState _sceneState = .Edit;
|
|
||||||
|
|
||||||
public this(EditorContentManager contentManager) : base("Example")
|
|
||||||
{
|
{
|
||||||
Application.Get().Window.IsVSync = false;
|
Application.Get().Window.IsVSync = false;
|
||||||
|
|
||||||
//InitContentManager();
|
|
||||||
_contentManager = contentManager;
|
_contentManager = contentManager;
|
||||||
|
|
||||||
InitGraphics();
|
InitGraphics();
|
||||||
|
|
||||||
_scene = new Scene();
|
_editorScene = new Scene();
|
||||||
|
SetReference!(_activeScene, _editorScene);
|
||||||
|
|
||||||
|
_gameSceneRenderer = new SceneRenderer();
|
||||||
|
_editorSceneRenderer = new SceneRenderer();
|
||||||
|
|
||||||
_camera = EditorCamera(Vector3(3.5f, 1.25f, 2.75f), Quaternion.FromEulerAngles(MathHelper.ToRadians(40), MathHelper.ToRadians(25), 0), MathHelper.ToRadians(75), 0.1f, 1);
|
_camera = EditorCamera(Vector3(3.5f, 1.25f, 2.75f), Quaternion.FromEulerAngles(MathHelper.ToRadians(40), MathHelper.ToRadians(25), 0), MathHelper.ToRadians(75), 0.1f, 1);
|
||||||
_camera.RenderTarget = _cameraTarget;
|
_camera.RenderTarget = _cameraTarget;
|
||||||
@@ -88,31 +105,6 @@ namespace GlitchyEditor
|
|||||||
NewScene();
|
NewScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*private void InitContentManager()
|
|
||||||
{
|
|
||||||
_contentManager = new EditorContentManager();
|
|
||||||
_contentManager.RegisterAssetLoader<EditorTextureAssetLoader>();
|
|
||||||
_contentManager.SetAsDefaultAssetLoader<EditorTextureAssetLoader>(".png", ".dds");
|
|
||||||
_contentManager.SetAssetPropertiesEditor<EditorTextureAssetLoader>(=> TextureAssetPropertiesEditor.Factory);
|
|
||||||
|
|
||||||
_contentManager.RegisterAssetLoader<ModelAssetLoader>();
|
|
||||||
_contentManager.SetAsDefaultAssetLoader<ModelAssetLoader>(".glb", ".gltf");
|
|
||||||
_contentManager.SetAssetPropertiesEditor<ModelAssetLoader>(=> ModelAssetPropertiesEditor.Factory);
|
|
||||||
|
|
||||||
_contentManager.RegisterAssetLoader<MaterialAssetLoader>();
|
|
||||||
_contentManager.SetAsDefaultAssetLoader<MaterialAssetLoader>(".mat");
|
|
||||||
_contentManager.SetAssetPropertiesEditor<MaterialAssetLoader>(=> MaterialAssetPropertiesEditor.Factory);
|
|
||||||
|
|
||||||
_contentManager.RegisterAssetLoader<EffectAssetLoader>();
|
|
||||||
_contentManager.SetAsDefaultAssetLoader<EffectAssetLoader>(".hlsl");
|
|
||||||
_contentManager.SetAssetPropertiesEditor<EffectAssetLoader>(=> EffectAssetPropertiesEditor.Factory);
|
|
||||||
|
|
||||||
_contentManager.SetContentDirectory("./content");
|
|
||||||
|
|
||||||
// Todo: Sketchy...
|
|
||||||
Application.Get().[Friend]_contentManager = _contentManager;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
private void InitGraphics()
|
private void InitGraphics()
|
||||||
{
|
{
|
||||||
_context = Application.Get().Window.Context..AddRef();
|
_context = Application.Get().Window.Context..AddRef();
|
||||||
@@ -141,7 +133,15 @@ namespace GlitchyEditor
|
|||||||
DepthTargetDescription = .(.D24_UNorm_S8_UInt)
|
DepthTargetDescription = .(.D24_UNorm_S8_UInt)
|
||||||
});
|
});
|
||||||
|
|
||||||
_viewportTarget = new RenderTargetGroup(.()
|
_editorViewportTarget = new RenderTargetGroup(.()
|
||||||
|
{
|
||||||
|
Width = 100,
|
||||||
|
Height = 100,
|
||||||
|
ColorTargetDescriptions = TargetDescription[](
|
||||||
|
.(.R8G8B8A8_UNorm))
|
||||||
|
});
|
||||||
|
|
||||||
|
_gameViewportTarget = new RenderTargetGroup(.()
|
||||||
{
|
{
|
||||||
Width = 100,
|
Width = 100,
|
||||||
Height = 100,
|
Height = 100,
|
||||||
@@ -154,18 +154,16 @@ namespace GlitchyEditor
|
|||||||
|
|
||||||
ContentBrowserWindow.s_FolderTexture = _editorIcons.Folder;
|
ContentBrowserWindow.s_FolderTexture = _editorIcons.Folder;
|
||||||
ContentBrowserWindow.s_FileTexture = _editorIcons.File;
|
ContentBrowserWindow.s_FileTexture = _editorIcons.File;
|
||||||
|
|
||||||
/*_editorIcons = new Texture2D("Textures/EditorIcons.dds");
|
|
||||||
_editorIcons.SamplerState = SamplerStateManager.AnisotropicClamp;
|
|
||||||
_iconDirectionalLight = .CreateFromGrid(_editorIcons, .(0, 0), .(64, 64));
|
|
||||||
_iconCamera = .CreateFromGrid(_editorIcons, .(1, 0), .(64, 64));*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitEditor()
|
private void InitEditor()
|
||||||
{
|
{
|
||||||
_editor = new Editor(_scene, _contentManager);
|
_editor = new Editor(_editorScene, _contentManager);
|
||||||
_editor.SceneViewportWindow.ViewportSizeChanged.Add(new (s, e) => ViewportSizeChanged(s, e));
|
_editor.SceneViewportWindow.ViewportSizeChanged.Add(new (s, e) => EditorViewportSizeChanged(s, e));
|
||||||
|
_editor.GameViewportWindow.ViewportSizeChanged.Add(new (s, e) => GameViewportSizeChanged(s, e));
|
||||||
_editor.CurrentCamera = &_camera;
|
_editor.CurrentCamera = &_camera;
|
||||||
|
_editor.GameSceneRenderer = _gameSceneRenderer;
|
||||||
|
_editor.EditorSceneRenderer = _editorSceneRenderer;
|
||||||
|
|
||||||
_editor.RequestOpenScene.Add(new (s, fileName) => {
|
_editor.RequestOpenScene.Add(new (s, fileName) => {
|
||||||
LoadSceneFile(fileName);
|
LoadSceneFile(fileName);
|
||||||
@@ -174,20 +172,54 @@ namespace GlitchyEditor
|
|||||||
|
|
||||||
public override void Update(GameTime gameTime)
|
public override void Update(GameTime gameTime)
|
||||||
{
|
{
|
||||||
_camera.Update(gameTime);
|
Debug.Profiler.ProfileFunction!();
|
||||||
|
|
||||||
|
_editor.CurrentScene = _activeScene;
|
||||||
|
|
||||||
|
Scene.UpdateMode updateMode;
|
||||||
|
|
||||||
|
switch (_sceneState)
|
||||||
|
{
|
||||||
|
case .Edit:
|
||||||
|
updateMode = .Editor;
|
||||||
|
case .Play:
|
||||||
|
updateMode = .Runtime;
|
||||||
|
case .Simulate:
|
||||||
|
updateMode = .Physics;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sceneState != .Edit && _isPaused)
|
||||||
|
updateMode = .None;
|
||||||
|
|
||||||
|
|
||||||
|
_activeScene.Update(gameTime, updateMode);
|
||||||
|
|
||||||
// Clear the swapchain-buffer
|
// Clear the swapchain-buffer
|
||||||
RenderCommand.Clear(null, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
|
RenderCommand.Clear(null, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
|
||||||
|
|
||||||
|
RenderCommand.SetBlendState(_alphaBlendState);
|
||||||
|
RenderCommand.SetDepthStencilState(_depthStencilState);
|
||||||
|
|
||||||
|
if (_editor.SceneViewportWindow.Visible)
|
||||||
|
{
|
||||||
|
_camera.Update(gameTime);
|
||||||
|
|
||||||
RenderCommand.Clear(_viewportTarget, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
|
_editorSceneRenderer.Scene = _activeScene;
|
||||||
|
|
||||||
|
RenderCommand.Clear(_editorViewportTarget, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
|
||||||
|
_editorSceneRenderer.RenderEditor(gameTime, _camera, _editorViewportTarget, scope => DebugDraw3D, scope => DebugDraw2D);
|
||||||
|
}
|
||||||
|
|
||||||
RenderCommand.SetBlendState(_alphaBlendState);
|
RenderCommand.SetBlendState(_alphaBlendState);
|
||||||
RenderCommand.SetDepthStencilState(_depthStencilState);
|
RenderCommand.SetDepthStencilState(_depthStencilState);
|
||||||
|
|
||||||
if (_sceneState == .Edit)
|
if (_editor.GameViewportWindow.Visible)
|
||||||
_scene.UpdateEditor(gameTime, _camera, _viewportTarget, scope => DebugDraw3D, scope => DebugDraw2D);
|
{
|
||||||
else if (_sceneState == .Play)
|
_gameSceneRenderer.Scene = _activeScene;
|
||||||
_scene.UpdateRuntime(gameTime, _viewportTarget);
|
|
||||||
|
RenderCommand.Clear(_gameViewportTarget, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
|
||||||
|
_gameSceneRenderer.RenderRuntime(gameTime, _gameViewportTarget);
|
||||||
|
}
|
||||||
|
|
||||||
RenderCommand.UnbindRenderTargets();
|
RenderCommand.UnbindRenderTargets();
|
||||||
RenderCommand.SetRenderTarget(null, 0, true);
|
RenderCommand.SetRenderTarget(null, 0, true);
|
||||||
@@ -226,11 +258,11 @@ namespace GlitchyEditor
|
|||||||
return Math.Clamp(1.5f - Vector3.Distance(_editor.CurrentCamera.Position, pos) / 50, 0, 1);
|
return Math.Clamp(1.5f - Vector3.Distance(_editor.CurrentCamera.Position, pos) / 50, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var (entity, transform, camera) in _scene.[Friend]_ecsWorld.Enumerate<TransformComponent, CameraComponent>())
|
for (var (entity, transform, camera) in _activeScene.GetEntities<TransformComponent, CameraComponent>())
|
||||||
{
|
{
|
||||||
if (_editor.EntityHierarchyWindow.SelectedEntities.Contains(.(entity, _scene)))
|
if (_editor.EntityHierarchyWindow.SelectedEntities.Contains(.(entity, _activeScene)))
|
||||||
{
|
{
|
||||||
DebugRenderer.DrawViewFrustum(transform.WorldTransform, camera.Camera.Projection, _camera.Projection * _camera.View, .White);
|
DebugRenderer.DrawViewFrustum(transform.WorldTransform, camera.Camera.Projection, .White);
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix world = Billboard(transform.WorldTransform);
|
Matrix world = Billboard(transform.WorldTransform);
|
||||||
@@ -240,9 +272,9 @@ namespace GlitchyEditor
|
|||||||
//Renderer2D.DrawQuad(world, _iconCamera, .White, .(0, 0, 1, 1), entity.Index);
|
//Renderer2D.DrawQuad(world, _iconCamera, .White, .(0, 0, 1, 1), entity.Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var (entity, transform, light) in _scene.[Friend]_ecsWorld.Enumerate<TransformComponent, LightComponent>())
|
for (var (entity, transform, light) in _activeScene.GetEntities<TransformComponent, LightComponent>())
|
||||||
{
|
{
|
||||||
if (_editor.EntityHierarchyWindow.SelectedEntities.Contains(.(entity, _scene)))
|
if (_editor.EntityHierarchyWindow.SelectedEntities.Contains(.(entity, _activeScene)))
|
||||||
{
|
{
|
||||||
Renderer.DrawRay(.Zero, .(0, 0, 20), ColorRGBA(light.SceneLight.Color, 1.0f), transform.WorldTransform);
|
Renderer.DrawRay(.Zero, .(0, 0, 20), ColorRGBA(light.SceneLight.Color, 1.0f), transform.WorldTransform);
|
||||||
|
|
||||||
@@ -258,7 +290,16 @@ namespace GlitchyEditor
|
|||||||
|
|
||||||
float alpha = CalculateAlpha(transform.WorldTransform.Translation);
|
float alpha = CalculateAlpha(transform.WorldTransform.Translation);
|
||||||
Renderer2D.DrawQuad(world, _editorIcons.DirectionalLight, ColorRGBA(light.SceneLight.Color.R * alpha, light.SceneLight.Color.G * alpha, light.SceneLight.Color.B * alpha, alpha), .(0, 0, 1, 1), entity.Index);
|
Renderer2D.DrawQuad(world, _editorIcons.DirectionalLight, ColorRGBA(light.SceneLight.Color.R * alpha, light.SceneLight.Color.G * alpha, light.SceneLight.Color.B * alpha, alpha), .(0, 0, 1, 1), entity.Index);
|
||||||
//Renderer2D.DrawQuad(world, _iconDirectionalLight, ColorRGBA(light.SceneLight.Color, alpha), .(0, 0, 1, 1), entity.Index);
|
}
|
||||||
|
|
||||||
|
for (var (entity, transform, collider) in _activeScene.GetEntities<TransformComponent, BoxCollider2DComponent>())
|
||||||
|
{
|
||||||
|
Renderer2D.DrawRect(transform.WorldTransform * Matrix.Translation(collider.Offset.X, collider.Offset.Y, 0) * Matrix.Scaling(collider.Size.X * 2, collider.Size.Y * 2, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var (entity, transform, collider) in _activeScene.GetEntities<TransformComponent, CircleCollider2DComponent>())
|
||||||
|
{
|
||||||
|
Renderer2D.DrawCircle(transform.WorldTransform * Matrix.Translation(collider.Offset.X, collider.Offset.Y, 0) * Matrix.Scaling(collider.Radius * 2), (Texture2D)null, ColorRGBA(0f, 1f, 0f), 0.01f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,7 +328,8 @@ namespace GlitchyEditor
|
|||||||
|
|
||||||
DrawMainMenuBar();
|
DrawMainMenuBar();
|
||||||
|
|
||||||
_editor.SceneViewportWindow.RenderTarget = _viewportTarget;
|
_editor.SceneViewportWindow.RenderTarget = _editorViewportTarget;
|
||||||
|
_editor.GameViewportWindow.RenderTarget = _gameViewportTarget;
|
||||||
|
|
||||||
_editor.Update();
|
_editor.Update();
|
||||||
|
|
||||||
@@ -317,22 +359,87 @@ namespace GlitchyEditor
|
|||||||
|
|
||||||
ImGui.Begin("##toolbar", null, .NoDecoration | .NoScrollbar | .NoScrollWithMouse);
|
ImGui.Begin("##toolbar", null, .NoDecoration | .NoScrollbar | .NoScrollWithMouse);
|
||||||
|
|
||||||
SubTexture2D icon = _sceneState == .Edit ? _editorIcons.Play : _editorIcons.Stop;
|
float padding = 2.0f;
|
||||||
|
|
||||||
float size = ImGui.GetWindowHeight() - 4.0f;
|
float size = ImGui.GetWindowHeight() - 2 * padding;
|
||||||
|
|
||||||
ImGui.SameLine((ImGui.GetContentRegionMax().x / 2 - size / 2));
|
|
||||||
|
|
||||||
if (ImGui.ImageButton(icon, .(size, size), .Zero, .Ones, 0))
|
float centerX = ImGui.GetContentRegionMax().x / 2;
|
||||||
|
|
||||||
|
|
||||||
|
if (_sceneState == .Edit)
|
||||||
|
EditorButtons:
|
||||||
{
|
{
|
||||||
if (_sceneState == .Edit)
|
// Display the buttons for edit state
|
||||||
{
|
|
||||||
|
float totalWidth = size * 3 + padding * 4;
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.SetCursorPosX(centerX - totalWidth / 2);
|
||||||
|
|
||||||
|
if (ImGui.ImageButton(_editorIcons.Play, .(size, size), .Zero, .Ones, 0))
|
||||||
OnScenePlay();
|
OnScenePlay();
|
||||||
}
|
|
||||||
else if (_sceneState == .Play)
|
ImGui.AttachTooltip("Play the game.");
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
|
||||||
|
ImGui.PushID(1);
|
||||||
|
|
||||||
|
if (ImGui.ImageButton(_editorIcons.Simulate, .(size, size), .Zero, .Ones, 0))
|
||||||
|
OnSceneSimulate();
|
||||||
|
|
||||||
|
ImGui.PopID();
|
||||||
|
|
||||||
|
ImGui.AttachTooltip("Enter simulation mode.\nThis only runs the physics engine.");
|
||||||
|
|
||||||
|
if (_isPaused)
|
||||||
{
|
{
|
||||||
OnSceneStop();
|
ImGui.PushStyleColor(.Button, *ImGui.GetStyleColorVec4(.ButtonActive));
|
||||||
|
|
||||||
|
defer:EditorButtons { ImGui.PopStyleColor(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui.PushID(2);
|
||||||
|
|
||||||
|
//ImGui.SameLine(penX += size + 2 * padding);
|
||||||
|
ImGui.SameLine();
|
||||||
|
|
||||||
|
if (ImGui.ImageButton(_editorIcons.Pause, .(size, size), .Zero, .Ones, 0))
|
||||||
|
_isPaused = !_isPaused;
|
||||||
|
|
||||||
|
ImGui.PopID();
|
||||||
|
|
||||||
|
ImGui.AttachTooltip("If enabled the game or simulation will be started in paused state.");
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Display the buttons for play/simulation state
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.SetCursorPosX(centerX - size - padding);
|
||||||
|
|
||||||
|
SubTexture2D pauseButtonIcon = _isPaused ? _editorIcons.Play : _editorIcons.Pause;
|
||||||
|
|
||||||
|
if (ImGui.ImageButton(pauseButtonIcon, .(size, size), .Zero, .Ones, 0))
|
||||||
|
{
|
||||||
|
if (_isPaused)
|
||||||
|
OnSceneResume();
|
||||||
|
else
|
||||||
|
OnScenePause();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.AttachTooltip(_isPaused ? "Resume" : "Pause");
|
||||||
|
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.PushID(1);
|
||||||
|
|
||||||
|
if (ImGui.ImageButton(_editorIcons.Stop, .(size, size), .Zero, .Ones, 0))
|
||||||
|
OnSceneStop();
|
||||||
|
|
||||||
|
ImGui.PopID();
|
||||||
|
|
||||||
|
ImGui.AttachTooltip("Stop");
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.End();
|
ImGui.End();
|
||||||
@@ -343,194 +450,129 @@ namespace GlitchyEditor
|
|||||||
|
|
||||||
private void OnScenePlay()
|
private void OnScenePlay()
|
||||||
{
|
{
|
||||||
_sceneState = .Play;
|
|
||||||
_editor.SceneViewportWindow.EditorMode = false;
|
_editor.SceneViewportWindow.EditorMode = false;
|
||||||
|
_sceneState = .Play;
|
||||||
|
|
||||||
_scene.OnRuntimeStart();
|
using (Scene runtimeScene = new Scene())
|
||||||
|
{
|
||||||
|
_editorScene.CopyTo(runtimeScene);
|
||||||
|
|
||||||
|
runtimeScene.OnRuntimeStart();
|
||||||
|
|
||||||
|
SetReference!(_activeScene, runtimeScene);
|
||||||
|
}
|
||||||
|
|
||||||
|
_editor.CurrentScene = _activeScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSceneSimulate()
|
||||||
|
{
|
||||||
|
_editor.SceneViewportWindow.EditorMode = false;
|
||||||
|
_sceneState = .Simulate;
|
||||||
|
|
||||||
|
using (Scene simulationScene = new Scene())
|
||||||
|
{
|
||||||
|
_editorScene.CopyTo(simulationScene);
|
||||||
|
|
||||||
|
simulationScene.OnSimulationStart();
|
||||||
|
|
||||||
|
SetReference!(_activeScene, simulationScene);
|
||||||
|
}
|
||||||
|
|
||||||
|
_editor.CurrentScene = _activeScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnScenePause()
|
||||||
|
{
|
||||||
|
_isPaused = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSceneResume()
|
||||||
|
{
|
||||||
|
_isPaused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSceneStop()
|
private void OnSceneStop()
|
||||||
{
|
{
|
||||||
_scene.OnRuntimeStop();
|
if (_sceneState == .Play)
|
||||||
|
_activeScene.OnRuntimeStop();
|
||||||
|
else
|
||||||
|
_activeScene.OnSimulationStop();
|
||||||
|
|
||||||
|
SetReference!(_activeScene, _editorScene);
|
||||||
|
|
||||||
_editor.SceneViewportWindow.EditorMode = true;
|
_editor.SceneViewportWindow.EditorMode = true;
|
||||||
_sceneState = .Edit;
|
_sceneState = .Edit;
|
||||||
}
|
|
||||||
|
|
||||||
// Just for testing
|
_editor.CurrentScene = _activeScene;
|
||||||
private void TestEntitiesWithModels()
|
|
||||||
{
|
|
||||||
/*{
|
|
||||||
var lightNtt = _scene.CreateEntity("My Sexy Sun 2");
|
|
||||||
let transform = lightNtt.GetComponent<TransformComponent>();
|
|
||||||
transform.Position = .(0, 0, 0);
|
|
||||||
transform.RotationEuler = .(MathHelper.ToRadians(70), MathHelper.ToRadians(-30), 0);
|
|
||||||
|
|
||||||
let light = lightNtt.AddComponent<LightComponent>();
|
|
||||||
light.SceneLight.Illuminance = 10.0f;
|
|
||||||
light.SceneLight.Color = .(1.0f, 0.95f, 0.8f);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var lightNtt = _scene.CreateEntity("My Sexy Sun 3");
|
|
||||||
let transform = lightNtt.GetComponent<TransformComponent>();
|
|
||||||
transform.Position = .(0, 0, 0);
|
|
||||||
transform.RotationEuler = .(MathHelper.ToRadians(20), MathHelper.ToRadians(-55), 0);
|
|
||||||
|
|
||||||
let light = lightNtt.AddComponent<LightComponent>();
|
|
||||||
light.SceneLight.Illuminance = 10.0f;
|
|
||||||
light.SceneLight.Color = .(1.0f, 0.95f, 0.8f);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
var cameraNtt = _scene.CreateEntity("My Camera");
|
|
||||||
let transform = cameraNtt.GetComponent<TransformComponent>();
|
|
||||||
transform.Position = .(5, 5, -5);
|
|
||||||
transform.RotationEuler = .(MathHelper.ToRadians(45), MathHelper.ToRadians(-45), 0);
|
|
||||||
|
|
||||||
let camera = cameraNtt.AddComponent<CameraComponent>();
|
|
||||||
camera.Primary = true;
|
|
||||||
camera.Camera.SetPerspective(MathHelper.ToRadians(45), 0.1f, 10.0f);
|
|
||||||
camera.RenderTarget = _cameraTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
var fxLib = Application.Get().EffectLibrary;
|
|
||||||
|
|
||||||
using (Effect myEffect = fxLib.Load("content/Shaders/myEffect.hlsl"))
|
|
||||||
/*using (Texture2D albedo = new Texture2D("Textures/White.png", true))
|
|
||||||
using (Texture2D normal = new Texture2D("Textures/White.png"))
|
|
||||||
using (Texture2D rough = new Texture2D("Textures/White.png"))
|
|
||||||
using (Texture2D metal = new Texture2D("Textures/White.png"))*/
|
|
||||||
using (Texture2D albedo = new Texture2D("Textures/TestMat/rustediron2_albedo.png", true))
|
|
||||||
using (Texture2D normal = new Texture2D("Textures/TestMat/rustediron2_normal.png"))
|
|
||||||
using (Texture2D rough = new Texture2D("Textures/TestMat/rustediron2_roughness.png"))
|
|
||||||
using (Texture2D metal = new Texture2D("Textures/TestMat/rustediron2_metallic.png"))
|
|
||||||
{
|
|
||||||
albedo.SamplerState = SamplerStateManager.AnisotropicWrap;
|
|
||||||
normal.SamplerState = SamplerStateManager.AnisotropicWrap;
|
|
||||||
rough.SamplerState = SamplerStateManager.AnisotropicWrap;
|
|
||||||
metal.SamplerState = SamplerStateManager.AnisotropicWrap;
|
|
||||||
|
|
||||||
List<AnimationClip> clips = scope .();
|
|
||||||
|
|
||||||
using (Material mat = new .(myEffect))
|
|
||||||
{
|
|
||||||
mat.SetTexture("AlbedoTexture", albedo);
|
|
||||||
mat.SetTexture("NormalTexture", normal);
|
|
||||||
mat.SetTexture("MetallicTexture", metal);
|
|
||||||
mat.SetTexture("RoughnessTexture", rough);
|
|
||||||
|
|
||||||
mat.SetVariable("AlbedoColor", ColorRGBA.White);
|
|
||||||
mat.SetVariable("NormalScaling", Vector2.One);
|
|
||||||
mat.SetVariable("MetallicFactor", 1.0f);
|
|
||||||
mat.SetVariable("RoughnessFactor", 1.0f);
|
|
||||||
|
|
||||||
// TODO: completely wrong!
|
|
||||||
EcsEntity e = ModelLoader.LoadModel("content/Models/sphere.glb", mat, _scene.[Friend]_ecsWorld, clips, "Sphere 1");
|
|
||||||
|
|
||||||
Entity entity = .(e, _scene);
|
|
||||||
var transform = entity.GetComponent<TransformComponent>();
|
|
||||||
transform.Position = .(5, 0, 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*using (Material mat = new .(myEffect))
|
|
||||||
{
|
|
||||||
mat.SetTexture("AlbedoTexture", albedo);
|
|
||||||
mat.SetTexture("NormalTexture", normal);
|
|
||||||
mat.SetTexture("MetallicTexture", metal);
|
|
||||||
mat.SetTexture("RoughnessTexture", rough);
|
|
||||||
//mat.SetVariable("BaseColor", Vector4(1, 1, 0, 1));
|
|
||||||
//mat.SetVariable("LightDir", Vector3(0, 1, 0).Normalized());
|
|
||||||
|
|
||||||
|
|
||||||
ModelLoader.LoadModel("content/Models/sphere.glb", myEffect, mat, _scene.[Friend]_ecsWorld, clips);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
ClearAndReleaseItems!(clips);
|
|
||||||
}
|
|
||||||
|
|
||||||
using (Effect myEffect = fxLib.Get("myEffect"))
|
|
||||||
using (Texture2D white = new Texture2D("Textures/White.png"))
|
|
||||||
using (Texture2D normal = new Texture2D("Textures/DefaultNormal.png"))
|
|
||||||
{
|
|
||||||
white.SamplerState = SamplerStateManager.PointClamp;
|
|
||||||
normal.SamplerState = SamplerStateManager.PointClamp;
|
|
||||||
|
|
||||||
List<AnimationClip> clips = scope .();
|
|
||||||
|
|
||||||
for (int x < 10)
|
|
||||||
for (int y < 10)
|
|
||||||
{
|
|
||||||
using (Material mat = new .(myEffect))
|
|
||||||
{
|
|
||||||
mat.SetTexture("AlbedoTexture", white);
|
|
||||||
mat.SetTexture("NormalTexture", normal);
|
|
||||||
mat.SetTexture("MetallicTexture", white);
|
|
||||||
mat.SetTexture("RoughnessTexture", white);
|
|
||||||
|
|
||||||
mat.SetVariable("AlbedoColor", Vector4(1, 0, 0, 1));
|
|
||||||
mat.SetVariable("NormalScaling", Vector2(1.0f));
|
|
||||||
mat.SetVariable("RoughnessFactor", (x + 1) / 10.0f);
|
|
||||||
mat.SetVariable("MetallicFactor", y / 9.0f);
|
|
||||||
|
|
||||||
EcsEntity e = ModelLoader.LoadModel("content/Models/sphere.glb", mat, _scene.[Friend]_ecsWorld, clips, scope $"Sphere {x} {y}");
|
_isPaused = false;
|
||||||
|
|
||||||
Entity entity = .(e, _scene);
|
/*
|
||||||
var transform = entity.GetComponent<TransformComponent>();
|
* Update the viewport size because if the game windows size changed in
|
||||||
transform.Position = .(x * 1.5f, y * 1.5f, 0);
|
* "Game"-mode the updated aspect-rations will reset once we go back
|
||||||
}
|
* into "Editor"-mode (because Game-Mode works on a copy of the scene).
|
||||||
}
|
*/
|
||||||
|
GameViewportSizeChanged(null, _editor.GameViewportWindow.ViewportSize);
|
||||||
ClearAndReleaseItems!(clips);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new scene.
|
/// Creates a new scene.
|
||||||
private void NewScene()
|
private void NewScene()
|
||||||
{
|
{
|
||||||
|
OnSceneStop();
|
||||||
|
|
||||||
SceneFilePath = null;
|
SceneFilePath = null;
|
||||||
|
|
||||||
delete _scene;
|
Scene newScene = new Scene();
|
||||||
_scene = new Scene();
|
|
||||||
_editor.CurrentScene = _scene;
|
|
||||||
var vpSize = _editor.SceneViewportWindow.ViewportSize;
|
|
||||||
_scene.OnViewportResize((.)vpSize.X, (.)vpSize.Y);
|
|
||||||
|
|
||||||
_camera.Position = .(-1.5f, 1.5f, -2.5f);
|
_camera.Position = .(-1.5f, 1.5f, -2.5f);
|
||||||
_camera.RotationEuler = .(MathHelper.ToRadians(25), MathHelper.ToRadians(35), 0);
|
_camera.RotationEuler = .(MathHelper.ToRadians(25), MathHelper.ToRadians(35), 0);
|
||||||
|
|
||||||
// Create default camera
|
// Create a default camera
|
||||||
/*{
|
|
||||||
let camEntity = _scene.CreateEntity("Camera");
|
|
||||||
let transform = camEntity.Transform;
|
|
||||||
transform.Position =
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*// Create the default light source
|
|
||||||
{
|
{
|
||||||
let lightNtt = _scene.CreateEntity("Light");
|
let cameraEntity = newScene.CreateEntity("Camera");
|
||||||
let transform = lightNtt.Transform;
|
let transform = cameraEntity.Transform;
|
||||||
transform.Position = .(0, 0, 0);
|
transform.Position = Vector3(0, 2, -5);
|
||||||
transform.RotationEuler = .(MathHelper.ToRadians(45), MathHelper.ToRadians(-100), 0);
|
transform.RotationEuler = Vector3(0, MathHelper.ToRadians(25), 0);
|
||||||
|
|
||||||
|
let camera = cameraEntity.AddComponent<CameraComponent>();
|
||||||
|
camera.Primary = true;
|
||||||
|
camera.Camera.ProjectionType = .InfinitePerspective;
|
||||||
|
camera.Camera.PerspectiveFovY = MathHelper.ToRadians(75);
|
||||||
|
camera.Camera.PerspectiveNearPlane = 0.1f;
|
||||||
|
}
|
||||||
|
|
||||||
let light = lightNtt.AddComponent<LightComponent>();
|
// Create a default light source
|
||||||
|
{
|
||||||
|
let lightEntity = newScene.CreateEntity("Light");
|
||||||
|
let transform = lightEntity.Transform;
|
||||||
|
transform.Position = .(-3, 4, -1.5f);
|
||||||
|
transform.RotationEuler = .(MathHelper.ToRadians(20), MathHelper.ToRadians(75), MathHelper.ToRadians(20));
|
||||||
|
|
||||||
|
let light = lightEntity.AddComponent<LightComponent>();
|
||||||
light.SceneLight.Illuminance = 10.0f;
|
light.SceneLight.Illuminance = 10.0f;
|
||||||
light.SceneLight.Color = .(1.0f, 0.95f, 0.8f);
|
light.SceneLight.Color = .(1.0f, 0.95f, 0.8f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestEntitiesWithModels();*/
|
_editorScene.ReleaseRef();
|
||||||
|
_editorScene = newScene;
|
||||||
|
_editor.CurrentScene = _editorScene;
|
||||||
|
var vpSize = _editor.SceneViewportWindow.ViewportSize;
|
||||||
|
_editorScene.OnViewportResize((.)vpSize.X, (.)vpSize.Y);
|
||||||
|
|
||||||
|
SetReference!(_activeScene, _editorScene);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Saves the scene in the file that is was loaded from or saved to last. If there is no such path (i.e. it is a new scene) the save file dialog will open.
|
/// Saves the scene in the file that is was loaded from or saved to last. If there is no such path (i.e. it is a new scene) the save file dialog will open.
|
||||||
private void SaveScene()
|
private void SaveScene()
|
||||||
{
|
{
|
||||||
if (String.IsNullOrWhiteSpace(SceneFilePath))
|
if (SceneFilePath.IsWhiteSpace)
|
||||||
{
|
{
|
||||||
SaveSceneAs();
|
SaveSceneAs();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneSerializer serializer = scope .(_scene);
|
SceneSerializer serializer = scope .(_editorScene);
|
||||||
serializer.Serialize(SceneFilePath);
|
serializer.Serialize(SceneFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,16 +607,20 @@ namespace GlitchyEditor
|
|||||||
/// Loads the given scene file.
|
/// Loads the given scene file.
|
||||||
private void LoadSceneFile(StringView filename)
|
private void LoadSceneFile(StringView filename)
|
||||||
{
|
{
|
||||||
|
OnSceneStop();
|
||||||
|
|
||||||
SceneFilePath = scope String(filename);
|
SceneFilePath = scope String(filename);
|
||||||
|
|
||||||
delete _scene;
|
_editorScene.ReleaseRef();
|
||||||
_scene = new Scene();
|
_editorScene = new Scene();
|
||||||
_editor.CurrentScene = _scene;
|
_editor.CurrentScene = _editorScene;
|
||||||
var vpSize = _editor.SceneViewportWindow.ViewportSize;
|
var vpSize = _editor.SceneViewportWindow.ViewportSize;
|
||||||
_scene.OnViewportResize((.)vpSize.X, (.)vpSize.Y);
|
_editorScene.OnViewportResize((.)vpSize.X, (.)vpSize.Y);
|
||||||
|
|
||||||
SceneSerializer serializer = scope .(_scene);
|
SceneSerializer serializer = scope .(_editorScene);
|
||||||
serializer.Deserialize(SceneFilePath);
|
serializer.Deserialize(SceneFilePath);
|
||||||
|
|
||||||
|
SetReference!(_activeScene, _editorScene);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawMainMenuBar()
|
private void DrawMainMenuBar()
|
||||||
@@ -610,25 +656,27 @@ namespace GlitchyEditor
|
|||||||
|
|
||||||
if(ImGui.BeginMenu("View", true))
|
if(ImGui.BeginMenu("View", true))
|
||||||
{
|
{
|
||||||
if(ImGui.MenuItem(EntityHierarchyWindow.s_WindowTitle))
|
|
||||||
{
|
|
||||||
_editor.EntityHierarchyWindow.Open = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ImGui.MenuItem(ComponentEditWindow.s_WindowTitle))
|
if(ImGui.MenuItem(ComponentEditWindow.s_WindowTitle))
|
||||||
{
|
|
||||||
_editor.ComponentEditWindow.Open = true;
|
_editor.ComponentEditWindow.Open = true;
|
||||||
}
|
|
||||||
|
|
||||||
if(ImGui.MenuItem(SceneViewportWindow.s_WindowTitle))
|
if(ImGui.MenuItem(ContentBrowserWindow.s_WindowTitle))
|
||||||
{
|
_editor.ComponentEditWindow.Open = true;
|
||||||
|
|
||||||
|
if(ImGui.MenuItem(EditorViewportWindow.s_WindowTitle))
|
||||||
_editor.SceneViewportWindow.Open = true;
|
_editor.SceneViewportWindow.Open = true;
|
||||||
}
|
|
||||||
|
if(ImGui.MenuItem(EntityHierarchyWindow.s_WindowTitle))
|
||||||
|
_editor.EntityHierarchyWindow.Open = true;
|
||||||
|
|
||||||
|
if(ImGui.MenuItem(GameViewportWindow.s_WindowTitle))
|
||||||
|
_editor.GameViewportWindow.Open = true;
|
||||||
|
|
||||||
|
if(ImGui.MenuItem(PropertiesWindow.s_WindowTitle))
|
||||||
|
_editor.PropertiesWindow.Open = true;
|
||||||
|
|
||||||
ImGui.EndMenu();
|
ImGui.EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ImGui.EndMainMenuBar();
|
ImGui.EndMainMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,7 +685,7 @@ namespace GlitchyEditor
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ViewportSizeChanged(Object sender, Vector2 viewportSize)
|
private void EditorViewportSizeChanged(Object sender, Vector2 viewportSize)
|
||||||
{
|
{
|
||||||
uint32 sizeX = (uint32)viewportSize.X;
|
uint32 sizeX = (uint32)viewportSize.X;
|
||||||
uint32 sizeY = (uint32)viewportSize.Y;
|
uint32 sizeY = (uint32)viewportSize.Y;
|
||||||
@@ -645,11 +693,27 @@ namespace GlitchyEditor
|
|||||||
if(sizeX == 0 || sizeY == 0)
|
if(sizeX == 0 || sizeY == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_viewportTarget.Resize(sizeX, sizeY);
|
_editorViewportTarget.Resize(sizeX, sizeY);
|
||||||
_cameraTarget.Resize(sizeX, sizeY);
|
_cameraTarget.Resize(sizeX, sizeY);
|
||||||
|
|
||||||
_scene.OnViewportResize(sizeX, sizeY);
|
|
||||||
_camera.OnViewportResize(sizeX, sizeY);
|
_camera.OnViewportResize(sizeX, sizeY);
|
||||||
|
|
||||||
|
_editorSceneRenderer.OnViewportResize(sizeX, sizeY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GameViewportSizeChanged(Object sender, Vector2 viewportSize)
|
||||||
|
{
|
||||||
|
uint32 sizeX = (uint32)viewportSize.X;
|
||||||
|
uint32 sizeY = (uint32)viewportSize.Y;
|
||||||
|
|
||||||
|
if(sizeX == 0 || sizeY == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_gameViewportTarget.Resize(sizeX, sizeY);
|
||||||
|
|
||||||
|
_activeScene.OnViewportResize(sizeX, sizeY);
|
||||||
|
|
||||||
|
_gameSceneRenderer.OnViewportResize(sizeX, sizeY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool OnKeyPressed(KeyPressedEvent e)
|
private bool OnKeyPressed(KeyPressedEvent e)
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ namespace GlitchyEngine
|
|||||||
|
|
||||||
public bool IsMinimized => _isMinimized;
|
public bool IsMinimized => _isMinimized;
|
||||||
|
|
||||||
|
public GameTime GameTime => _gameTime;
|
||||||
|
|
||||||
[Inline]
|
[Inline]
|
||||||
public static Application Get() => s_Instance;
|
public static Application Get() => s_Instance;
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace GlitchyEngine.Collections
|
|||||||
{
|
{
|
||||||
public T Value;
|
public T Value;
|
||||||
|
|
||||||
|
public Self Parent;
|
||||||
public List<Self> Children = new .() ~ DeleteContainerAndItems!(_);
|
public List<Self> Children = new .() ~ DeleteContainerAndItems!(_);
|
||||||
|
|
||||||
public this() {}
|
public this() {}
|
||||||
@@ -29,6 +30,7 @@ namespace GlitchyEngine.Collections
|
|||||||
}
|
}
|
||||||
|
|
||||||
Self newChild = new .(value);
|
Self newChild = new .(value);
|
||||||
|
newChild.Parent = this;
|
||||||
|
|
||||||
Children.Add(newChild);
|
Children.Add(newChild);
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ using System.IO;
|
|||||||
namespace GlitchyEngine.Content;
|
namespace GlitchyEngine.Content;
|
||||||
|
|
||||||
[BonTarget]
|
[BonTarget]
|
||||||
class Asset : RefCounter
|
abstract class Asset : RefCounter
|
||||||
{
|
{
|
||||||
|
internal AssetHandle _handle = .Invalid;
|
||||||
|
|
||||||
private append String _identifier;
|
private append String _identifier;
|
||||||
|
|
||||||
internal IContentManager _contentManager;
|
internal IContentManager _contentManager;
|
||||||
@@ -20,19 +22,18 @@ class Asset : RefCounter
|
|||||||
public StringView Identifier
|
public StringView Identifier
|
||||||
{
|
{
|
||||||
get => _identifier;
|
get => _identifier;
|
||||||
set
|
internal set => _identifier.Set(value);
|
||||||
{
|
|
||||||
_contentManager?.UpdateAssetIdentifier(this, _identifier, value);
|
|
||||||
|
|
||||||
_identifier.Set(value);
|
|
||||||
// TODO: do we need to tell the content manager, that the name changed?
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If true the asset is completely loaded. If false it is only partially loaded (if at all).
|
||||||
|
public bool Complete { get; internal set; }
|
||||||
|
|
||||||
// TODO: do we need unmanaged assets? Probably not...
|
// TODO: do we need unmanaged assets? Probably not...
|
||||||
/// Gets the content manager that manages this asset; or null if this asset isn't managed.
|
/// Gets the content manager that manages this asset; or null if this asset isn't managed.
|
||||||
public IContentManager ContentManager => _contentManager;
|
public IContentManager ContentManager => _contentManager;
|
||||||
|
|
||||||
|
public AssetHandle Handle => _handle;
|
||||||
|
|
||||||
static this
|
static this
|
||||||
{
|
{
|
||||||
gBonEnv.typeHandlers.Add(typeof(Asset),
|
gBonEnv.typeHandlers.Add(typeof(Asset),
|
||||||
@@ -43,7 +44,7 @@ class Asset : RefCounter
|
|||||||
{
|
{
|
||||||
// TODO: crash when _contentManager is deleted first...
|
// TODO: crash when _contentManager is deleted first...
|
||||||
// TODO: unregister from content manager
|
// TODO: unregister from content manager
|
||||||
_contentManager?.UnmanageAsset(this);
|
//_contentManager?.UnmanageAsset(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AssetSerialize(BonWriter writer, ValueView value, BonEnvironment environment, SerializeValueState state)
|
static void AssetSerialize(BonWriter writer, ValueView value, BonEnvironment environment, SerializeValueState state)
|
||||||
@@ -62,7 +63,15 @@ class Asset : RefCounter
|
|||||||
|
|
||||||
Deserialize.String!(reader, ref identifier, environment);
|
Deserialize.String!(reader, ref identifier, environment);
|
||||||
|
|
||||||
Asset asset = Application.Get().ContentManager.LoadAsset(identifier);
|
AssetHandle handle = Content.LoadAsset(identifier);
|
||||||
|
|
||||||
|
if (handle == .Invalid)
|
||||||
|
{
|
||||||
|
value.Assign<Asset>(null);
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
Asset asset = Content.GetAsset<Asset>(handle);
|
||||||
|
|
||||||
if (asset != null)
|
if (asset != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,336 @@
|
|||||||
|
using Bon;
|
||||||
|
using Bon.Integrated;
|
||||||
|
using System;
|
||||||
|
using xxHash;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using GlitchyEngine.Core;
|
||||||
|
|
||||||
|
namespace GlitchyEngine.Content;
|
||||||
|
|
||||||
|
struct AssetHandle : IHashable
|
||||||
|
{
|
||||||
|
private UUID _uuid;
|
||||||
|
|
||||||
|
/// Defines an asset that is invalid.
|
||||||
|
public const AssetHandle Invalid = .(UUID(0));
|
||||||
|
|
||||||
|
public bool IsValid => this != .Invalid;
|
||||||
|
public bool IsInvalid => this == .Invalid;
|
||||||
|
|
||||||
|
/// Create a new random AssetHandle
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
_uuid = UUID();
|
||||||
|
}
|
||||||
|
|
||||||
|
private this(UUID uuid)
|
||||||
|
{
|
||||||
|
_uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static this
|
||||||
|
{
|
||||||
|
gBonEnv.typeHandlers.Add(typeof(AssetHandle),
|
||||||
|
((.)new => AssetSerialize, new => AssetDeserialize));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public T Get<T>(IContentManager contentManager = null) where T : Asset
|
||||||
|
{
|
||||||
|
return Content.GetAsset<T>(this, contentManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetHashCode() => _uuid.GetHashCode();
|
||||||
|
|
||||||
|
static void AssetSerialize(BonWriter writer, ValueView value, BonEnvironment environment, SerializeValueState state)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Assert(value.type == typeof(AssetHandle));
|
||||||
|
|
||||||
|
AssetHandle handle = value.Get<AssetHandle>();
|
||||||
|
|
||||||
|
if (handle.IsInvalid)
|
||||||
|
writer.String("");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
let identifier = handle.Get<Asset>().Identifier;
|
||||||
|
writer.String(identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result<void> AssetDeserialize(BonReader reader, ValueView value, BonEnvironment environment, DeserializeValueState state)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Assert(value.type == typeof(AssetHandle));
|
||||||
|
|
||||||
|
String identifier = scope .();
|
||||||
|
|
||||||
|
Deserialize.String!(reader, ref identifier, environment);
|
||||||
|
|
||||||
|
AssetHandle handle = Content.LoadAsset(identifier);
|
||||||
|
|
||||||
|
value.Assign<AssetHandle>(handle);
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AssetHandle<T> where T : Asset
|
||||||
|
{
|
||||||
|
private AssetHandle _handle;
|
||||||
|
private IContentManager _contentManager;
|
||||||
|
/*
|
||||||
|
* We don't increment/decrement the reference counter since we guarantee that we query for the asset every frame.
|
||||||
|
*/
|
||||||
|
private T _asset;
|
||||||
|
//private uint8 _currentFrame;
|
||||||
|
//private uint64 _actualCurrentFrame = 0;
|
||||||
|
|
||||||
|
public const Self Invalid = .();
|
||||||
|
|
||||||
|
public bool IsValid => this != .Invalid;
|
||||||
|
public bool IsInvalid => this == .Invalid;
|
||||||
|
|
||||||
|
public this(AssetHandle handle, IContentManager contentManager = null)
|
||||||
|
{
|
||||||
|
_handle = handle;
|
||||||
|
|
||||||
|
_asset = handle.Get<T>(contentManager);
|
||||||
|
_contentManager = _asset?.ContentManager;
|
||||||
|
if (_contentManager == null)
|
||||||
|
_contentManager = contentManager;
|
||||||
|
//_currentFrame = (uint8)Application.Get().GameTime.FrameCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new invalid asset handle
|
||||||
|
private this()
|
||||||
|
{
|
||||||
|
_handle = .Invalid;
|
||||||
|
//_currentFrame = 0;
|
||||||
|
_contentManager = null;
|
||||||
|
_asset = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static this
|
||||||
|
{
|
||||||
|
gBonEnv.typeHandlers.Add(typeof(AssetHandle<T>),
|
||||||
|
((.)new => AssetSerialize, new => AssetDeserialize));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator Self(AssetHandle handle)
|
||||||
|
{
|
||||||
|
return Self(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator AssetHandle(Self handle)
|
||||||
|
{
|
||||||
|
return handle._handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator T(ref Self handle)
|
||||||
|
{
|
||||||
|
return handle.Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Get(IContentManager contentManager = null)
|
||||||
|
{
|
||||||
|
return Content.GetAsset<T>(_handle, contentManager == null ? _contentManager : contentManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Comptime, OnCompile(.TypeInit)]
|
||||||
|
static void Init()
|
||||||
|
{
|
||||||
|
for (var field in typeof(T).GetFields(BindingFlags.FlattenHierarchy))
|
||||||
|
{
|
||||||
|
if (field.IsStatic || !field.IsPublic)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
String modifier = field.IsPublic ? "public" : "private";
|
||||||
|
|
||||||
|
String code = scope $"""
|
||||||
|
{modifier} {field.FieldType} {field.Name}
|
||||||
|
{{
|
||||||
|
get mut
|
||||||
|
{{
|
||||||
|
return Get().{field.Name};
|
||||||
|
}}
|
||||||
|
set mut
|
||||||
|
{{
|
||||||
|
Get().{field.Name} = value;
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
""";
|
||||||
|
|
||||||
|
Compiler.EmitTypeBody(typeof(Self), code);
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<StringView, (MethodInfo? Getter, MethodInfo? Setter)> properties = scope .();
|
||||||
|
|
||||||
|
for (var method in typeof(T).GetMethods(BindingFlags.FlattenHierarchy | BindingFlags.Public))
|
||||||
|
{
|
||||||
|
if (method.IsStatic || !method.IsPublic || method.IsConstructor || method.IsDestructor)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Filter out destructors
|
||||||
|
if (method.Name == "~this")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (method.Name.StartsWith("get__"))
|
||||||
|
{
|
||||||
|
StringView name = method.Name;
|
||||||
|
name.RemoveFromStart(5);
|
||||||
|
|
||||||
|
if (!properties.TryGetValue(name, var propertyInfo))
|
||||||
|
{
|
||||||
|
propertyInfo = default;
|
||||||
|
}
|
||||||
|
|
||||||
|
propertyInfo.Getter = method;
|
||||||
|
|
||||||
|
properties[name] = propertyInfo;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (method.Name.StartsWith("set__"))
|
||||||
|
{
|
||||||
|
StringView name = method.Name;
|
||||||
|
name.RemoveFromStart(5);
|
||||||
|
|
||||||
|
if (!properties.TryGetValue(name, var propertyInfo))
|
||||||
|
{
|
||||||
|
propertyInfo = default;
|
||||||
|
}
|
||||||
|
|
||||||
|
propertyInfo.Setter = method;
|
||||||
|
|
||||||
|
properties[name] = propertyInfo;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String modifier = method.IsPublic ? "public" : "private";
|
||||||
|
|
||||||
|
String parameters = scope String();
|
||||||
|
String arguments = scope String();
|
||||||
|
|
||||||
|
for (int param < method.ParamCount)
|
||||||
|
{
|
||||||
|
Type paramType = method.GetParamType(param);
|
||||||
|
StringView paramName = method.GetParamName(param);
|
||||||
|
/*String buffer = scope .();
|
||||||
|
method.GetParamsDecl(buffer);*/
|
||||||
|
|
||||||
|
if (param != 0)
|
||||||
|
{
|
||||||
|
parameters.Append(", ");
|
||||||
|
arguments.Append(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Default value
|
||||||
|
parameters.AppendF($"{paramType} {paramName}");
|
||||||
|
|
||||||
|
/*if (!buffer.IsEmpty)
|
||||||
|
{
|
||||||
|
parameters.AppendF($"/*{buffer}*/");
|
||||||
|
}*/
|
||||||
|
|
||||||
|
arguments.AppendF($" {paramName}");
|
||||||
|
}
|
||||||
|
|
||||||
|
String code = scope $"""
|
||||||
|
{modifier} {method.ReturnType} {method.Name}({parameters}) mut
|
||||||
|
{{
|
||||||
|
return Get().{method.Name}({arguments});
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
""";
|
||||||
|
|
||||||
|
Compiler.EmitTypeBody(typeof(Self), code);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var (propertyName, property) in properties)
|
||||||
|
{
|
||||||
|
Type propertyType = property.Getter?.ReturnType ?? property.Setter?.GetParamType(0);
|
||||||
|
|
||||||
|
String getter = scope .();
|
||||||
|
String setter = scope .();
|
||||||
|
|
||||||
|
if (property.Getter != null)
|
||||||
|
{
|
||||||
|
getter.AppendF($"""
|
||||||
|
get mut
|
||||||
|
{{
|
||||||
|
return Get().{propertyName};
|
||||||
|
}}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
if (property.Setter != null)
|
||||||
|
{
|
||||||
|
getter.AppendF($"""
|
||||||
|
|
||||||
|
set mut
|
||||||
|
{{
|
||||||
|
Get().{propertyName} = value;
|
||||||
|
}}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
|
String code = scope $"""
|
||||||
|
public {propertyType} {propertyName}
|
||||||
|
{{
|
||||||
|
{getter}{setter}
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
""";
|
||||||
|
|
||||||
|
Compiler.EmitTypeBody(typeof(Self), code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetHandle<NewT> Cast<NewT>()
|
||||||
|
where NewT : Asset
|
||||||
|
where T : NewT
|
||||||
|
{
|
||||||
|
return AssetHandle<NewT>(this._handle, this._contentManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Cast up?
|
||||||
|
public AssetHandle<NewT> Cast<NewT>() where NewT : T
|
||||||
|
{
|
||||||
|
return AssetHandle<NewT>(this._handle, this._contentManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AssetSerialize(BonWriter writer, ValueView value, BonEnvironment environment, SerializeValueState state)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Assert(value.type == typeof(AssetHandle<T>));
|
||||||
|
|
||||||
|
AssetHandle handle = value.Get<AssetHandle<T>>();
|
||||||
|
|
||||||
|
if (handle.IsInvalid)
|
||||||
|
writer.String("");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
let identifier = handle.Get<Asset>().Identifier;
|
||||||
|
writer.String(identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result<void> AssetDeserialize(BonReader reader, ValueView value, BonEnvironment environment, DeserializeValueState state)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Assert(value.type == typeof(AssetHandle<T>));
|
||||||
|
|
||||||
|
String identifier = scope .();
|
||||||
|
|
||||||
|
Deserialize.String!(reader, ref identifier, environment);
|
||||||
|
|
||||||
|
AssetHandle<T> handle = Content.LoadAsset(identifier);
|
||||||
|
|
||||||
|
value.Assign<AssetHandle<T>>(handle);
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -57,40 +57,82 @@ namespace GlitchyEngine.Content
|
|||||||
/// @param contentManager The content manager used to load the asset.
|
/// @param contentManager The content manager used to load the asset.
|
||||||
/// @returns The loaded asset.
|
/// @returns The loaded asset.
|
||||||
Asset LoadAsset(Stream file, AssetLoaderConfig config, StringView assetIdentifier, StringView? subAsset, IContentManager contentManager);
|
Asset LoadAsset(Stream file, AssetLoaderConfig config, StringView assetIdentifier, StringView? subAsset, IContentManager contentManager);
|
||||||
|
|
||||||
|
/// Returns the placeholder asset.
|
||||||
|
Asset GetPlaceholderAsset(Type assetType);
|
||||||
|
|
||||||
|
/// Returns the error asset.
|
||||||
|
Asset GetErrorAsset(Type assetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static class Content
|
||||||
{
|
{
|
||||||
/// Loads the specified asset with the given contentManager or the current applications content manager.
|
/// Loads the specified asset with the given contentManager or the current applications content manager.
|
||||||
public static T LoadAsset<T>(StringView assetIdentifier, IContentManager contentManager = null) where T : Asset
|
public static AssetHandle LoadAsset(StringView assetIdentifier, IContentManager contentManager = null, bool blocking = false)
|
||||||
{
|
{
|
||||||
var contentManager;
|
var contentManager;
|
||||||
|
|
||||||
if (contentManager == null)
|
if (contentManager == null)
|
||||||
contentManager = Application.Get().ContentManager;
|
contentManager = Application.Get().ContentManager;
|
||||||
|
|
||||||
Asset asset = contentManager.LoadAsset(assetIdentifier);
|
AssetHandle handle = contentManager.LoadAsset(assetIdentifier, blocking);
|
||||||
|
|
||||||
Log.EngineLogger.AssertDebug(asset is T);
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Loads the specified asset with the given contentManager or the current applications content manager.
|
||||||
|
public static T GetAsset<T>(AssetHandle handle, IContentManager contentManager = null) where T : Asset
|
||||||
|
{
|
||||||
|
var contentManager;
|
||||||
|
|
||||||
|
if (contentManager == null)
|
||||||
|
contentManager = Application.Get().ContentManager;
|
||||||
|
|
||||||
|
Asset asset = contentManager.GetAsset(typeof(T), handle);
|
||||||
|
|
||||||
return (T)asset;
|
return (T)asset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static AssetHandle ManageAsset(Asset asset, IContentManager contentManager = null)
|
||||||
|
{
|
||||||
|
var contentManager;
|
||||||
|
|
||||||
|
if (contentManager == null)
|
||||||
|
contentManager = Application.Get().ContentManager;
|
||||||
|
|
||||||
|
return contentManager.ManageAsset(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*public static AssetHandle<T> ManageAsset<T>(T asset, IContentManager contentManager = null) where T : Asset
|
||||||
|
{
|
||||||
|
var contentManager;
|
||||||
|
|
||||||
|
if (contentManager == null)
|
||||||
|
contentManager = Application.Get().ContentManager;
|
||||||
|
|
||||||
|
contentManager.ManageAsset(asset);
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IContentManager
|
interface IContentManager
|
||||||
{
|
{
|
||||||
/// Loads the given asset.
|
/// Loads the Asset with the given handle and returns the handle.
|
||||||
Asset LoadAsset(StringView assetIdentifier);
|
AssetHandle LoadAsset(StringView assetIdentifier, bool blocking = false);
|
||||||
|
|
||||||
|
/// Returns the asset for the given handle or null, if it isn't loaded.
|
||||||
|
Asset GetAsset(AssetHandle handle)
|
||||||
|
{
|
||||||
|
return GetAsset(null, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the asset for the given handle or the default asset of the given type.
|
||||||
|
Asset GetAsset(Type assetType, AssetHandle handle);
|
||||||
|
|
||||||
/// The content manager will manage the asset (e.g. provide it when LoadAsset is called with the assets identifier)
|
/// The content manager will manage the asset (e.g. provide it when LoadAsset is called with the assets identifier)
|
||||||
void ManageAsset(Asset asset);
|
AssetHandle ManageAsset(Asset asset);
|
||||||
|
|
||||||
/// The content manager will no longer manage the asset.
|
/// The content manager will no longer manage the asset.
|
||||||
void UnmanageAsset(Asset asset);
|
void UnmanageAsset(AssetHandle asset);
|
||||||
|
|
||||||
// TODO: Maybe calling UnmanageAsset -> ManageAsset is enough....
|
|
||||||
/// Provides a method for the asset to tell its content manager that the identifer changed.
|
|
||||||
void UpdateAssetIdentifier(Asset asset, StringView oldIdentifier, StringView newIdentifier);
|
|
||||||
|
|
||||||
/// Returns a data stream for the given asset.
|
/// Returns a data stream for the given asset.
|
||||||
Stream GetStream(StringView assetIdentifier);
|
Stream GetStream(StringView assetIdentifier);
|
||||||
@@ -109,22 +151,22 @@ namespace GlitchyEngine.Content
|
|||||||
Runtime.NotImplemented();
|
Runtime.NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Asset LoadAsset(StringView assetIdentifier)
|
public AssetHandle LoadAsset(StringView assetIdentifier, bool blocking = false)
|
||||||
{
|
{
|
||||||
Runtime.NotImplemented();
|
Runtime.NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ManageAsset(Asset asset)
|
public Asset GetAsset(Type assetType, AssetHandle handle)
|
||||||
{
|
{
|
||||||
Runtime.NotImplemented();
|
Runtime.NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UnmanageAsset(Asset asset)
|
public AssetHandle ManageAsset(Asset asset)
|
||||||
{
|
{
|
||||||
Runtime.NotImplemented();
|
Runtime.NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateAssetIdentifier(Asset asset, StringView oldIdentifier, StringView newIdentifier)
|
public void UnmanageAsset(AssetHandle asset)
|
||||||
{
|
{
|
||||||
Runtime.NotImplemented();
|
Runtime.NotImplemented();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -229,156 +229,6 @@ namespace GlitchyEngine.Content
|
|||||||
return .Success;
|
return .Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EcsEntity LoadModel(String filename, Material material, EcsWorld world,
|
|
||||||
List<AnimationClip> outClips, StringView entityName = StringView())
|
|
||||||
{
|
|
||||||
CGLTF.Options options = .();
|
|
||||||
CGLTF.Data* data;
|
|
||||||
CGLTF.Result result = CGLTF.ParseFile(options, filename, out data);
|
|
||||||
|
|
||||||
Log.EngineLogger.Assert(result == .Success, "Failed to load model.");
|
|
||||||
|
|
||||||
result = CGLTF.LoadBuffers(options, data, filename);
|
|
||||||
|
|
||||||
Log.EngineLogger.Assert(result == .Success, "Failed to load buffers");
|
|
||||||
|
|
||||||
(EcsEntity entity, ?) = CreateEntity(world, entityName, .InvalidEntity);
|
|
||||||
|
|
||||||
for(var node in data.Scenes[0].Nodes)
|
|
||||||
{
|
|
||||||
NodesToEntities(data, node, entity, world, material, outClips);
|
|
||||||
}
|
|
||||||
|
|
||||||
CGLTF.Free(data);
|
|
||||||
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static (EcsEntity Entity, TransformComponent* Transform) CreateEntity(EcsWorld world, StringView? name, EcsEntity parent)
|
|
||||||
{
|
|
||||||
EcsEntity entity = world.NewEntity();
|
|
||||||
|
|
||||||
var nameComponent = world.AssignComponent<DebugNameComponent>(entity);
|
|
||||||
|
|
||||||
if (name != null && name.Value.Ptr != null)
|
|
||||||
{
|
|
||||||
nameComponent.SetName(name.Value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nameComponent.SetName("Unnamed Node");
|
|
||||||
}
|
|
||||||
|
|
||||||
/////TODO: !!!!!!!!REPORT!!!!!!!!!!!!!
|
|
||||||
// This works
|
|
||||||
TransformComponent cmp = .();
|
|
||||||
var childTransform = world.AssignComponent<TransformComponent>(entity, cmp);
|
|
||||||
// This trashes the stack
|
|
||||||
//var childTransform = world.AssignComponent<TransformComponent>(entity);
|
|
||||||
childTransform.Parent = parent;
|
|
||||||
|
|
||||||
return (entity, childTransform);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void NodesToEntities(CGLTF.Data* data, CGLTF.Node* node, EcsEntity parentEntity, EcsWorld world, Material material, List<AnimationClip> clips)
|
|
||||||
{
|
|
||||||
(EcsEntity entity, TransformComponent* childTransform) = CreateEntity(world, node.Name == null ? null : StringView(node.Name), parentEntity);
|
|
||||||
|
|
||||||
if(node.HasMatrix)
|
|
||||||
{
|
|
||||||
childTransform.LocalTransform = *(Matrix*)&node.Matrix;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(node.HasTranslation)
|
|
||||||
childTransform.Position = *(Vector3*)&node.Translation;
|
|
||||||
else
|
|
||||||
childTransform.Position = .Zero;
|
|
||||||
|
|
||||||
if(node.HasRotation)
|
|
||||||
childTransform.Rotation = *(Quaternion*)&node.Rotation;
|
|
||||||
else
|
|
||||||
childTransform.Rotation = .Identity;
|
|
||||||
|
|
||||||
if(node.HasScale)
|
|
||||||
childTransform.Scale = *(Vector3*)&node.Scale;
|
|
||||||
else
|
|
||||||
childTransform.Scale = .(1, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invert the Z-Axis of the root Node to convert the coordinate system from right-handed to left-handed
|
|
||||||
if(parentEntity == .InvalidEntity)
|
|
||||||
childTransform.Scale *= .(1, 1, -1);
|
|
||||||
|
|
||||||
Skeleton skeleton = null;
|
|
||||||
|
|
||||||
if(node.Skin != null)
|
|
||||||
{
|
|
||||||
skeleton = ExtractSkeleton(node.Skin);
|
|
||||||
|
|
||||||
LoadAnimationClips(data, node.Skin, skeleton, clips);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(node.Mesh != null)
|
|
||||||
{
|
|
||||||
// If we have only one primitive, add it directly to the entity
|
|
||||||
if(node.Mesh.Primitives.Length == 1)
|
|
||||||
{
|
|
||||||
var mesh = world.AssignComponent<MeshComponent>(entity);
|
|
||||||
|
|
||||||
using (var geo = PrimitiveToGeoBinding(node.Mesh.Primitives[0]))
|
|
||||||
{
|
|
||||||
mesh.Mesh = geo;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(skeleton == null)
|
|
||||||
{
|
|
||||||
var meshRenderer = world.AssignComponent<MeshRendererComponent>(entity);
|
|
||||||
meshRenderer.Material = material;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var meshRenderer = world.AssignComponent<SkinnedMeshRendererComponent>(entity);
|
|
||||||
meshRenderer.Material = material;
|
|
||||||
meshRenderer.Skeleton = skeleton;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// otherwise one child-entity per primitive
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(var primitive in node.Mesh.Primitives)
|
|
||||||
{
|
|
||||||
EcsEntity meshEntity = world.NewEntity();
|
|
||||||
|
|
||||||
var meshParent = world.AssignComponent<ParentComponent>(meshEntity);
|
|
||||||
meshParent.Entity = entity;
|
|
||||||
|
|
||||||
var mesh = world.AssignComponent<MeshComponent>(meshEntity);
|
|
||||||
mesh.Mesh = PrimitiveToGeoBinding(primitive);
|
|
||||||
|
|
||||||
if(skeleton == null)
|
|
||||||
{
|
|
||||||
var meshRenderer = world.AssignComponent<MeshRendererComponent>(meshEntity);
|
|
||||||
meshRenderer.Material = material;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var meshRenderer = world.AssignComponent<SkinnedMeshRendererComponent>(meshEntity);
|
|
||||||
meshRenderer.Material = material;
|
|
||||||
meshRenderer.Skeleton = skeleton;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
skeleton?.ReleaseRef();
|
|
||||||
|
|
||||||
for(var child in node.Children)
|
|
||||||
{
|
|
||||||
NodesToEntities(data, child, entity, world, material, clips);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GeometryBinding PrimitiveToGeoBinding(CGLTF.Primitive primitive)
|
public static GeometryBinding PrimitiveToGeoBinding(CGLTF.Primitive primitive)
|
||||||
{
|
{
|
||||||
GeometryBinding binding = new GeometryBinding();
|
GeometryBinding binding = new GeometryBinding();
|
||||||
|
|||||||
@@ -20,11 +20,10 @@ namespace GlitchyEngine.Generators
|
|||||||
outFileName.Append(name);
|
outFileName.Append(name);
|
||||||
outText.AppendF(
|
outText.AppendF(
|
||||||
$"""
|
$"""
|
||||||
namespace {Namespace}
|
namespace {Namespace};
|
||||||
|
|
||||||
|
struct {name}
|
||||||
{{
|
{{
|
||||||
struct {name}
|
|
||||||
{{
|
|
||||||
}}
|
|
||||||
}}
|
}}
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,5 +4,4 @@ namespace GlitchyEngine.Math
|
|||||||
{
|
{
|
||||||
typealias Matrix3x3 = DirectX.Math.Matrix3x3;
|
typealias Matrix3x3 = DirectX.Math.Matrix3x3;
|
||||||
typealias Matrix4x3 = DirectX.Math.Matrix4x3;
|
typealias Matrix4x3 = DirectX.Math.Matrix4x3;
|
||||||
typealias Matrix = DirectX.Math.Matrix;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,877 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GlitchyEngine.Math;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a 4 by 4 column-major matrix.
|
||||||
|
*/
|
||||||
|
[Union]
|
||||||
|
public struct Matrix
|
||||||
|
{
|
||||||
|
public struct Values
|
||||||
|
{
|
||||||
|
public float _11, _21, _31, _41,
|
||||||
|
_12, _22, _32, _42,
|
||||||
|
_13, _23, _33, _43,
|
||||||
|
_14, _24, _34, _44;
|
||||||
|
}
|
||||||
|
|
||||||
|
public const Matrix Zero = .();
|
||||||
|
public const Matrix Identity = .(.UnitX, .UnitY, .UnitZ, .UnitW);
|
||||||
|
|
||||||
|
public using Values V;
|
||||||
|
public float[4][4] Values;
|
||||||
|
public Vector4[4] Columns;
|
||||||
|
|
||||||
|
/// Creates a new zero-matrix.
|
||||||
|
public this() => this = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new Matrix.
|
||||||
|
* @param value The value that will be assigned to all components.
|
||||||
|
*/
|
||||||
|
/// Creates a new matrix.
|
||||||
|
public this(float value)
|
||||||
|
{
|
||||||
|
this = ?;
|
||||||
|
_11 = _12 = _13 = _14 =
|
||||||
|
_21 = _22 = _23 = _24 =
|
||||||
|
_31 = _32 = _33 = _34 =
|
||||||
|
_41 = _42 = _43 = _44 = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new matrix and initializes it with the given entries.
|
||||||
|
public this(float m00, float m01, float m02, float m03,
|
||||||
|
float m10, float m11, float m12, float m13,
|
||||||
|
float m20, float m21, float m22, float m23,
|
||||||
|
float m30, float m31, float m32, float m33)
|
||||||
|
{
|
||||||
|
Values[0][0] = m00; Values[0][1] = m10; Values[0][2] = m20; Values[0][3] = m30;
|
||||||
|
Values[1][0] = m01; Values[1][1] = m11; Values[1][2] = m21; Values[1][3] = m31;
|
||||||
|
Values[2][0] = m02; Values[2][1] = m12; Values[2][2] = m22; Values[2][3] = m32;
|
||||||
|
Values[3][0] = m03; Values[3][1] = m13; Values[3][2] = m23; Values[3][3] = m33;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new matrix and initializes it with the given column-vectors.
|
||||||
|
public this(Vector4 c0, Vector4 c1, Vector4 c2, Vector4 c3)
|
||||||
|
{
|
||||||
|
Columns[0] = c0;
|
||||||
|
Columns[1] = c1;
|
||||||
|
Columns[2] = c2;
|
||||||
|
Columns[3] = c3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref Vector3 Right
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
#unwarn
|
||||||
|
return ref *(Vector3*)&Columns[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref Vector3 Up
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
#unwarn
|
||||||
|
return ref *(Vector3*)&Columns[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref Vector3 Forward
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
#unwarn
|
||||||
|
return ref *(Vector3*)&Columns[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref Vector3 Translation
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
#unwarn
|
||||||
|
return ref *(Vector3*)&Columns[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 Scale
|
||||||
|
{
|
||||||
|
[Inline]
|
||||||
|
get => .(_11, _22, _33);
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
_11 = value.X;
|
||||||
|
_22 = value.Y;
|
||||||
|
_33 = value.Z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref float this[int row, int column]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
#unwarn
|
||||||
|
return ref *(float*)&Values[column][row];
|
||||||
|
}
|
||||||
|
|
||||||
|
[Checked]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if(column < 0 || column > 3 || row < 0 || row > 3)
|
||||||
|
Internal.ThrowIndexOutOfRange();
|
||||||
|
|
||||||
|
#unwarn
|
||||||
|
return ref *(float*)&Values[column][row];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref Vector4 this[int column]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
#unwarn
|
||||||
|
return ref *(Vector4*)&Columns[column];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Checked]
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if(column < 0 || column > 3)
|
||||||
|
Internal.ThrowIndexOutOfRange();
|
||||||
|
|
||||||
|
#unwarn
|
||||||
|
return ref *(Vector4*)&Columns[column];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Assignment Operators
|
||||||
|
//
|
||||||
|
|
||||||
|
// Addition
|
||||||
|
|
||||||
|
public void operator +=(Matrix value) mut
|
||||||
|
{
|
||||||
|
Columns[0] += value.Columns[0];
|
||||||
|
Columns[1] += value.Columns[1];
|
||||||
|
Columns[2] += value.Columns[2];
|
||||||
|
Columns[3] += value.Columns[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matrix + Scalar : Matrix + Scalar * Identity
|
||||||
|
public void operator +=(float scalar) mut
|
||||||
|
{
|
||||||
|
_11 += scalar;
|
||||||
|
_22 += scalar;
|
||||||
|
_33 += scalar;
|
||||||
|
_44 += scalar;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtraction
|
||||||
|
|
||||||
|
public void operator -=(Matrix value) mut
|
||||||
|
{
|
||||||
|
Columns[0] -= value.Columns[0];
|
||||||
|
Columns[1] -= value.Columns[1];
|
||||||
|
Columns[2] -= value.Columns[2];
|
||||||
|
Columns[3] -= value.Columns[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matrix - Scalar : Matrix - Scalar * Identity
|
||||||
|
public void operator -=(float scalar) mut
|
||||||
|
{
|
||||||
|
_11 -= scalar;
|
||||||
|
_22 -= scalar;
|
||||||
|
_33 -= scalar;
|
||||||
|
_44 -= scalar;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiplication
|
||||||
|
|
||||||
|
public void operator *=(float scalar) mut
|
||||||
|
{
|
||||||
|
Columns[0] *= scalar;
|
||||||
|
Columns[1] *= scalar;
|
||||||
|
Columns[2] *= scalar;
|
||||||
|
Columns[3] *= scalar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void operator *=(Matrix value) mut
|
||||||
|
{
|
||||||
|
this = this * value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Divide
|
||||||
|
|
||||||
|
public void operator /=(float scalar) mut
|
||||||
|
{
|
||||||
|
float inv = 1.0f / scalar;
|
||||||
|
Columns[0] *= inv;
|
||||||
|
Columns[1] *= inv;
|
||||||
|
Columns[2] *= inv;
|
||||||
|
Columns[3] *= inv;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Operators
|
||||||
|
//
|
||||||
|
|
||||||
|
// Addition
|
||||||
|
|
||||||
|
public static Matrix operator +(Matrix left, Matrix right)
|
||||||
|
{
|
||||||
|
return .(left.Columns[0] + right.Columns[0],
|
||||||
|
left.Columns[1] + right.Columns[1],
|
||||||
|
left.Columns[2] + right.Columns[2],
|
||||||
|
left.Columns[3] + right.Columns[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix operator +(Matrix left, float right)
|
||||||
|
{
|
||||||
|
Matrix result = left;
|
||||||
|
result._11 += right;
|
||||||
|
result._22 += right;
|
||||||
|
result._33 += right;
|
||||||
|
result._44 += right;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix operator +(float left, Matrix right)
|
||||||
|
{
|
||||||
|
Matrix result = right;
|
||||||
|
result._11 += left;
|
||||||
|
result._22 += left;
|
||||||
|
result._33 += left;
|
||||||
|
result._44 += left;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtraction
|
||||||
|
|
||||||
|
public static Matrix operator -(Matrix left, Matrix right)
|
||||||
|
{
|
||||||
|
return .(left.Columns[0] - right.Columns[0],
|
||||||
|
left.Columns[1] - right.Columns[1],
|
||||||
|
left.Columns[2] - right.Columns[2],
|
||||||
|
left.Columns[3] - right.Columns[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix operator -(Matrix value, float scalar)
|
||||||
|
{
|
||||||
|
Matrix result = value;
|
||||||
|
result._11 -= scalar;
|
||||||
|
result._22 -= scalar;
|
||||||
|
result._33 -= scalar;
|
||||||
|
result._44 -= scalar;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix operator -(float scalar, Matrix value)
|
||||||
|
{
|
||||||
|
Matrix result = value;
|
||||||
|
result._11 -= scalar;
|
||||||
|
result._22 -= scalar;
|
||||||
|
result._33 -= scalar;
|
||||||
|
result._44 -= scalar;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix operator -(Matrix value)
|
||||||
|
{
|
||||||
|
return .(-value.Columns[0],
|
||||||
|
-value.Columns[1],
|
||||||
|
-value.Columns[2],
|
||||||
|
-value.Columns[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiplication
|
||||||
|
|
||||||
|
public static Matrix operator *(Matrix left, Matrix right)
|
||||||
|
{
|
||||||
|
#unwarn
|
||||||
|
var l = &left.V;
|
||||||
|
#unwarn
|
||||||
|
var r = &right.V;
|
||||||
|
|
||||||
|
Matrix result = ?;
|
||||||
|
|
||||||
|
result._11 = (l._11 * r._11) + (l._12 * r._21) + (l._13 * r._31) + (l._14 * r._41);
|
||||||
|
result._12 = (l._11 * r._12) + (l._12 * r._22) + (l._13 * r._32) + (l._14 * r._42);
|
||||||
|
result._13 = (l._11 * r._13) + (l._12 * r._23) + (l._13 * r._33) + (l._14 * r._43);
|
||||||
|
result._14 = (l._11 * r._14) + (l._12 * r._24) + (l._13 * r._34) + (l._14 * r._44);
|
||||||
|
|
||||||
|
result._21 = (l._21 * r._11) + (l._22 * r._21) + (l._23 * r._31) + (l._24 * r._41);
|
||||||
|
result._22 = (l._21 * r._12) + (l._22 * r._22) + (l._23 * r._32) + (l._24 * r._42);
|
||||||
|
result._23 = (l._21 * r._13) + (l._22 * r._23) + (l._23 * r._33) + (l._24 * r._43);
|
||||||
|
result._24 = (l._21 * r._14) + (l._22 * r._24) + (l._23 * r._34) + (l._24 * r._44);
|
||||||
|
|
||||||
|
result._31 = (l._31 * r._11) + (l._32 * r._21) + (l._33 * r._31) + (l._34 * r._41);
|
||||||
|
result._32 = (l._31 * r._12) + (l._32 * r._22) + (l._33 * r._32) + (l._34 * r._42);
|
||||||
|
result._33 = (l._31 * r._13) + (l._32 * r._23) + (l._33 * r._33) + (l._34 * r._43);
|
||||||
|
result._34 = (l._31 * r._14) + (l._32 * r._24) + (l._33 * r._34) + (l._34 * r._44);
|
||||||
|
|
||||||
|
result._41 = (l._41 * r._11) + (l._42 * r._21) + (l._43 * r._31) + (l._44 * r._41);
|
||||||
|
result._42 = (l._41 * r._12) + (l._42 * r._22) + (l._43 * r._32) + (l._44 * r._42);
|
||||||
|
result._43 = (l._41 * r._13) + (l._42 * r._23) + (l._43 * r._33) + (l._44 * r._43);
|
||||||
|
result._44 = (l._41 * r._14) + (l._42 * r._24) + (l._43 * r._34) + (l._44 * r._44);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix operator *(Matrix value, float scalar)
|
||||||
|
{
|
||||||
|
return .(value.Columns[0] * scalar,
|
||||||
|
value.Columns[1] * scalar,
|
||||||
|
value.Columns[2] * scalar,
|
||||||
|
value.Columns[3] * scalar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix operator *(float scalar, Matrix value)
|
||||||
|
{
|
||||||
|
return .(value.Columns[0] * scalar,
|
||||||
|
value.Columns[1] * scalar,
|
||||||
|
value.Columns[2] * scalar,
|
||||||
|
value.Columns[3] * scalar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplies a matrix and a column-vector resulting in a column vector.
|
||||||
|
*/
|
||||||
|
public static Vector4 operator *(Matrix matrix, Vector4 columnVector)
|
||||||
|
{
|
||||||
|
#unwarn
|
||||||
|
var m = &matrix.V;
|
||||||
|
|
||||||
|
Vector4 result = ?;
|
||||||
|
result.X = (m._11 * columnVector.X) + (m._12 * columnVector.Y) + (m._13 * columnVector.Z) + (m._14 * columnVector.W);
|
||||||
|
result.Y = (m._21 * columnVector.X) + (m._22 * columnVector.Y) + (m._23 * columnVector.Z) + (m._24 * columnVector.W);
|
||||||
|
result.Z = (m._31 * columnVector.X) + (m._32 * columnVector.Y) + (m._33 * columnVector.Z) + (m._34 * columnVector.W);
|
||||||
|
result.W = (m._41 * columnVector.X) + (m._42 * columnVector.Y) + (m._43 * columnVector.Z) + (m._44 * columnVector.W);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplies a row-vector and a matrix resulting in a row vector.
|
||||||
|
*/
|
||||||
|
public static Vector4 operator *(Vector4 rowVector, Matrix matrix)
|
||||||
|
{
|
||||||
|
#unwarn
|
||||||
|
var m = &matrix.V;
|
||||||
|
|
||||||
|
Vector4 result = ?;
|
||||||
|
result.X = (rowVector.X * m._11) + (rowVector.Y * m._21) + (rowVector.Z * m._31) + (rowVector.W * m._41);
|
||||||
|
result.Y = (rowVector.X * m._12) + (rowVector.Y * m._22) + (rowVector.Z * m._32) + (rowVector.W * m._42);
|
||||||
|
result.Z = (rowVector.X * m._13) + (rowVector.Y * m._23) + (rowVector.Z * m._33) + (rowVector.W * m._43);
|
||||||
|
result.W = (rowVector.X * m._14) + (rowVector.Y * m._24) + (rowVector.Z * m._34) + (rowVector.W * m._44);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Divison
|
||||||
|
|
||||||
|
public static Matrix operator /(Matrix m, float s)
|
||||||
|
{
|
||||||
|
float f = 1 / s;
|
||||||
|
Matrix M = m;
|
||||||
|
|
||||||
|
return .(M.Columns[0] * f, M.Columns[1] * f, M.Columns[2] * f, M.Columns[3] * f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix Scaling(float scale)
|
||||||
|
{
|
||||||
|
return .(scale, 0, 0, 0,
|
||||||
|
0, scale, 0, 0,
|
||||||
|
0, 0, scale, 0,
|
||||||
|
0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix Scaling(float scaleX, float scaleY, float scaleZ)
|
||||||
|
{
|
||||||
|
return .(scaleX, 0, 0, 0,
|
||||||
|
0, scaleY, 0, 0,
|
||||||
|
0, 0, scaleZ, 0,
|
||||||
|
0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix Scaling(Vector3 scale)
|
||||||
|
{
|
||||||
|
return .(scale.X, 0, 0, 0,
|
||||||
|
0, scale.Y, 0, 0,
|
||||||
|
0, 0, scale.Z, 0,
|
||||||
|
0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix Translation(float x, float y, float z)
|
||||||
|
{
|
||||||
|
return .(1, 0, 0, x,
|
||||||
|
0, 1, 0, y,
|
||||||
|
0, 0, 1, z,
|
||||||
|
0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix Translation(Vector3 translation)
|
||||||
|
{
|
||||||
|
return .(1, 0, 0, translation.X,
|
||||||
|
0, 1, 0, translation.Y,
|
||||||
|
0, 0, 1, translation.Z,
|
||||||
|
0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix RotationX(float rot)
|
||||||
|
{
|
||||||
|
float sin = Math.Sin(rot);
|
||||||
|
float cos = Math.Cos(rot);
|
||||||
|
|
||||||
|
return .(1, 0, 0, 0,
|
||||||
|
0, cos, -sin, 0,
|
||||||
|
0, sin, cos, 0,
|
||||||
|
0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix RotationY(float rot)
|
||||||
|
{
|
||||||
|
float sin = Math.Sin(rot);
|
||||||
|
float cos = Math.Cos(rot);
|
||||||
|
|
||||||
|
return .(cos, 0, sin, 0,
|
||||||
|
0, 1, 0, 0,
|
||||||
|
-sin, 0, cos, 0,
|
||||||
|
0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Matrix RotationZ(float rot)
|
||||||
|
{
|
||||||
|
float sin = Math.Sin(rot);
|
||||||
|
float cos = Math.Cos(rot);
|
||||||
|
|
||||||
|
return .(cos, -sin, 0, 0,
|
||||||
|
sin, cos, 0, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates a view Matrix that is located at specified postion and looks at the given target.
|
||||||
|
* @param position The cameras position.
|
||||||
|
* @param target The point the camera looks at.
|
||||||
|
* @param up A vector defining the up direction of the camera.
|
||||||
|
* @returns a view matrix.
|
||||||
|
*/
|
||||||
|
public static Matrix LookAt(Vector3 position, Vector3 target, Vector3 up)
|
||||||
|
{
|
||||||
|
Vector3 forward = target - position;
|
||||||
|
forward.Normalize();
|
||||||
|
|
||||||
|
Vector3 right = Vector3.Cross(up, forward);
|
||||||
|
right.Normalize();
|
||||||
|
|
||||||
|
Vector3 newUp = Vector3.Cross(forward, right);
|
||||||
|
newUp.Normalize();
|
||||||
|
|
||||||
|
Matrix result = .Identity;
|
||||||
|
|
||||||
|
result.Forward = forward;
|
||||||
|
result.Up = up;
|
||||||
|
result.Right = right;
|
||||||
|
result.Translation.X = -Vector3.Dot(position, right);
|
||||||
|
result.Translation.Y = -Vector3.Dot(position, up);
|
||||||
|
result.Translation.Z = -Vector3.Dot(position, forward);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the transpose of this matrix
|
||||||
|
[DisableChecks]
|
||||||
|
public Matrix Transpose()
|
||||||
|
{
|
||||||
|
return .(_11, _21, _31, _41,
|
||||||
|
_12, _22, _32, _42,
|
||||||
|
_13, _23, _33, _43,
|
||||||
|
_14, _24, _34, _44);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Calculates the inverse of the matrix.
|
||||||
|
*/
|
||||||
|
[DisableChecks]
|
||||||
|
public float Determinant() mut
|
||||||
|
{
|
||||||
|
// From: Lengyel, Eric. Foundations of Game Engine Development, Volume 1: Mathematics (S.61). Kindle-Version.
|
||||||
|
|
||||||
|
Vector3 a = *(Vector3*)&Columns[0];
|
||||||
|
Vector3 b = *(Vector3*)&Columns[1];
|
||||||
|
Vector3 c = *(Vector3*)&Columns[2];
|
||||||
|
Vector3 d = *(Vector3*)&Columns[3];
|
||||||
|
|
||||||
|
float x = this[3, 0];
|
||||||
|
float y = this[3, 1];
|
||||||
|
float z = this[3, 2];
|
||||||
|
float w = this[3, 3];
|
||||||
|
|
||||||
|
Vector3 s = Vector3.Cross(a, b);
|
||||||
|
Vector3 t = Vector3.Cross(c, d);
|
||||||
|
Vector3 u = y * a - x * b;
|
||||||
|
Vector3 v = w * c - z * d;
|
||||||
|
|
||||||
|
return Vector3.Dot(s, v) + Vector3.Dot(t, u);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Calculates the inverse of the matrix.
|
||||||
|
*/
|
||||||
|
public Matrix Invert()
|
||||||
|
{
|
||||||
|
// From: Lengyel, Eric. Foundations of Game Engine Development, Volume 1: Mathematics (S.61). Kindle-Version.
|
||||||
|
|
||||||
|
#unwarn
|
||||||
|
Vector3 a = *(Vector3*)&Columns[0];
|
||||||
|
#unwarn
|
||||||
|
Vector3 b = *(Vector3*)&Columns[1];
|
||||||
|
#unwarn
|
||||||
|
Vector3 c = *(Vector3*)&Columns[2];
|
||||||
|
#unwarn
|
||||||
|
Vector3 d = *(Vector3*)&Columns[3];
|
||||||
|
|
||||||
|
float x = this[3, 0];
|
||||||
|
float y = this[3, 1];
|
||||||
|
float z = this[3, 2];
|
||||||
|
float w = this[3, 3];
|
||||||
|
|
||||||
|
Vector3 s = Vector3.Cross(a, b);
|
||||||
|
Vector3 t = Vector3.Cross(c, d);
|
||||||
|
Vector3 u = y * a - x * b;
|
||||||
|
Vector3 v = w * c - z * d;
|
||||||
|
|
||||||
|
float invDet = 1.0f / (Vector3.Dot(s, v) + Vector3.Dot(t, u));
|
||||||
|
|
||||||
|
s *= invDet;
|
||||||
|
t *= invDet;
|
||||||
|
u *= invDet;
|
||||||
|
v *= invDet;
|
||||||
|
|
||||||
|
Vector3 r0 = Vector3.Cross(b, v) + t * y;
|
||||||
|
Vector3 r1 = Vector3.Cross(v, a) - t * x;
|
||||||
|
Vector3 r2 = Vector3.Cross(d, u) + s * w;
|
||||||
|
Vector3 r3 = Vector3.Cross(u, c) - s * z;
|
||||||
|
return .(r0.X, r0.Y, r0.Z, -Vector3.Dot(b, t),
|
||||||
|
r1.X, r1.Y, r1.Z, Vector3.Dot(a, t),
|
||||||
|
r2.X, r2.Y, r2.Z, -Vector3.Dot(d, s),
|
||||||
|
r3.X, r3.Y, r3.Z, Vector3.Dot(c, s));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculates the inverse of the matrix.
|
||||||
|
public static Matrix Invert(in Matrix matrix)
|
||||||
|
{
|
||||||
|
// From: Lengyel, Eric. Foundations of Game Engine Development, Volume 1: Mathematics (S.61). Kindle-Version.
|
||||||
|
|
||||||
|
#unwarn
|
||||||
|
Vector3 a = *(Vector3*)&matrix.Columns[0];
|
||||||
|
#unwarn
|
||||||
|
Vector3 b = *(Vector3*)&matrix.Columns[1];
|
||||||
|
#unwarn
|
||||||
|
Vector3 c = *(Vector3*)&matrix.Columns[2];
|
||||||
|
#unwarn
|
||||||
|
Vector3 d = *(Vector3*)&matrix.Columns[3];
|
||||||
|
|
||||||
|
float x = matrix[3, 0];
|
||||||
|
float y = matrix[3, 1];
|
||||||
|
float z = matrix[3, 2];
|
||||||
|
float w = matrix[3, 3];
|
||||||
|
|
||||||
|
Vector3 s = Vector3.Cross(a, b);
|
||||||
|
Vector3 t = Vector3.Cross(c, d);
|
||||||
|
Vector3 u = y * a - x * b;
|
||||||
|
Vector3 v = w * c - z * d;
|
||||||
|
|
||||||
|
float invDet = 1.0f / (Vector3.Dot(s, v) + Vector3.Dot(t, u));
|
||||||
|
|
||||||
|
s *= invDet;
|
||||||
|
t *= invDet;
|
||||||
|
u *= invDet;
|
||||||
|
v *= invDet;
|
||||||
|
|
||||||
|
Vector3 r0 = Vector3.Cross(b, v) + t * y;
|
||||||
|
Vector3 r1 = Vector3.Cross(v, a) - t * x;
|
||||||
|
Vector3 r2 = Vector3.Cross(d, u) + s * w;
|
||||||
|
Vector3 r3 = Vector3.Cross(u, c) - s * z;
|
||||||
|
return .(r0.X, r0.Y, r0.Z, -Vector3.Dot(b, t),
|
||||||
|
r1.X, r1.Y, r1.Z, Vector3.Dot(a, t),
|
||||||
|
r2.X, r2.Y, r2.Z, -Vector3.Dot(d, s),
|
||||||
|
r3.X, r3.Y, r3.Z, Vector3.Dot(c, s));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a perspective projection matrix.
|
||||||
|
* @param fovY The vertical field of view.
|
||||||
|
* @param aspectRation The aspect ratio of the viewport.
|
||||||
|
* @param nearPlane The distance to the near plane.
|
||||||
|
* @param farPlane The distance to the far plane.
|
||||||
|
*/
|
||||||
|
public static Matrix PerspectiveProjection(float fovY, float aspectRatio, float nearPlane, float farPlane)
|
||||||
|
{
|
||||||
|
// Lengyel, Eric. Foundations of Game Engine Development, Volume 2: Rendering (Seite82). . Kindle-Version.
|
||||||
|
|
||||||
|
float g = 1.0f / Math.Tan(fovY * 0.5f);
|
||||||
|
float k = farPlane / (farPlane - nearPlane);
|
||||||
|
|
||||||
|
return .(g / aspectRatio, 0, 0, 0,
|
||||||
|
0, g, 0, 0,
|
||||||
|
0, 0, k, -nearPlane * k,
|
||||||
|
0, 0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a perspective projection matrix with reversed near- and far plane.
|
||||||
|
* (i.e. Points on near plane have z-value of 1 and points of far plane have z-value of 0)
|
||||||
|
* @param fovY The vertical field of view.
|
||||||
|
* @param aspectRation The aspect ratio of the viewport.
|
||||||
|
* @param nearPlane The distance to the near plane.
|
||||||
|
* @param farPlane The distance to the far plane.
|
||||||
|
*/
|
||||||
|
public static Matrix ReversedPerspectiveProjection(float fovY, float aspectRatio, float nearPlane, float farPlane)
|
||||||
|
{
|
||||||
|
// Lengyel, Eric. Foundations of Game Engine Development, Volume 2: Rendering (Seite86). . Kindle-Version.
|
||||||
|
|
||||||
|
float g = 1.0f / Math.Tan(fovY * 0.5f);
|
||||||
|
float k = nearPlane / (nearPlane - farPlane);
|
||||||
|
|
||||||
|
return .(g / aspectRatio, 0, 0, 0,
|
||||||
|
0, g, 0, 0,
|
||||||
|
0, 0, k, -farPlane * k,
|
||||||
|
0, 0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a perspective projection matrix with a far plane at infinity.
|
||||||
|
* @param fovY The vertical field of view.
|
||||||
|
* @param aspectRation The aspect ratio of the viewport.
|
||||||
|
* @param nearPlane The distance to the near plane.
|
||||||
|
* @param ε An offset to account for floating point round-off errors at infinity.
|
||||||
|
* Note: Use a tiny value significant compared to the floating-point value of one.
|
||||||
|
*/
|
||||||
|
public static Matrix InfinitePerspectiveProjection(float fovY, float aspectRatio, float nearPlane, float ε = 1e-6f)
|
||||||
|
{
|
||||||
|
// Lengyel, Eric. Foundations of Game Engine Development, Volume 2: Rendering (Seite83). . Kindle-Version.
|
||||||
|
|
||||||
|
float g = 1.0f / Math.Tan(fovY * 0.5f);
|
||||||
|
|
||||||
|
float f = 1 - ε;
|
||||||
|
|
||||||
|
return .(g / aspectRatio, 0, 0, 0,
|
||||||
|
0, g, 0, 0,
|
||||||
|
0, 0, f, -nearPlane * f,
|
||||||
|
0, 0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a perspective projection matrix with a far plane at infinity with reversed near- and far plane.
|
||||||
|
* (i.e. Points on near plane have z-value of 1 and points of far plane have z-value of 0)
|
||||||
|
* @param fovY The vertical field of view.
|
||||||
|
* @param aspectRation The aspect ratio of the viewport.
|
||||||
|
* @param nearPlane The distance to the near plane.
|
||||||
|
* @param ε An offset to account for floating point round-off errors at infinity.
|
||||||
|
* Note: Use a tiny value significant compared to the floating-point value of one.
|
||||||
|
*/
|
||||||
|
public static Matrix ReversedInfinitePerspectiveProjection(float fovY, float aspectRatio, float nearPlane, float ε = 1e-6f)
|
||||||
|
{
|
||||||
|
// Lengyel, Eric. Foundations of Game Engine Development, Volume 2: Rendering (Seite88). . Kindle-Version.
|
||||||
|
|
||||||
|
float g = 1.0f / Math.Tan(fovY * 0.5f);
|
||||||
|
|
||||||
|
return .(g / aspectRatio, 0, 0, 0,
|
||||||
|
0, g, 0, 0,
|
||||||
|
0, 0, ε, nearPlane * (1 - ε),
|
||||||
|
0, 0, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an orthographic projection matrix with the camera centered at the near-plane.
|
||||||
|
* @param width The width of the view volume.
|
||||||
|
* @param height The height of the view volume.
|
||||||
|
* @param depth The depth of the view volume.
|
||||||
|
*/
|
||||||
|
public static Matrix OrthographicProjection(float width, float height, float depth)
|
||||||
|
{
|
||||||
|
// Lengyel, Eric. Foundations of Game Engine Development, Volume 2: Rendering (Seite91). . Kindle-Version.
|
||||||
|
return .(2.0f / width, 0, 0, 0,
|
||||||
|
0, 2.0f/height, 0, 0,
|
||||||
|
0, 0, 1.0f / depth, 0,
|
||||||
|
0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an orthographic projection matrix.
|
||||||
|
* @param left The left side of the view volume.
|
||||||
|
* @param right The right side of the view volume.
|
||||||
|
* @param top The top side of the view volume.
|
||||||
|
* @param bottom The bottom side of the view volume.
|
||||||
|
* @param near The near plane of the view volume.
|
||||||
|
* @param far The far plane of the view volume.
|
||||||
|
*/
|
||||||
|
public static Matrix OrthographicProjectionOffCenter(float left, float right, float top, float bottom, float near, float far)
|
||||||
|
{
|
||||||
|
// Lengyel, Eric. Foundations of Game Engine Development, Volume 2: Rendering (Seite91). . Kindle-Version.
|
||||||
|
|
||||||
|
float w_inv = 1.0f / (right - left);
|
||||||
|
float h_inv = 1.0f / (top - bottom);
|
||||||
|
float d_inv = 1.0f / (far - near);
|
||||||
|
|
||||||
|
return .(2.0f * w_inv, 0.0f, 0.0f, -(right + left) * w_inv,
|
||||||
|
0.0f, 2.0f * h_inv, 0.0f, -(bottom + top) * h_inv,
|
||||||
|
0.0f, 0.0f, d_inv, -near * d_inv,
|
||||||
|
0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(Matrix left, Matrix right)
|
||||||
|
{
|
||||||
|
return Matrix.Equals(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(Matrix left, Matrix right)
|
||||||
|
{
|
||||||
|
return !Matrix.Equals(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Equals(Matrix left, Matrix right)
|
||||||
|
{
|
||||||
|
return left.Values == right.Values;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static explicit operator Matrix3x3(Matrix value)
|
||||||
|
{
|
||||||
|
return .(value.Right, value.Up, value.Forward);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Exponent(ref Matrix matrix, int exponent, out Matrix result)
|
||||||
|
{
|
||||||
|
if(exponent == 0)
|
||||||
|
result = .Identity;
|
||||||
|
else if(exponent == 1)
|
||||||
|
result = matrix;
|
||||||
|
else if(exponent > 1)
|
||||||
|
{
|
||||||
|
result = .Identity;
|
||||||
|
Matrix b = matrix;
|
||||||
|
|
||||||
|
var exponent;
|
||||||
|
|
||||||
|
for(;exponent > 0;)
|
||||||
|
{
|
||||||
|
if(exponent & 1 > 0)
|
||||||
|
result *= b;
|
||||||
|
|
||||||
|
exponent >>= 1;
|
||||||
|
|
||||||
|
if(exponent > 0)
|
||||||
|
b *= b;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else // Exponent < 0
|
||||||
|
{
|
||||||
|
Matrix m = matrix.Invert();
|
||||||
|
Exponent(ref m, -exponent, out result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Orthogonalizes the matrix.
|
||||||
|
*/
|
||||||
|
public void Orthogonalize() mut
|
||||||
|
{
|
||||||
|
Columns[1] -= .Project(Columns[1], Columns[0]);
|
||||||
|
Columns[2] -= .Project(Columns[2], Columns[0]) + .Project(Columns[2], Columns[1]);
|
||||||
|
Columns[3] -= .Project(Columns[3], Columns[0]) + .Project(Columns[3], Columns[1]) + .Project(Columns[3], Columns[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Orthonormalizes the matrix.
|
||||||
|
*/
|
||||||
|
public void Orthonormalize() mut
|
||||||
|
{
|
||||||
|
Columns[0].Normalize();
|
||||||
|
Columns[1] = .Normalize(.Reject(Columns[1], Columns[0]));
|
||||||
|
Columns[2] = .Normalize(.Reject(.Reject(Columns[2], Columns[0]), Columns[1]));
|
||||||
|
Columns[3] = .Normalize(.Reject(.Reject(.Reject(Columns[2], Columns[0]), Columns[1]), Columns[2]));
|
||||||
|
}
|
||||||
|
public static Self RotationQuaternion(Quaternion rotation)
|
||||||
|
{
|
||||||
|
float xSq = 2 * rotation.X * rotation.X;
|
||||||
|
float ySq = 2 * rotation.Y * rotation.Y;
|
||||||
|
float zSq = 2 * rotation.Z * rotation.Z;
|
||||||
|
|
||||||
|
float xy = 2 * rotation.X * rotation.Y;
|
||||||
|
float xz = 2 * rotation.X * rotation.Z;
|
||||||
|
float xw = 2 * rotation.X * rotation.W;
|
||||||
|
float yz = 2 * rotation.Y * rotation.Z;
|
||||||
|
float yw = 2 * rotation.Y * rotation.W;
|
||||||
|
float zw = 2 * rotation.Z * rotation.W;
|
||||||
|
|
||||||
|
Self result = ?;
|
||||||
|
|
||||||
|
result._11 = 1 - ySq - zSq;
|
||||||
|
result._21 = xy + zw;
|
||||||
|
result._31 = xz - yw;
|
||||||
|
result._41 = 0;
|
||||||
|
|
||||||
|
result._12 = xy - zw;
|
||||||
|
result._22 = 1 - xSq - zSq;
|
||||||
|
result._32 = yz + xw;
|
||||||
|
result._42 = 0;
|
||||||
|
|
||||||
|
result._13 = xz + yw;
|
||||||
|
result._23 = yz - xw;
|
||||||
|
result._33 = 1 - xSq - ySq;
|
||||||
|
result._43 = 0;
|
||||||
|
|
||||||
|
result._14 = 0;
|
||||||
|
result._24 = 0;
|
||||||
|
result._34 = 0;
|
||||||
|
result._44 = 1;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Decompose(Self matrix, out Vector3 position, out Quaternion rotation, out Vector3 scale)
|
||||||
|
{
|
||||||
|
var matrix;
|
||||||
|
|
||||||
|
// Translation -> get last column
|
||||||
|
position = matrix.Translation;
|
||||||
|
// Zero translation for next step
|
||||||
|
matrix.Translation = .Zero;
|
||||||
|
|
||||||
|
// TODO: this doesn't detect mirroring
|
||||||
|
|
||||||
|
// Extract scaling from matrix
|
||||||
|
scale.X = (*(Vector3*)&matrix.Columns[0]).Magnitude();
|
||||||
|
scale.Y = (*(Vector3*)&matrix.Columns[1]).Magnitude();
|
||||||
|
scale.Z = (*(Vector3*)&matrix.Columns[2]).Magnitude();
|
||||||
|
|
||||||
|
if(MathHelper.IsZero(scale.X) || MathHelper.IsZero(scale.Y) || MathHelper.IsZero(scale.Z))
|
||||||
|
{
|
||||||
|
rotation = .Identity;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove scale from matrix (normalize the columns)
|
||||||
|
matrix.Columns[0] /= scale.X;
|
||||||
|
matrix.Columns[1] /= scale.Y;
|
||||||
|
matrix.Columns[2] /= scale.Z;
|
||||||
|
|
||||||
|
rotation = Quaternion.FromMatrix(matrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
using System;
|
|
||||||
using GlitchyEngine.Math;
|
|
||||||
using GlitchyEngine;
|
|
||||||
|
|
||||||
namespace DirectX.Math
|
|
||||||
{
|
|
||||||
extension Matrix
|
|
||||||
{
|
|
||||||
typealias Vec3 = GlitchyEngine.Math.Vector3;
|
|
||||||
|
|
||||||
public static Self RotationQuaternion(Quaternion rotation)
|
|
||||||
{
|
|
||||||
float xSq = 2 * rotation.X * rotation.X;
|
|
||||||
float ySq = 2 * rotation.Y * rotation.Y;
|
|
||||||
float zSq = 2 * rotation.Z * rotation.Z;
|
|
||||||
|
|
||||||
float xy = 2 * rotation.X * rotation.Y;
|
|
||||||
float xz = 2 * rotation.X * rotation.Z;
|
|
||||||
float xw = 2 * rotation.X * rotation.W;
|
|
||||||
float yz = 2 * rotation.Y * rotation.Z;
|
|
||||||
float yw = 2 * rotation.Y * rotation.W;
|
|
||||||
float zw = 2 * rotation.Z * rotation.W;
|
|
||||||
|
|
||||||
Self result = ?;
|
|
||||||
|
|
||||||
result.V._11 = 1 - ySq - zSq;
|
|
||||||
result.V._21 = xy + zw;
|
|
||||||
result.V._31 = xz - yw;
|
|
||||||
result.V._41 = 0;
|
|
||||||
|
|
||||||
result.V._12 = xy - zw;
|
|
||||||
result.V._22 = 1 - xSq - zSq;
|
|
||||||
result.V._32 = yz + xw;
|
|
||||||
result.V._42 = 0;
|
|
||||||
|
|
||||||
result.V._13 = xz + yw;
|
|
||||||
result.V._23 = yz - xw;
|
|
||||||
result.V._33 = 1 - xSq - ySq;
|
|
||||||
result.V._43 = 0;
|
|
||||||
|
|
||||||
result.V._14 = 0;
|
|
||||||
result.V._24 = 0;
|
|
||||||
result.V._34 = 0;
|
|
||||||
result.V._44 = 1;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Decompose(Self matrix, out Vec3 position, out Quaternion rotation, out Vec3 scale)
|
|
||||||
{
|
|
||||||
var matrix;
|
|
||||||
|
|
||||||
// Translation -> get last column
|
|
||||||
position = matrix.Translation;
|
|
||||||
// Zero translation for next step
|
|
||||||
matrix.Translation = .Zero;
|
|
||||||
|
|
||||||
// TODO: this doesn't detect mirroring
|
|
||||||
|
|
||||||
// Extract scaling from matrix
|
|
||||||
scale.X = (*(Vec3*)&matrix.Columns[0]).Magnitude();
|
|
||||||
scale.Y = (*(Vec3*)&matrix.Columns[1]).Magnitude();
|
|
||||||
scale.Z = (*(Vec3*)&matrix.Columns[2]).Magnitude();
|
|
||||||
|
|
||||||
if(MathHelper.IsZero(scale.X) || MathHelper.IsZero(scale.Y) || MathHelper.IsZero(scale.Z))
|
|
||||||
{
|
|
||||||
rotation = .Identity;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove scale from matrix (normalize the columns)
|
|
||||||
matrix.Columns[0] /= scale.X;
|
|
||||||
matrix.Columns[1] /= scale.Y;
|
|
||||||
matrix.Columns[2] /= scale.Z;
|
|
||||||
|
|
||||||
rotation = Quaternion.FromMatrix(matrix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*[Test]
|
|
||||||
static void TestQuaternionToMatrix()
|
|
||||||
{
|
|
||||||
// Rotation around Z-Axis by 90°
|
|
||||||
Quaternion quat = .(0, 0, 0.707107f, 0.707107f);
|
|
||||||
quat.Normalize();
|
|
||||||
|
|
||||||
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -144,7 +144,7 @@ namespace GlitchyEngine.Math
|
|||||||
{
|
{
|
||||||
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/
|
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/
|
||||||
|
|
||||||
var m = matrix.V;
|
var m = matrix;
|
||||||
|
|
||||||
Quaternion result = ?;
|
Quaternion result = ?;
|
||||||
|
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
SetBlendState(_nonblendingState);
|
SetBlendState(_nonblendingState);
|
||||||
|
|
||||||
_clearUintFx.Variables["ClearValue"].SetData(value);
|
_clearUintFx.Variables["ClearValue"].SetData(value);
|
||||||
|
_clearUintFx.ApplyChanges();
|
||||||
_clearUintFx.Bind();
|
_clearUintFx.Bind();
|
||||||
|
|
||||||
FullscreenQuad.Draw();
|
FullscreenQuad.Draw();
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
LoadDdsResourcePlatform(stream, ref nativeTexture);
|
LoadDdsResourcePlatform(stream, ref nativeTexture);
|
||||||
|
|
||||||
let resType = nativeTexture.GetResourceType();
|
let resType = nativeTexture.GetResourceType();
|
||||||
Log.EngineLogger.Assert(resType == .Texture2D, scope $"The texture \"{_path}\" is not a 2D texture (it is {resType}).");
|
Log.EngineLogger.Assert(resType == .Texture2D, scope $"The texture is not a 2D texture (it is {resType}).");
|
||||||
|
|
||||||
nativeTexture.GetDescription(out nativeDesc);
|
nativeTexture.GetDescription(out nativeDesc);
|
||||||
}
|
}
|
||||||
@@ -261,13 +261,6 @@ namespace GlitchyEngine.Renderer
|
|||||||
{
|
{
|
||||||
return .(_nativeResourceView, _samplerState?.nativeSamplerState);
|
return .(_nativeResourceView, _samplerState?.nativeSamplerState);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PlatformSneakySwappyTexture(Texture2D otherTexture)
|
|
||||||
{
|
|
||||||
Swap!(nativeDesc, otherTexture.nativeDesc);
|
|
||||||
Swap!(nativeTexture, otherTexture.nativeTexture);
|
|
||||||
Swap!(_nativeResourceView, otherTexture._nativeResourceView);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TextureCube
|
extension TextureCube
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
* @param observerVP The view projection of the rendering camera.
|
* @param observerVP The view projection of the rendering camera.
|
||||||
* @param color The color of the frustum.
|
* @param color The color of the frustum.
|
||||||
*/
|
*/
|
||||||
public static void DrawViewFrustum(Matrix worldTransform, Matrix projection, Matrix observerVP, ColorRGBA color = .Red)
|
public static void DrawViewFrustum(Matrix worldTransform, Matrix projection, ColorRGBA color = .Red)
|
||||||
{
|
{
|
||||||
/*if (_frustumGeometry == null)
|
/*if (_frustumGeometry == null)
|
||||||
{
|
{
|
||||||
@@ -111,15 +111,15 @@ namespace GlitchyEngine.Renderer
|
|||||||
|
|
||||||
Vector4[8] corners;
|
Vector4[8] corners;
|
||||||
// Perspective
|
// Perspective
|
||||||
if(projection.V._43 != 0.0f)
|
if(projection._43 != 0.0f)
|
||||||
{
|
{
|
||||||
// near plane for perspective projection, far plane if reversed
|
// near plane for perspective projection, far plane if reversed
|
||||||
float d1 = -projection.V._34 / projection.V._33;
|
float d1 = -projection._34 / projection._33;
|
||||||
|
|
||||||
float d2 = projection.V._34 / (1.0f - projection.V._33);
|
float d2 = projection._34 / (1.0f - projection._33);
|
||||||
|
|
||||||
float gOverS = projection.V._11;
|
float gOverS = projection._11;
|
||||||
float g = projection.V._22;
|
float g = projection._22;
|
||||||
|
|
||||||
//var corners = //(Vector4*)&_vbFrustum.Data;
|
//var corners = //(Vector4*)&_vbFrustum.Data;
|
||||||
|
|
||||||
@@ -158,14 +158,14 @@ namespace GlitchyEngine.Renderer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float l = -(projection.V._14 + 1.0f) / projection.V._11;
|
float l = -(projection._14 + 1.0f) / projection._11;
|
||||||
float r = (1.0f - projection.V._14) / projection.V._11;
|
float r = (1.0f - projection._14) / projection._11;
|
||||||
|
|
||||||
float t = -(projection.V._24 + 1.0f) / projection.V._22;
|
float t = -(projection._24 + 1.0f) / projection._22;
|
||||||
float b = (1.0f - projection.V._24) / projection.V._22;
|
float b = (1.0f - projection._24) / projection._22;
|
||||||
|
|
||||||
float n = -projection.V._34 / projection.V._33;
|
float n = -projection._34 / projection._33;
|
||||||
float f = (1 - projection.V._34) / projection.V._33;
|
float f = (1 - projection._34) / projection._33;
|
||||||
|
|
||||||
//var corners = (Vector4*)&_vbFrustum.Data;
|
//var corners = (Vector4*)&_vbFrustum.Data;
|
||||||
corners[0] = .(r, t, n, 1.0f);
|
corners[0] = .(r, t, n, 1.0f);
|
||||||
@@ -184,7 +184,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
uint16 index0 = indices[i];
|
uint16 index0 = indices[i];
|
||||||
uint16 index1 = indices[i + 1];
|
uint16 index1 = indices[i + 1];
|
||||||
|
|
||||||
Renderer.DrawLine(corners[index0], corners[index1], color, worldTransform, observerVP);
|
Renderer2D.DrawLine(worldTransform * corners[index0], worldTransform * corners[index1], color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -134,7 +134,20 @@ public class Effect : Asset
|
|||||||
|
|
||||||
BufferVariableCollection _variables ~ delete _;
|
BufferVariableCollection _variables ~ delete _;
|
||||||
|
|
||||||
typealias TextureEntry = (TextureViewBinding BoundTexture, ShaderTextureCollection.ResourceEntry* VsSlot, ShaderTextureCollection.ResourceEntry* PsSlot);
|
public struct TextureEntry
|
||||||
|
{
|
||||||
|
public TextureViewBinding BoundTexture;
|
||||||
|
public ShaderTextureCollection.ResourceEntry* VsSlot;
|
||||||
|
public ShaderTextureCollection.ResourceEntry* PsSlot;
|
||||||
|
|
||||||
|
public this(TextureViewBinding boundTexture, ShaderTextureCollection.ResourceEntry* vsSlot, ShaderTextureCollection.ResourceEntry* psSlot)
|
||||||
|
{
|
||||||
|
BoundTexture = boundTexture;
|
||||||
|
VsSlot = vsSlot;
|
||||||
|
PsSlot = psSlot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Dictionary<String, TextureEntry> _textures ~ delete _;
|
Dictionary<String, TextureEntry> _textures ~ delete _;
|
||||||
|
|
||||||
public Dictionary<String, TextureEntry> Textures => _textures;
|
public Dictionary<String, TextureEntry> Textures => _textures;
|
||||||
@@ -199,6 +212,9 @@ public class Effect : Asset
|
|||||||
{
|
{
|
||||||
Debug.Profiler.ProfileRendererFunction!();
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
|
|
||||||
|
if (texture == null)
|
||||||
|
return;
|
||||||
|
|
||||||
[Inline]InternalSetTexture(name, texture.GetViewBinding());
|
[Inline]InternalSetTexture(name, texture.GetViewBinding());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -725,7 +741,7 @@ public class Effect : Asset
|
|||||||
// Get existing entry or create new
|
// Get existing entry or create new
|
||||||
if(!_textures.TryGetValue(shaderEntry.Name, out entry))
|
if(!_textures.TryGetValue(shaderEntry.Name, out entry))
|
||||||
{
|
{
|
||||||
entry = (shaderEntry.BoundTexture, null, null);
|
entry = .(shaderEntry.BoundTexture, null, null);
|
||||||
entry.BoundTexture.AddRef();
|
entry.BoundTexture.AddRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public class Material : Asset
|
|||||||
|
|
||||||
private uint8[] _rawVariables ~ delete _;
|
private uint8[] _rawVariables ~ delete _;
|
||||||
|
|
||||||
private Dictionary<String, TextureViewBinding> _textures = new .();
|
private Dictionary<String, AssetHandle<Texture>> _textures = new .() ~ delete _;
|
||||||
|
|
||||||
private Dictionary<String, (uint32 Offset, BufferVariable Variable)> _variables = new .() ~ delete _;
|
private Dictionary<String, (uint32 Offset, BufferVariable Variable)> _variables = new .() ~ delete _;
|
||||||
|
|
||||||
@@ -26,26 +26,20 @@ public class Material : Asset
|
|||||||
|
|
||||||
// TODO: get variables from effect
|
// TODO: get variables from effect
|
||||||
|
|
||||||
|
// Get texture slots from effect
|
||||||
for(let (name, entry) in _effect.Textures)
|
for(let (name, entry) in _effect.Textures)
|
||||||
{
|
{
|
||||||
var texture = entry.BoundTexture;
|
// TODO: We need to be able to define default textures in the shader.
|
||||||
texture.AddRef();
|
// At least things like "Black", "White", "Normal"
|
||||||
|
// At best whole paths. Shouldn't be that hard to do...
|
||||||
|
/*var texture = entry.BoundTexture;*/
|
||||||
|
|
||||||
_textures.Add(name, texture);
|
_textures.Add(name, .Invalid);
|
||||||
}
|
}
|
||||||
|
|
||||||
InitRawData();
|
InitRawData();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ~this()
|
|
||||||
{
|
|
||||||
for(let (name, texture) in _textures)
|
|
||||||
{
|
|
||||||
texture.Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
delete _textures;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @brief Initializes the raw data array for the variables.
|
/** @brief Initializes the raw data array for the variables.
|
||||||
*/
|
*/
|
||||||
@@ -88,12 +82,12 @@ public class Material : Asset
|
|||||||
* @param name The name of the texture to set.
|
* @param name The name of the texture to set.
|
||||||
* @param texture The texture to bind to the effect.
|
* @param texture The texture to bind to the effect.
|
||||||
*/
|
*/
|
||||||
public void SetTexture(String name, Texture texture)
|
public void SetTexture(String name, AssetHandle<Texture> texture)
|
||||||
{
|
{
|
||||||
if(_textures.TryGetValue(name, var entry))
|
if(_textures.TryGetValue(name, var entry))
|
||||||
{
|
{
|
||||||
entry.Release();
|
//entry?.ReleaseRef();
|
||||||
_textures[name] = texture.GetViewBinding();
|
_textures[name] = texture;
|
||||||
//texture?.AddRef();
|
//texture?.AddRef();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,27 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using GlitchyEngine.World;
|
using GlitchyEngine.World;
|
||||||
|
using GlitchyEngine.Content;
|
||||||
|
|
||||||
namespace GlitchyEngine.Renderer
|
namespace GlitchyEngine.Renderer
|
||||||
{
|
{
|
||||||
public struct MeshComponent : IDisposableComponent
|
public struct MeshComponent
|
||||||
{
|
{
|
||||||
private GeometryBinding _mesh;
|
public AssetHandle<GeometryBinding> Mesh = .Invalid;
|
||||||
public GeometryBinding Mesh
|
|
||||||
{
|
|
||||||
[Inline]
|
|
||||||
get => _mesh;
|
|
||||||
set mut
|
|
||||||
{
|
|
||||||
if(_mesh == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SetReference!(_mesh, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() mut
|
|
||||||
{
|
|
||||||
ReleaseRefAndNullify!(_mesh);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
{
|
{
|
||||||
_rendererAPI.SetDepthStencilState(depthStencilState, stencilReference);
|
_rendererAPI.SetDepthStencilState(depthStencilState, stencilReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Inline]
|
[Inline]
|
||||||
public static void DrawIndexed(GeometryBinding geometry)
|
public static void DrawIndexed(GeometryBinding geometry)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using GlitchyEngine.Math;
|
|||||||
using GlitchyEngine.World;
|
using GlitchyEngine.World;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System;
|
using System;
|
||||||
|
using GlitchyEngine.Content;
|
||||||
|
|
||||||
namespace GlitchyEngine.Renderer
|
namespace GlitchyEngine.Renderer
|
||||||
{
|
{
|
||||||
@@ -79,13 +80,13 @@ namespace GlitchyEngine.Renderer
|
|||||||
|
|
||||||
static SceneConstants _sceneConstants;
|
static SceneConstants _sceneConstants;
|
||||||
|
|
||||||
static Effect LineEffect;
|
//static AssetHandle<Effect> LineEffect;
|
||||||
static VertexBuffer LineVertices;
|
static VertexBuffer LineVertices;
|
||||||
static GeometryBinding LineGeometry;
|
static GeometryBinding LineGeometry;
|
||||||
|
|
||||||
static GBuffer _gBuffer;
|
static GBuffer _gBuffer;
|
||||||
static Effect TestFullscreenEffect;
|
static AssetHandle<Effect> TestFullscreenEffect;
|
||||||
static Effect s_tonemappingEffect;
|
static AssetHandle<Effect> s_tonemappingEffect;
|
||||||
|
|
||||||
static BlendState _gBufferBlend;
|
static BlendState _gBufferBlend;
|
||||||
static BlendState _lightBlend;
|
static BlendState _lightBlend;
|
||||||
@@ -132,7 +133,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
{
|
{
|
||||||
Debug.Profiler.ProfileFunction!();
|
Debug.Profiler.ProfileFunction!();
|
||||||
|
|
||||||
LineEffect = Content.LoadAsset<Effect>("Shaders\\lineShader.hlsl");
|
//LineEffect = Content.LoadAsset("Shaders\\lineShader.hlsl");
|
||||||
|
|
||||||
LineGeometry = new GeometryBinding();
|
LineGeometry = new GeometryBinding();
|
||||||
LineGeometry.SetPrimitiveTopology(.LineList);
|
LineGeometry.SetPrimitiveTopology(.LineList);
|
||||||
@@ -158,13 +159,12 @@ namespace GlitchyEngine.Renderer
|
|||||||
{
|
{
|
||||||
LineVertices.ReleaseRef();
|
LineVertices.ReleaseRef();
|
||||||
LineGeometry.ReleaseRef();
|
LineGeometry.ReleaseRef();
|
||||||
LineEffect.ReleaseRef();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void InitDeferredRenderer()
|
static void InitDeferredRenderer()
|
||||||
{
|
{
|
||||||
TestFullscreenEffect = Content.LoadAsset<Effect>("Shaders\\simpleLight.hlsl");
|
TestFullscreenEffect = Content.LoadAsset("Shaders\\simpleLight.hlsl");
|
||||||
s_tonemappingEffect = Content.LoadAsset<Effect>("Shaders\\SimpleTonemapping.hlsl");
|
s_tonemappingEffect = Content.LoadAsset("Shaders\\SimpleTonemapping.hlsl");
|
||||||
|
|
||||||
_gBuffer = new GBuffer();
|
_gBuffer = new GBuffer();
|
||||||
BlendStateDescription gBufferBlendDesc = .Default;
|
BlendStateDescription gBufferBlendDesc = .Default;
|
||||||
@@ -203,9 +203,6 @@ namespace GlitchyEngine.Renderer
|
|||||||
_lightBlend.ReleaseRef();
|
_lightBlend.ReleaseRef();
|
||||||
_gBufferBlend.ReleaseRef();
|
_gBufferBlend.ReleaseRef();
|
||||||
delete _gBuffer;
|
delete _gBuffer;
|
||||||
|
|
||||||
s_tonemappingEffect.ReleaseRef();
|
|
||||||
TestFullscreenEffect.ReleaseRef();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// [Obsolete("", false)]
|
// [Obsolete("", false)]
|
||||||
@@ -346,22 +343,23 @@ namespace GlitchyEngine.Renderer
|
|||||||
|
|
||||||
Vector3 lightDir = -light.Transform.Forward;
|
Vector3 lightDir = -light.Transform.Forward;
|
||||||
|
|
||||||
TestFullscreenEffect.SetTexture("GBuffer_Albedo", _gBuffer.Target, 0);
|
Effect fsEffect = TestFullscreenEffect.Get();
|
||||||
TestFullscreenEffect.SetTexture("GBuffer_Normal", _gBuffer.Target, 1);
|
fsEffect.SetTexture("GBuffer_Albedo", _gBuffer.Target, 0);
|
||||||
TestFullscreenEffect.SetTexture("GBuffer_Tangent", _gBuffer.Target, 2);
|
fsEffect.SetTexture("GBuffer_Normal", _gBuffer.Target, 1);
|
||||||
TestFullscreenEffect.SetTexture("GBuffer_Position", _gBuffer.Target, 3);
|
fsEffect.SetTexture("GBuffer_Tangent", _gBuffer.Target, 2);
|
||||||
TestFullscreenEffect.SetTexture("GBuffer_Material", _gBuffer.Target, 4);
|
fsEffect.SetTexture("GBuffer_Position", _gBuffer.Target, 3);
|
||||||
|
fsEffect.SetTexture("GBuffer_Material", _gBuffer.Target, 4);
|
||||||
|
|
||||||
TestFullscreenEffect.Variables["LightColor"].SetData(light.Light.Color);
|
fsEffect.Variables["LightColor"].SetData(light.Light.Color);
|
||||||
TestFullscreenEffect.Variables["Illuminance"].SetData(light.Light.Illuminance);
|
fsEffect.Variables["Illuminance"].SetData(light.Light.Illuminance);
|
||||||
TestFullscreenEffect.Variables["LightDir"].SetData(lightDir);
|
fsEffect.Variables["LightDir"].SetData(lightDir);
|
||||||
|
|
||||||
TestFullscreenEffect.Variables["CameraPos"].SetData(_sceneConstants.CameraPosition);
|
fsEffect.Variables["CameraPos"].SetData(_sceneConstants.CameraPosition);
|
||||||
|
|
||||||
TestFullscreenEffect.Variables["Scaling"].SetData(scaling);
|
fsEffect.Variables["Scaling"].SetData(scaling);
|
||||||
|
|
||||||
TestFullscreenEffect.ApplyChanges();
|
fsEffect.ApplyChanges();
|
||||||
TestFullscreenEffect.Bind();
|
fsEffect.Bind();
|
||||||
|
|
||||||
//RenderCommand.BindEffect(TestFullscreenEffect);
|
//RenderCommand.BindEffect(TestFullscreenEffect);
|
||||||
|
|
||||||
@@ -378,11 +376,12 @@ namespace GlitchyEngine.Renderer
|
|||||||
RenderCommand.UnbindRenderTargets();
|
RenderCommand.UnbindRenderTargets();
|
||||||
RenderCommand.BindRenderTargets();
|
RenderCommand.BindRenderTargets();
|
||||||
RenderCommand.SetRenderTargetGroup(_sceneConstants.CompositionTarget, true);
|
RenderCommand.SetRenderTargetGroup(_sceneConstants.CompositionTarget, true);
|
||||||
|
|
||||||
|
Effect toneMappingFx = s_tonemappingEffect.Get();
|
||||||
// TODO: Postprocessing effects
|
// TODO: Postprocessing effects
|
||||||
s_tonemappingEffect.SetTexture("CameraTarget", _sceneConstants.CameraTarget, 0);
|
toneMappingFx.SetTexture("CameraTarget", _sceneConstants.CameraTarget, 0);
|
||||||
s_tonemappingEffect.ApplyChanges();
|
toneMappingFx.ApplyChanges();
|
||||||
s_tonemappingEffect.Bind();
|
toneMappingFx.Bind();
|
||||||
|
|
||||||
RenderCommand.BindRenderTargets();
|
RenderCommand.BindRenderTargets();
|
||||||
//RenderCommand.BindEffect(s_tonemappingEffect);
|
//RenderCommand.BindEffect(s_tonemappingEffect);
|
||||||
@@ -470,6 +469,9 @@ namespace GlitchyEngine.Renderer
|
|||||||
{
|
{
|
||||||
Debug.Profiler.ProfileRendererFunction!();
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
|
|
||||||
|
if (geometry == null || material == null)
|
||||||
|
return;
|
||||||
|
|
||||||
_queue.Add(SubmittedMesh(geometry, material, transform, entity.[Friend]Index));
|
_queue.Add(SubmittedMesh(geometry, material, transform, entity.[Friend]Index));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,9 +487,10 @@ namespace GlitchyEngine.Renderer
|
|||||||
* @param end The end point of the line.
|
* @param end The end point of the line.
|
||||||
* @param color The color of the line.
|
* @param color The color of the line.
|
||||||
*/
|
*/
|
||||||
public static void DrawLine(Vector3 start, Vector3 end, Color color)
|
public static void DrawLine(Vector3 start, Vector3 end, ColorRGBA color)
|
||||||
{
|
{
|
||||||
DrawLine(Vector4(start, 1.0f), Vector4(end, 1.0f), (ColorRGBA)color, .Identity);
|
Renderer2D.DrawLine(start, end, color);
|
||||||
|
//DrawLine(Vector4(start, 1.0f), Vector4(end, 1.0f), (ColorRGBA)color, .Identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Draws a line.
|
/** @brief Draws a line.
|
||||||
@@ -498,7 +501,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
*/
|
*/
|
||||||
public static void DrawLine(Vector3 start, Vector3 end, ColorRGBA color, Matrix transform)
|
public static void DrawLine(Vector3 start, Vector3 end, ColorRGBA color, Matrix transform)
|
||||||
{
|
{
|
||||||
DrawLine(Vector4(start, 1.0f), Vector4(end, 1.0f), color, transform);
|
Renderer2D.DrawLine(transform * Vector4(start, 1.0f), transform * Vector4(end, 1.0f), color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Draws a ray.
|
/** @brief Draws a ray.
|
||||||
@@ -508,7 +511,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
*/
|
*/
|
||||||
public static void DrawRay(Vector3 start, Vector3 direction, ColorRGBA color)
|
public static void DrawRay(Vector3 start, Vector3 direction, ColorRGBA color)
|
||||||
{
|
{
|
||||||
DrawLine(Vector4(start, 1.0f), Vector4(direction, 0.0f), color, .Identity);
|
Renderer2D.DrawRay(start, direction, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Draws a ray.
|
/** @brief Draws a ray.
|
||||||
@@ -519,50 +522,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
*/
|
*/
|
||||||
public static void DrawRay(Vector3 start, Vector3 direction, ColorRGBA color, Matrix transform)
|
public static void DrawRay(Vector3 start, Vector3 direction, ColorRGBA color, Matrix transform)
|
||||||
{
|
{
|
||||||
DrawLine(Vector4(start, 1.0f), Vector4(direction, 0.0f), color, transform);
|
Renderer2D.DrawLine(transform * Vector4(start, 1.0f), transform * Vector4(direction, 0.0f), color);
|
||||||
}
|
|
||||||
|
|
||||||
/** @brief Draws a line.
|
|
||||||
* @param start The start point of the line.
|
|
||||||
* @param end The end point of the line.
|
|
||||||
* @param color The color of the line.
|
|
||||||
* @param transform A transform matrix transforming the line.
|
|
||||||
*/
|
|
||||||
public static void DrawLine(Vector4 start, Vector4 end, ColorRGBA color, Matrix transform)
|
|
||||||
{
|
|
||||||
Debug.Profiler.ProfileRendererFunction!();
|
|
||||||
|
|
||||||
LineVertices.SetData(Vector4[2](start, end), 0, .WriteDiscard);
|
|
||||||
LineEffect.Variables["ViewProjection"].SetData(_sceneConstants.ViewProjection * transform);
|
|
||||||
LineEffect.Variables["Color"].SetData(color);
|
|
||||||
|
|
||||||
LineEffect.ApplyChanges();
|
|
||||||
LineEffect.Bind();
|
|
||||||
|
|
||||||
LineGeometry.Bind();
|
|
||||||
RenderCommand.DrawIndexed(LineGeometry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @brief Draws a line.
|
|
||||||
* @param start The start point of the line.
|
|
||||||
* @param end The end point of the line.
|
|
||||||
* @param color The color of the line.
|
|
||||||
* @param transform A transform matrix transforming the line.
|
|
||||||
* @param viewProjection The observing cameras viewprojection
|
|
||||||
*/
|
|
||||||
public static void DrawLine(Vector4 start, Vector4 end, ColorRGBA color, Matrix transform, Matrix viewProjection)
|
|
||||||
{
|
|
||||||
Debug.Profiler.ProfileRendererFunction!();
|
|
||||||
|
|
||||||
LineVertices.SetData(Vector4[2](start, end), 0, .WriteDiscard);
|
|
||||||
LineEffect.Variables["ViewProjection"].SetData(viewProjection * transform);
|
|
||||||
LineEffect.Variables["Color"].SetData(color);
|
|
||||||
|
|
||||||
LineEffect.ApplyChanges();
|
|
||||||
LineEffect.Bind();
|
|
||||||
|
|
||||||
LineGeometry.Bind();
|
|
||||||
RenderCommand.DrawIndexed(LineGeometry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,9 +42,25 @@ namespace GlitchyEngine.Renderer
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CRepr]
|
||||||
|
struct LineBatchVertex
|
||||||
|
{
|
||||||
|
public Vector4 Position;
|
||||||
|
public ColorRGBA Color;
|
||||||
|
|
||||||
|
public uint32 EntityId;
|
||||||
|
|
||||||
|
public this(Vector4 position, ColorRGBA color, uint32 entityId)
|
||||||
|
{
|
||||||
|
Position = position;
|
||||||
|
Color = color;
|
||||||
|
EntityId = entityId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[CRepr]
|
[CRepr]
|
||||||
struct BatchVertex
|
struct QuadBatchVertex
|
||||||
{
|
{
|
||||||
public Matrix Transform;
|
public Matrix Transform;
|
||||||
public ColorRGBA Color;
|
public ColorRGBA Color;
|
||||||
@@ -62,7 +78,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
[CRepr]
|
[CRepr]
|
||||||
struct CircleBatchVertex : BatchVertex
|
struct CircleBatchVertex : QuadBatchVertex
|
||||||
{
|
{
|
||||||
public float InnerRadius;
|
public float InnerRadius;
|
||||||
|
|
||||||
@@ -93,6 +109,8 @@ namespace GlitchyEngine.Renderer
|
|||||||
*/
|
*/
|
||||||
FrontToBack
|
FrontToBack
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct QueueLine: this(Vector4 Start, Vector4 End, ColorRGBA Color, float Depth, uint32 entityId = uint32.MaxValue) { }
|
||||||
|
|
||||||
struct QueueQuad: this(Matrix Transform, ColorRGBA Color, Texture Texture, float Depth, Vector4 uvTransform, uint32 entityId = uint32.MaxValue) { }
|
struct QueueQuad: this(Matrix Transform, ColorRGBA Color, Texture Texture, float Depth, Vector4 uvTransform, uint32 entityId = uint32.MaxValue) { }
|
||||||
|
|
||||||
@@ -112,32 +130,40 @@ namespace GlitchyEngine.Renderer
|
|||||||
private static bool s_sceneRunning;
|
private static bool s_sceneRunning;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private static Effect s_batchEffect;
|
private static Effect s_quadBatchEffect;
|
||||||
private static Effect s_circleBatchEffect;
|
private static Effect s_circleBatchEffect;
|
||||||
|
private static Effect s_lineBatchEffect;
|
||||||
|
|
||||||
private static GeometryBinding s_quadGeometry;
|
private static GeometryBinding s_quadGeometry;
|
||||||
|
|
||||||
private static Texture2D s_whiteTexture;
|
private static Texture2D s_whiteTexture;
|
||||||
|
|
||||||
private static GeometryBinding s_quadBatchBinding;
|
private static GeometryBinding s_quadBatchBinding;
|
||||||
private static GeometryBinding s_circleBatchBinding;
|
private static GeometryBinding s_circleBatchBinding;
|
||||||
|
private static GeometryBinding s_lineBatchBinding;
|
||||||
private static VertexBuffer s_quadInstanceBuffer;
|
private static VertexBuffer s_quadInstanceBuffer;
|
||||||
private static VertexBuffer s_circleInstanceBuffer;
|
private static VertexBuffer s_circleInstanceBuffer;
|
||||||
|
private static VertexBuffer s_lineInstanceBuffer;
|
||||||
|
|
||||||
private static uint32 s_maxInstancesPerBatch = 8192;
|
private static uint32 s_maxInstancesPerBatch = 8192;
|
||||||
|
|
||||||
private static BatchVertex[] s_rawQuadInstances;
|
private static QuadBatchVertex[] s_rawQuadInstances;
|
||||||
private static CircleBatchVertex[] s_rawCircleInstances;
|
private static CircleBatchVertex[] s_rawCircleInstances;
|
||||||
private static uint32 s_setInstances = 0;
|
private static LineBatchVertex[] s_rawLineVertices;
|
||||||
|
private static uint32 s_setQuadInstances = 0;
|
||||||
|
private static uint32 s_setCircleInstances = 0;
|
||||||
|
private static uint32 s_setLineInstances = 0;
|
||||||
|
|
||||||
private static List<QueueQuad> s_QuadinstanceQueue;
|
private static List<QueueQuad> s_QuadinstanceQueue;
|
||||||
private static List<QueueCircle> s_circleInstanceQueue;
|
private static List<QueueCircle> s_circleInstanceQueue;
|
||||||
|
private static List<QueueLine> s_lineInstanceQueue;
|
||||||
|
|
||||||
private static DrawOrder s_drawOrder;
|
private static DrawOrder s_drawOrder;
|
||||||
|
|
||||||
/// The effect that is currently used to draw the sprites.
|
/// The effect that is currently used to draw the sprites.
|
||||||
private static Effect s_currentEffect;
|
private static Effect s_currentQuadEffect;
|
||||||
private static Effect s_currentCircleEffect;
|
private static Effect s_currentCircleEffect;
|
||||||
|
private static Effect s_currentLineEffect;
|
||||||
|
|
||||||
public static uint32 MaxInstancesPerBatch
|
public static uint32 MaxInstancesPerBatch
|
||||||
{
|
{
|
||||||
@@ -157,8 +183,9 @@ namespace GlitchyEngine.Renderer
|
|||||||
{
|
{
|
||||||
Debug.Profiler.ProfileFunction!();
|
Debug.Profiler.ProfileFunction!();
|
||||||
|
|
||||||
s_batchEffect = new Effect("content\\Shaders\\spritebatch.hlsl");
|
s_quadBatchEffect = new Effect("content\\Shaders\\spritebatch.hlsl");
|
||||||
s_circleBatchEffect = new Effect("content\\Shaders\\circlebatch.hlsl");
|
s_circleBatchEffect = new Effect("content\\Shaders\\circlebatch.hlsl");
|
||||||
|
s_lineBatchEffect = new Effect("content\\Shaders\\linebatch.hlsl");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void InitGeometry()
|
private static void InitGeometry()
|
||||||
@@ -252,6 +279,23 @@ namespace GlitchyEngine.Renderer
|
|||||||
s_circleBatchBinding.SetIndexBuffer(s_quadGeometry.GetIndexBuffer(), 0);
|
s_circleBatchBinding.SetIndexBuffer(s_quadGeometry.GetIndexBuffer(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Line
|
||||||
|
{
|
||||||
|
VertexElement[] vertexElements = new .(
|
||||||
|
VertexElement(.R32G32B32A32_Float, "POSITION", false, 0, 0, 0, .PerVertexData, 0),
|
||||||
|
VertexElement(.R32G32B32A32_Float, "COLOR", false, 0, 0, (.)-1, .PerVertexData, 0),
|
||||||
|
VertexElement(.R32_UInt, "ENTITYID", false, 0, 0, (.)-1, .PerVertexData, 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
s_lineBatchBinding = new GeometryBinding();
|
||||||
|
s_lineBatchBinding.SetPrimitiveTopology(.LineList);
|
||||||
|
|
||||||
|
using (var lineBatchLayout = new VertexLayout(vertexElements, true))
|
||||||
|
{
|
||||||
|
s_lineBatchBinding.SetVertexLayout(lineBatchLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ApplyInstanceCount();
|
ApplyInstanceCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,7 +306,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
|
|
||||||
// Quads
|
// Quads
|
||||||
{
|
{
|
||||||
VertexBuffer quadInstanceBuffer = new VertexBuffer(typeof(BatchVertex), s_maxInstancesPerBatch, .Dynamic, .Write);
|
VertexBuffer quadInstanceBuffer = new VertexBuffer(typeof(QuadBatchVertex), s_maxInstancesPerBatch, .Dynamic, .Write);
|
||||||
quadInstanceBuffer.SetData(0);
|
quadInstanceBuffer.SetData(0);
|
||||||
|
|
||||||
s_quadInstanceBuffer?.ReleaseRef();
|
s_quadInstanceBuffer?.ReleaseRef();
|
||||||
@@ -271,7 +315,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
|
|
||||||
delete s_rawQuadInstances;
|
delete s_rawQuadInstances;
|
||||||
delete s_QuadinstanceQueue;
|
delete s_QuadinstanceQueue;
|
||||||
s_rawQuadInstances = new BatchVertex[s_maxInstancesPerBatch];
|
s_rawQuadInstances = new QuadBatchVertex[s_maxInstancesPerBatch];
|
||||||
s_QuadinstanceQueue = new List<QueueQuad>(s_maxInstancesPerBatch);
|
s_QuadinstanceQueue = new List<QueueQuad>(s_maxInstancesPerBatch);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -290,6 +334,21 @@ namespace GlitchyEngine.Renderer
|
|||||||
s_rawCircleInstances = new CircleBatchVertex[s_maxInstancesPerBatch];
|
s_rawCircleInstances = new CircleBatchVertex[s_maxInstancesPerBatch];
|
||||||
s_circleInstanceQueue = new List<QueueCircle>(s_maxInstancesPerBatch);
|
s_circleInstanceQueue = new List<QueueCircle>(s_maxInstancesPerBatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lines
|
||||||
|
{
|
||||||
|
VertexBuffer lineInstanceBuffer = new VertexBuffer(typeof(LineBatchVertex), s_maxInstancesPerBatch, .Dynamic, .Write);
|
||||||
|
lineInstanceBuffer.SetData(0);
|
||||||
|
|
||||||
|
s_lineInstanceBuffer?.ReleaseRef();
|
||||||
|
s_lineInstanceBuffer = lineInstanceBuffer;
|
||||||
|
s_lineBatchBinding.SetVertexBufferSlot(s_lineInstanceBuffer, 0);
|
||||||
|
|
||||||
|
delete s_rawLineVertices;
|
||||||
|
delete s_lineInstanceQueue;
|
||||||
|
s_rawLineVertices = new LineBatchVertex[s_maxInstancesPerBatch];
|
||||||
|
s_lineInstanceQueue = new List<QueueLine>(s_maxInstancesPerBatch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void InitWhitetexture()
|
private static void InitWhitetexture()
|
||||||
@@ -366,8 +425,9 @@ namespace GlitchyEngine.Renderer
|
|||||||
|
|
||||||
FontRenderer.Deinit();
|
FontRenderer.Deinit();
|
||||||
|
|
||||||
s_batchEffect.ReleaseRef();
|
s_quadBatchEffect.ReleaseRef();
|
||||||
s_circleBatchEffect.ReleaseRef();
|
s_circleBatchEffect.ReleaseRef();
|
||||||
|
s_lineBatchEffect.ReleaseRef();
|
||||||
|
|
||||||
s_quadGeometry.ReleaseRef();
|
s_quadGeometry.ReleaseRef();
|
||||||
|
|
||||||
@@ -375,16 +435,21 @@ namespace GlitchyEngine.Renderer
|
|||||||
|
|
||||||
s_quadBatchBinding.ReleaseRef();
|
s_quadBatchBinding.ReleaseRef();
|
||||||
s_circleBatchBinding.ReleaseRef();
|
s_circleBatchBinding.ReleaseRef();
|
||||||
|
s_lineBatchBinding.ReleaseRef();
|
||||||
s_quadInstanceBuffer.ReleaseRef();
|
s_quadInstanceBuffer.ReleaseRef();
|
||||||
s_circleInstanceBuffer.ReleaseRef();
|
s_circleInstanceBuffer.ReleaseRef();
|
||||||
|
s_lineInstanceBuffer.ReleaseRef();
|
||||||
|
|
||||||
delete s_rawQuadInstances;
|
delete s_rawQuadInstances;
|
||||||
delete s_rawCircleInstances;
|
delete s_rawCircleInstances;
|
||||||
|
delete s_rawLineVertices;
|
||||||
delete s_QuadinstanceQueue;
|
delete s_QuadinstanceQueue;
|
||||||
delete s_circleInstanceQueue;
|
delete s_circleInstanceQueue;
|
||||||
|
delete s_lineInstanceQueue;
|
||||||
|
|
||||||
s_currentEffect?.ReleaseRef();
|
s_currentQuadEffect?.ReleaseRef();
|
||||||
s_currentCircleEffect?.ReleaseRef();
|
s_currentCircleEffect?.ReleaseRef();
|
||||||
|
s_currentLineEffect?.ReleaseRef();
|
||||||
|
|
||||||
s_opaqueBlendState.ReleaseRef();
|
s_opaqueBlendState.ReleaseRef();
|
||||||
s_transparentBlendState.ReleaseRef();
|
s_transparentBlendState.ReleaseRef();
|
||||||
@@ -405,14 +470,14 @@ namespace GlitchyEngine.Renderer
|
|||||||
|
|
||||||
//s_textureColorEffect.Bind(Renderer._context);
|
//s_textureColorEffect.Bind(Renderer._context);
|
||||||
|
|
||||||
s_currentEffect?.ReleaseRef();
|
s_currentQuadEffect?.ReleaseRef();
|
||||||
if(effect != null)
|
if(effect != null)
|
||||||
{
|
{
|
||||||
s_currentEffect = effect..AddRef();
|
s_currentQuadEffect = effect..AddRef();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s_currentEffect = s_batchEffect..AddRef();
|
s_currentQuadEffect = s_quadBatchEffect..AddRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
s_currentCircleEffect?.ReleaseRef();
|
s_currentCircleEffect?.ReleaseRef();
|
||||||
@@ -425,7 +490,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
s_currentCircleEffect = s_circleBatchEffect..AddRef();
|
s_currentCircleEffect = s_circleBatchEffect..AddRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
s_currentEffect.Variables["ViewProjection"].SetData(camera.ViewProjection);
|
s_currentQuadEffect.Variables["ViewProjection"].SetData(camera.ViewProjection);
|
||||||
s_currentCircleEffect.Variables["ViewProjection"].SetData(camera.ViewProjection);
|
s_currentCircleEffect.Variables["ViewProjection"].SetData(camera.ViewProjection);
|
||||||
|
|
||||||
s_drawOrder = drawOrder;
|
s_drawOrder = drawOrder;
|
||||||
@@ -445,14 +510,14 @@ namespace GlitchyEngine.Renderer
|
|||||||
|
|
||||||
//s_textureColorEffect.Bind(Renderer._context);
|
//s_textureColorEffect.Bind(Renderer._context);
|
||||||
|
|
||||||
s_currentEffect?.ReleaseRef();
|
s_currentQuadEffect?.ReleaseRef();
|
||||||
if(effect != null)
|
if(effect != null)
|
||||||
{
|
{
|
||||||
s_currentEffect = effect..AddRef();
|
s_currentQuadEffect = effect..AddRef();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s_currentEffect = s_batchEffect..AddRef();
|
s_currentQuadEffect = s_quadBatchEffect..AddRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
s_currentCircleEffect?.ReleaseRef();
|
s_currentCircleEffect?.ReleaseRef();
|
||||||
@@ -464,11 +529,22 @@ namespace GlitchyEngine.Renderer
|
|||||||
{
|
{
|
||||||
s_currentCircleEffect = s_circleBatchEffect..AddRef();
|
s_currentCircleEffect = s_circleBatchEffect..AddRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_currentLineEffect?.ReleaseRef();
|
||||||
|
/*if(circleEffect != null)
|
||||||
|
{
|
||||||
|
s_currentLineEffect = effect..AddRef();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{*/
|
||||||
|
s_currentLineEffect = s_lineBatchEffect..AddRef();
|
||||||
|
//}
|
||||||
|
|
||||||
Matrix viewProjection = camera.Projection * Matrix.Invert(transform);
|
Matrix viewProjection = camera.Projection * Matrix.Invert(transform);
|
||||||
|
|
||||||
s_currentEffect.Variables["ViewProjection"].SetData(viewProjection);
|
s_currentQuadEffect.Variables["ViewProjection"].SetData(viewProjection);
|
||||||
s_currentCircleEffect.Variables["ViewProjection"].SetData(viewProjection);
|
s_currentCircleEffect.Variables["ViewProjection"].SetData(viewProjection);
|
||||||
|
s_currentLineEffect.Variables["ViewProjection"].SetData(viewProjection);
|
||||||
|
|
||||||
s_drawOrder = drawOrder;
|
s_drawOrder = drawOrder;
|
||||||
|
|
||||||
@@ -487,14 +563,14 @@ namespace GlitchyEngine.Renderer
|
|||||||
|
|
||||||
//s_textureColorEffect.Bind(Renderer._context);
|
//s_textureColorEffect.Bind(Renderer._context);
|
||||||
|
|
||||||
s_currentEffect?.ReleaseRef();
|
s_currentQuadEffect?.ReleaseRef();
|
||||||
if(effect != null)
|
if(effect != null)
|
||||||
{
|
{
|
||||||
s_currentEffect = effect..AddRef();
|
s_currentQuadEffect = effect..AddRef();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s_currentEffect = s_batchEffect..AddRef();
|
s_currentQuadEffect = s_quadBatchEffect..AddRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
s_currentCircleEffect?.ReleaseRef();
|
s_currentCircleEffect?.ReleaseRef();
|
||||||
@@ -506,11 +582,22 @@ namespace GlitchyEngine.Renderer
|
|||||||
{
|
{
|
||||||
s_currentCircleEffect = s_circleBatchEffect..AddRef();
|
s_currentCircleEffect = s_circleBatchEffect..AddRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_currentLineEffect?.ReleaseRef();
|
||||||
|
/*if(circleEffect != null)
|
||||||
|
{
|
||||||
|
s_currentLineEffect = effect..AddRef();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{*/
|
||||||
|
s_currentLineEffect = s_lineBatchEffect..AddRef();
|
||||||
|
//}
|
||||||
|
|
||||||
Matrix viewProjection = camera.Projection * camera.View;
|
Matrix viewProjection = camera.Projection * camera.View;
|
||||||
|
|
||||||
s_currentEffect.Variables["ViewProjection"].SetData(viewProjection);
|
s_currentQuadEffect.Variables["ViewProjection"].SetData(viewProjection);
|
||||||
s_currentCircleEffect.Variables["ViewProjection"].SetData(viewProjection);
|
s_currentCircleEffect.Variables["ViewProjection"].SetData(viewProjection);
|
||||||
|
s_currentLineEffect.Variables["ViewProjection"].SetData(viewProjection);
|
||||||
|
|
||||||
s_drawOrder = drawOrder;
|
s_drawOrder = drawOrder;
|
||||||
|
|
||||||
@@ -558,23 +645,31 @@ namespace GlitchyEngine.Renderer
|
|||||||
s_circleInstanceQueue.Add(QueueCircle(transform, color, texture ?? s_whiteTexture, depth, uvTransform, innerRadius, id));
|
s_circleInstanceQueue.Add(QueueCircle(transform, color, texture ?? s_whiteTexture, depth, uvTransform, innerRadius, id));
|
||||||
s_statistics.CircleCount++;
|
s_statistics.CircleCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void FlushInstances()
|
/// Adds a line instance to the instance queue.
|
||||||
|
[Inline]
|
||||||
|
private static void QueueLineInstance(Vector4 start, Vector4 end, ColorRGBA color, uint32 id = uint32.MaxValue)
|
||||||
|
{
|
||||||
|
s_lineInstanceQueue.Add(QueueLine(start, end, color, id));
|
||||||
|
s_statistics.LineCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FlushQuadInstances()
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileRendererFunction!();
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
|
|
||||||
if(s_setInstances == 0)
|
if(s_setQuadInstances == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
s_quadInstanceBuffer.SetData<BatchVertex>(s_rawQuadInstances.Ptr, s_setInstances, 0, .WriteDiscard);
|
s_quadInstanceBuffer.SetData<QuadBatchVertex>(s_rawQuadInstances.Ptr, s_setQuadInstances, 0, .WriteDiscard);
|
||||||
|
|
||||||
s_currentEffect.ApplyChanges();
|
s_currentQuadEffect.ApplyChanges();
|
||||||
s_currentEffect.Bind();
|
s_currentQuadEffect.Bind();
|
||||||
s_quadBatchBinding.InstanceCount = s_setInstances;
|
s_quadBatchBinding.InstanceCount = s_setQuadInstances;
|
||||||
s_quadBatchBinding.Bind();
|
s_quadBatchBinding.Bind();
|
||||||
RenderCommand.DrawIndexedInstanced(s_quadBatchBinding);
|
RenderCommand.DrawIndexedInstanced(s_quadBatchBinding);
|
||||||
|
|
||||||
s_setInstances = 0;
|
s_setQuadInstances = 0;
|
||||||
|
|
||||||
s_statistics.QuadDrawCalls++;
|
s_statistics.QuadDrawCalls++;
|
||||||
}
|
}
|
||||||
@@ -583,21 +678,41 @@ namespace GlitchyEngine.Renderer
|
|||||||
{
|
{
|
||||||
Debug.Profiler.ProfileRendererFunction!();
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
|
|
||||||
if(s_setInstances == 0)
|
if(s_setCircleInstances == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
s_circleInstanceBuffer.SetData<CircleBatchVertex>(s_rawCircleInstances.Ptr, s_setInstances, 0, .WriteDiscard);
|
s_circleInstanceBuffer.SetData<CircleBatchVertex>(s_rawCircleInstances.Ptr, s_setCircleInstances, 0, .WriteDiscard);
|
||||||
|
|
||||||
s_currentCircleEffect.ApplyChanges();
|
s_currentCircleEffect.ApplyChanges();
|
||||||
s_currentCircleEffect.Bind();
|
s_currentCircleEffect.Bind();
|
||||||
s_circleBatchBinding.InstanceCount = s_setInstances;
|
s_circleBatchBinding.InstanceCount = s_setCircleInstances;
|
||||||
s_circleBatchBinding.Bind();
|
s_circleBatchBinding.Bind();
|
||||||
RenderCommand.DrawIndexedInstanced(s_circleBatchBinding);
|
RenderCommand.DrawIndexedInstanced(s_circleBatchBinding);
|
||||||
|
|
||||||
s_setInstances = 0;
|
s_setCircleInstances = 0;
|
||||||
|
|
||||||
s_statistics.CircleDrawCalls++;
|
s_statistics.CircleDrawCalls++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void FlushLineInstances()
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
|
|
||||||
|
if(s_setLineInstances == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
s_lineInstanceBuffer.SetData<LineBatchVertex>(s_rawLineVertices.Ptr, s_setLineInstances, 0, .WriteDiscard);
|
||||||
|
|
||||||
|
s_currentLineEffect.ApplyChanges();
|
||||||
|
s_currentLineEffect.Bind();
|
||||||
|
s_lineBatchBinding.VertexCount = (.)s_setLineInstances;
|
||||||
|
s_lineBatchBinding.Bind();
|
||||||
|
RenderCommand.DrawIndexed(s_lineBatchBinding);
|
||||||
|
|
||||||
|
s_setLineInstances = 0;
|
||||||
|
|
||||||
|
s_statistics.LineDrawCalls++;
|
||||||
|
}
|
||||||
|
|
||||||
// Quad comparison
|
// Quad comparison
|
||||||
private static int TextureComparison(QueueQuad lhs, QueueQuad rhs)
|
private static int TextureComparison(QueueQuad lhs, QueueQuad rhs)
|
||||||
@@ -627,6 +742,20 @@ namespace GlitchyEngine.Renderer
|
|||||||
return lhs.Depth <=> rhs.Depth;
|
return lhs.Depth <=> rhs.Depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Line comparison
|
||||||
|
/*private static int TextureComparison(QueueLine lhs, QueueLine rhs)
|
||||||
|
{
|
||||||
|
return (int)Internal.UnsafeCastToPtr(lhs.Texture) - (int)Internal.UnsafeCastToPtr(rhs.Texture);
|
||||||
|
}*/
|
||||||
|
private static int BackToFrontComparison(QueueLine lhs, QueueLine rhs)
|
||||||
|
{
|
||||||
|
return rhs.Depth <=> lhs.Depth;
|
||||||
|
}
|
||||||
|
private static int FrontToBackComparison(QueueLine lhs, QueueLine rhs)
|
||||||
|
{
|
||||||
|
return lhs.Depth <=> rhs.Depth;
|
||||||
|
}
|
||||||
|
|
||||||
private static void SortInstances()
|
private static void SortInstances()
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileRendererFunction!();
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
@@ -636,12 +765,16 @@ namespace GlitchyEngine.Renderer
|
|||||||
case .SortByTexture:
|
case .SortByTexture:
|
||||||
s_QuadinstanceQueue.Sort(scope => TextureComparison);
|
s_QuadinstanceQueue.Sort(scope => TextureComparison);
|
||||||
s_circleInstanceQueue.Sort(scope => TextureComparison);
|
s_circleInstanceQueue.Sort(scope => TextureComparison);
|
||||||
|
/*Lines cant be sorted by texture*/
|
||||||
|
s_lineInstanceQueue.Sort(scope => BackToFrontComparison);
|
||||||
case .BackToFront:
|
case .BackToFront:
|
||||||
s_QuadinstanceQueue.Sort(scope => BackToFrontComparison);
|
s_QuadinstanceQueue.Sort(scope => BackToFrontComparison);
|
||||||
s_circleInstanceQueue.Sort(scope => BackToFrontComparison);
|
s_circleInstanceQueue.Sort(scope => BackToFrontComparison);
|
||||||
|
s_lineInstanceQueue.Sort(scope => BackToFrontComparison);
|
||||||
case .FrontToBack:
|
case .FrontToBack:
|
||||||
s_QuadinstanceQueue.Sort(scope => FrontToBackComparison);
|
s_QuadinstanceQueue.Sort(scope => FrontToBackComparison);
|
||||||
s_circleInstanceQueue.Sort(scope => FrontToBackComparison);
|
s_circleInstanceQueue.Sort(scope => FrontToBackComparison);
|
||||||
|
s_lineInstanceQueue.Sort(scope => FrontToBackComparison);
|
||||||
case .Immediate:
|
case .Immediate:
|
||||||
default:
|
default:
|
||||||
Log.EngineLogger.Error("Unknown instance draw order.");
|
Log.EngineLogger.Error("Unknown instance draw order.");
|
||||||
@@ -652,13 +785,14 @@ namespace GlitchyEngine.Renderer
|
|||||||
{
|
{
|
||||||
Debug.Profiler.ProfileRendererFunction!();
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
|
|
||||||
if(s_QuadinstanceQueue.IsEmpty && s_circleInstanceQueue.IsEmpty)
|
if(s_QuadinstanceQueue.IsEmpty && s_circleInstanceQueue.IsEmpty && s_lineInstanceQueue.IsEmpty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SortInstances();
|
SortInstances();
|
||||||
|
|
||||||
DrawDeferredQuads();
|
DrawDeferredQuads();
|
||||||
DrawDeferredCircles();
|
DrawDeferredCircles();
|
||||||
|
DrawDeferredLines();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DrawDeferredQuads()
|
private static void DrawDeferredQuads()
|
||||||
@@ -672,9 +806,9 @@ namespace GlitchyEngine.Renderer
|
|||||||
RenderCommand.SetBlendState(s_transparentBlendState);
|
RenderCommand.SetBlendState(s_transparentBlendState);
|
||||||
|
|
||||||
Texture texture = s_QuadinstanceQueue[0].Texture;
|
Texture texture = s_QuadinstanceQueue[0].Texture;
|
||||||
s_currentEffect.SetTexture("Texture", texture);
|
s_currentQuadEffect.SetTexture("Texture", texture);
|
||||||
|
|
||||||
s_setInstances = 0;
|
s_setQuadInstances = 0;
|
||||||
|
|
||||||
for(int i < s_QuadinstanceQueue.Count)
|
for(int i < s_QuadinstanceQueue.Count)
|
||||||
{
|
{
|
||||||
@@ -683,21 +817,21 @@ namespace GlitchyEngine.Renderer
|
|||||||
// flush every time the texture changes
|
// flush every time the texture changes
|
||||||
if(quad.Texture != texture)
|
if(quad.Texture != texture)
|
||||||
{
|
{
|
||||||
FlushInstances();
|
FlushQuadInstances();
|
||||||
|
|
||||||
texture = quad.Texture;
|
texture = quad.Texture;
|
||||||
s_currentEffect.SetTexture("Texture", texture);
|
s_currentQuadEffect.SetTexture("Texture", texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
s_rawQuadInstances[s_setInstances++] = .(quad.Transform, quad.Color, quad.uvTransform, quad.entityId);
|
s_rawQuadInstances[s_setQuadInstances++] = .(quad.Transform, quad.Color, quad.uvTransform, quad.entityId);
|
||||||
|
|
||||||
if(s_setInstances == s_rawQuadInstances.Count)
|
if(s_setQuadInstances == s_rawQuadInstances.Count)
|
||||||
{
|
{
|
||||||
FlushInstances();
|
FlushQuadInstances();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FlushInstances();
|
FlushQuadInstances();
|
||||||
|
|
||||||
s_QuadinstanceQueue.Clear();
|
s_QuadinstanceQueue.Clear();
|
||||||
}
|
}
|
||||||
@@ -715,7 +849,7 @@ namespace GlitchyEngine.Renderer
|
|||||||
Texture texture = s_circleInstanceQueue[0].Texture;
|
Texture texture = s_circleInstanceQueue[0].Texture;
|
||||||
s_currentCircleEffect.SetTexture("Texture", texture);
|
s_currentCircleEffect.SetTexture("Texture", texture);
|
||||||
|
|
||||||
s_setInstances = 0;
|
s_setCircleInstances = 0;
|
||||||
|
|
||||||
for(int i < s_circleInstanceQueue.Count)
|
for(int i < s_circleInstanceQueue.Count)
|
||||||
{
|
{
|
||||||
@@ -730,9 +864,9 @@ namespace GlitchyEngine.Renderer
|
|||||||
s_currentCircleEffect.SetTexture("Texture", texture);
|
s_currentCircleEffect.SetTexture("Texture", texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
s_rawCircleInstances[s_setInstances++] = .(circle.Transform, circle.Color, circle.uvTransform, circle.InnerRadius, circle.entityId);
|
s_rawCircleInstances[s_setCircleInstances++] = .(circle.Transform, circle.Color, circle.uvTransform, circle.InnerRadius, circle.entityId);
|
||||||
|
|
||||||
if(s_setInstances == s_rawCircleInstances.Count)
|
if(s_setCircleInstances == s_rawCircleInstances.Count)
|
||||||
{
|
{
|
||||||
FlushCircleInstances();
|
FlushCircleInstances();
|
||||||
}
|
}
|
||||||
@@ -743,6 +877,36 @@ namespace GlitchyEngine.Renderer
|
|||||||
s_circleInstanceQueue.Clear();
|
s_circleInstanceQueue.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void DrawDeferredLines()
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
|
|
||||||
|
if(s_lineInstanceQueue.IsEmpty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// TODO: per object blendstate
|
||||||
|
RenderCommand.SetBlendState(s_transparentBlendState);
|
||||||
|
|
||||||
|
s_setLineInstances = 0;
|
||||||
|
|
||||||
|
for(int i < s_lineInstanceQueue.Count)
|
||||||
|
{
|
||||||
|
let line = ref s_lineInstanceQueue[i];
|
||||||
|
|
||||||
|
s_rawLineVertices[s_setLineInstances++] = .(line.Start, line.Color, line.entityId);
|
||||||
|
s_rawLineVertices[s_setLineInstances++] = .(line.End, line.Color, line.entityId);
|
||||||
|
|
||||||
|
if(s_setLineInstances == s_rawLineVertices.Count)
|
||||||
|
{
|
||||||
|
FlushLineInstances();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FlushLineInstances();
|
||||||
|
|
||||||
|
s_lineInstanceQueue.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
/// A specialized function that calculates the 2D transform matrix
|
/// A specialized function that calculates the 2D transform matrix
|
||||||
private static Matrix Calculate2DTransform(Vector3 translation, Vector2 scale, float rotation)
|
private static Matrix Calculate2DTransform(Vector3 translation, Vector2 scale, float rotation)
|
||||||
{
|
{
|
||||||
@@ -762,6 +926,85 @@ namespace GlitchyEngine.Renderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Primitives
|
// Primitives
|
||||||
|
|
||||||
|
/** @brief Draws a line.
|
||||||
|
* @param start The start point of the line.
|
||||||
|
* @param end The end point of the line.
|
||||||
|
* @param color The color of the line.
|
||||||
|
* @param entityId The optional ID of the entity that belongs to this line (for picking).
|
||||||
|
*/
|
||||||
|
public static void DrawLine(Vector3 start, Vector3 end, ColorRGBA color = .White, uint32 entityId = uint32.MaxValue)
|
||||||
|
{
|
||||||
|
DrawLine(Vector4(start, 1.0f), Vector4(end, 1.0f), color, entityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Draws a ray.
|
||||||
|
* @param start The start point of the ray.
|
||||||
|
* @param direction The direction of the ray.
|
||||||
|
* @param color The color of the ray.
|
||||||
|
* @param entityId The optional ID of the entity that belongs to this ray (for picking).
|
||||||
|
*/
|
||||||
|
public static void DrawRay(Vector3 start, Vector3 direction, ColorRGBA color = .White, uint32 entityId = uint32.MaxValue)
|
||||||
|
{
|
||||||
|
DrawLine(Vector4(start, 1.0f), Vector4(direction, 0.0f), color, entityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Draws a rectangle.
|
||||||
|
* @param position The center of the rectangle.
|
||||||
|
* @param size The size of the rectangle.
|
||||||
|
* @param color The color of the rectangle.
|
||||||
|
* @param entityId The optional ID of the entity that belongs to this rectangle (for picking).
|
||||||
|
*/
|
||||||
|
public static void DrawRect(Vector2 position, Vector2 size, ColorRGBA color = .White, uint32 entityId = uint32.MaxValue)
|
||||||
|
{
|
||||||
|
Vector2 halfSize = size / 2;
|
||||||
|
|
||||||
|
Vector4 p0 = Vector4(position + Vector2(-halfSize.X, -halfSize.Y), 0.0f, 1.0f);
|
||||||
|
Vector4 p1 = Vector4(position + Vector2(halfSize.X, -halfSize.Y), 0.0f, 1.0f);
|
||||||
|
Vector4 p2 = Vector4(position + Vector2(halfSize.X, halfSize.Y), 0.0f, 1.0f);
|
||||||
|
Vector4 p3 = Vector4(position + Vector2(-halfSize.X, halfSize.Y), 0.0f, 1.0f);
|
||||||
|
|
||||||
|
DrawLine(p0, p1, color, entityId);
|
||||||
|
DrawLine(p1, p2, color, entityId);
|
||||||
|
DrawLine(p2, p3, color, entityId);
|
||||||
|
DrawLine(p3, p0, color, entityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Draws a rectangle.
|
||||||
|
* @param transform The transform of the rectangle.
|
||||||
|
* @param color The color of the rectangle.
|
||||||
|
* @param entityId The optional ID of the entity that belongs to this rectangle (for picking).
|
||||||
|
*/
|
||||||
|
public static void DrawRect(Matrix transform, ColorRGBA color = .White, uint32 entityId = uint32.MaxValue)
|
||||||
|
{
|
||||||
|
Vector2 halfSize = Vector2.One / 2.0f;
|
||||||
|
|
||||||
|
Vector4 p0 = transform * Vector4(-halfSize.X, -halfSize.Y, 0.0f, 1.0f);
|
||||||
|
Vector4 p1 = transform * Vector4(halfSize.X, -halfSize.Y, 0.0f, 1.0f);
|
||||||
|
Vector4 p2 = transform * Vector4(halfSize.X, halfSize.Y, 0.0f, 1.0f);
|
||||||
|
Vector4 p3 = transform * Vector4(-halfSize.X, halfSize.Y, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
DrawLine(p0, p1, color, entityId);
|
||||||
|
DrawLine(p1, p2, color, entityId);
|
||||||
|
DrawLine(p2, p3, color, entityId);
|
||||||
|
DrawLine(p3, p0, color, entityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DrawLine(Vector4 start, Vector4 end, ColorRGBA color = .White, uint32 entityId = uint32.MaxValue)
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
Log.EngineLogger.AssertDebug(s_sceneRunning, "Missing call of BeginScene.");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QueueLineInstance(start, end, color, entityId);
|
||||||
|
|
||||||
|
if(s_drawOrder == .Immediate)
|
||||||
|
{
|
||||||
|
DrawDeferred();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Colored Quad
|
// Colored Quad
|
||||||
|
|
||||||
@@ -873,12 +1116,14 @@ namespace GlitchyEngine.Renderer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawSprite(Matrix transform, SpriterRendererComponent* spriteRenderer, uint32 entityId)
|
public static void DrawSprite(Matrix transform, SpriteRendererComponent* spriteRenderer, uint32 entityId)
|
||||||
{
|
{
|
||||||
if (spriteRenderer.IsCircle)
|
DrawQuad(transform, spriteRenderer.Sprite.Get() ?? s_whiteTexture, spriteRenderer.Color, spriteRenderer.UvTransform, entityId);
|
||||||
DrawCircle(transform, spriteRenderer.Sprite ?? s_whiteTexture, spriteRenderer.Color, 1.0f, spriteRenderer.UvTransform, entityId);
|
}
|
||||||
else
|
|
||||||
DrawQuad(transform, spriteRenderer.Sprite ?? s_whiteTexture, spriteRenderer.Color, spriteRenderer.UvTransform, entityId);
|
public static void DrawCircle(Matrix transform, CircleRendererComponent* spriteRenderer, uint32 entityId)
|
||||||
|
{
|
||||||
|
DrawCircle(transform, spriteRenderer.Sprite.Get() ?? s_whiteTexture, spriteRenderer.Color, spriteRenderer.InnerRadius, spriteRenderer.UvTransform, entityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Textured quad pivot
|
// Textured quad pivot
|
||||||
@@ -937,21 +1182,26 @@ namespace GlitchyEngine.Renderer
|
|||||||
{
|
{
|
||||||
public uint32 QuadDrawCalls = 0;
|
public uint32 QuadDrawCalls = 0;
|
||||||
public uint32 CircleDrawCalls = 0;
|
public uint32 CircleDrawCalls = 0;
|
||||||
|
public uint32 LineDrawCalls = 0;
|
||||||
|
|
||||||
public uint32 QuadCount = 0;
|
public uint32 QuadCount = 0;
|
||||||
public uint32 CircleCount = 0;
|
public uint32 CircleCount = 0;
|
||||||
|
public uint32 LineCount = 0;
|
||||||
|
|
||||||
public uint32 TotalDrawCalls => QuadDrawCalls + CircleDrawCalls;
|
public uint32 TotalDrawCalls => QuadDrawCalls + CircleDrawCalls + LineDrawCalls;
|
||||||
public uint32 TotalInstanceCount => QuadCount + CircleCount;
|
public uint32 TotalInstanceCount => QuadCount + CircleCount + LineCount;
|
||||||
public uint32 TotalVertexCount => TotalInstanceCount * 4;
|
public uint32 TotalVertexCount => (QuadCount + CircleCount) * 4 + LineCount * 2;
|
||||||
public uint32 TotalTriangleCount => TotalInstanceCount * 2;
|
public uint32 TotalTriangleCount => (QuadCount + CircleCount) * 2;
|
||||||
public uint32 TotalIndexCount => TotalInstanceCount * 6;
|
public uint32 TotalIndexCount => (QuadCount + CircleCount) * 6;
|
||||||
|
|
||||||
public void Reset() mut
|
public void Reset() mut
|
||||||
{
|
{
|
||||||
QuadDrawCalls = 0;
|
QuadDrawCalls = 0;
|
||||||
CircleDrawCalls = 0;
|
CircleDrawCalls = 0;
|
||||||
|
LineDrawCalls = 0;
|
||||||
QuadCount = 0;
|
QuadCount = 0;
|
||||||
CircleCount = 0;
|
CircleCount = 0;
|
||||||
|
LineCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -333,8 +333,8 @@ namespace GlitchyEngine.Renderer.Text
|
|||||||
Renderer2D.Flush();
|
Renderer2D.Flush();
|
||||||
|
|
||||||
// TODO: this is very not good!
|
// TODO: this is very not good!
|
||||||
var lastEffect = Renderer2D.[Friend]s_currentEffect;
|
var lastEffect = Renderer2D.[Friend]s_currentQuadEffect;
|
||||||
Renderer2D.[Friend]s_currentEffect = _msdfEffect..AddRef();
|
Renderer2D.[Friend]s_currentQuadEffect = _msdfEffect..AddRef();
|
||||||
// TODO: oh no....
|
// TODO: oh no....
|
||||||
// Copy viewProjection from current effect
|
// Copy viewProjection from current effect
|
||||||
Matrix viewProjection = lastEffect.Variables["ViewProjection"].[Friend]GetData<Matrix>();
|
Matrix viewProjection = lastEffect.Variables["ViewProjection"].[Friend]GetData<Matrix>();
|
||||||
@@ -410,7 +410,7 @@ namespace GlitchyEngine.Renderer.Text
|
|||||||
// TODO: not good!
|
// TODO: not good!
|
||||||
// Change back effect
|
// Change back effect
|
||||||
_msdfEffect.ReleaseRef();
|
_msdfEffect.ReleaseRef();
|
||||||
Renderer2D.[Friend]s_currentEffect = lastEffect;
|
Renderer2D.[Friend]s_currentQuadEffect = lastEffect;
|
||||||
|
|
||||||
// release all atlas textures
|
// release all atlas textures
|
||||||
for(int i < atlasses.Count)
|
for(int i < atlasses.Count)
|
||||||
@@ -439,8 +439,8 @@ namespace GlitchyEngine.Renderer.Text
|
|||||||
Renderer2D.Flush();
|
Renderer2D.Flush();
|
||||||
|
|
||||||
// TODO: this is very not good!
|
// TODO: this is very not good!
|
||||||
var lastEffect = Renderer2D.[Friend]s_currentEffect;
|
var lastEffect = Renderer2D.[Friend]s_currentQuadEffect;
|
||||||
Renderer2D.[Friend]s_currentEffect = _msdfEffect..AddRef();
|
Renderer2D.[Friend]s_currentQuadEffect = _msdfEffect..AddRef();
|
||||||
// TODO: oh no....
|
// TODO: oh no....
|
||||||
// Copy viewProjection from current effect
|
// Copy viewProjection from current effect
|
||||||
Matrix viewProjection = lastEffect.Variables["ViewProjection"].[Friend]GetData<Matrix>();
|
Matrix viewProjection = lastEffect.Variables["ViewProjection"].[Friend]GetData<Matrix>();
|
||||||
@@ -664,7 +664,7 @@ namespace GlitchyEngine.Renderer.Text
|
|||||||
// TODO: not good!
|
// TODO: not good!
|
||||||
// Change back effect
|
// Change back effect
|
||||||
_msdfEffect.ReleaseRef();
|
_msdfEffect.ReleaseRef();
|
||||||
Renderer2D.[Friend]s_currentEffect = lastEffect;
|
Renderer2D.[Friend]s_currentQuadEffect = lastEffect;
|
||||||
|
|
||||||
// release all atlas textures
|
// release all atlas textures
|
||||||
for(int i < atlasses.Count)
|
for(int i < atlasses.Count)
|
||||||
|
|||||||
@@ -63,19 +63,11 @@ namespace GlitchyEngine.Renderer
|
|||||||
|
|
||||||
public class Texture2D : Texture
|
public class Texture2D : Texture
|
||||||
{
|
{
|
||||||
protected String _path ~ delete _;
|
|
||||||
|
|
||||||
//public override extern uint32 Width {get;}
|
//public override extern uint32 Width {get;}
|
||||||
//public override extern uint32 Height {get;}
|
//public override extern uint32 Height {get;}
|
||||||
public override uint32 Depth => 1;
|
public override uint32 Depth => 1;
|
||||||
//public override extern uint32 ArraySize {get;}
|
//public override extern uint32 ArraySize {get;}
|
||||||
//public override extern uint32 MipLevels {get;}
|
//public override extern uint32 MipLevels {get;}
|
||||||
|
|
||||||
private this(StringView path, bool pngSrgb = false)
|
|
||||||
{
|
|
||||||
_path = new String(path);
|
|
||||||
LoadTexture(pngSrgb);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: remove
|
// TODO: remove
|
||||||
private this(Stream data)
|
private this(Stream data)
|
||||||
@@ -83,72 +75,6 @@ namespace GlitchyEngine.Renderer
|
|||||||
LoadDds(data);
|
LoadDds(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
const String PngMagicWord = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A";
|
|
||||||
const String DdsMagicWord = "DDS ";
|
|
||||||
|
|
||||||
private void LoadTexture(bool pngSrgb)
|
|
||||||
{
|
|
||||||
Debug.Profiler.ProfileResourceFunction!();
|
|
||||||
|
|
||||||
Stream data = Application.Get().ContentManager.GetStream(_path);
|
|
||||||
defer delete data;
|
|
||||||
|
|
||||||
var readResult = data.Read<char8[8]>();
|
|
||||||
|
|
||||||
data.Position = 0;
|
|
||||||
|
|
||||||
char8[8] magicWord;
|
|
||||||
|
|
||||||
if (readResult case .Ok(out magicWord))
|
|
||||||
{
|
|
||||||
StringView strView = .(&magicWord, magicWord.Count);
|
|
||||||
|
|
||||||
if (strView.StartsWith(PngMagicWord))
|
|
||||||
{
|
|
||||||
LoadPng(data, pngSrgb);
|
|
||||||
}
|
|
||||||
else if (strView.StartsWith(DdsMagicWord))
|
|
||||||
{
|
|
||||||
LoadDds(data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Runtime.FatalError("Unknown image format.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void LoadPng(Stream stream, bool srgb)
|
|
||||||
{
|
|
||||||
Debug.Profiler.ProfileResourceFunction!();
|
|
||||||
|
|
||||||
uint8[] pngData = new:ScopedAlloc! uint8[stream.Length];
|
|
||||||
|
|
||||||
var result = stream.TryRead(pngData);
|
|
||||||
|
|
||||||
if (result case .Err(let err))
|
|
||||||
{
|
|
||||||
Log.EngineLogger.Error($"Failed to read data from stream. Texture: \"{_path}\", Error: {err}");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8* rawData = ?;
|
|
||||||
uint32 width = 0, height = 0;
|
|
||||||
|
|
||||||
uint32 errorCode = LodePng.LodePng.Decode32(&rawData, &width, &height, pngData.Ptr, (.)pngData.Count);
|
|
||||||
|
|
||||||
Debug.Assert(errorCode == 0, "Failed to load png File");
|
|
||||||
|
|
||||||
// TODO: load as SRGB because PNGs are usually not stored as linear
|
|
||||||
//Texture2DDesc desc = .(width, height, .R8G8B8A8_UNorm_SRGB, 1, 1, .Immutable);
|
|
||||||
Texture2DDesc desc = .(width, height, srgb? .R8G8B8A8_UNorm_SRGB : .R8G8B8A8_UNorm, 1, 1, .Immutable);
|
|
||||||
|
|
||||||
PrepareTexturePlatform(desc, false);
|
|
||||||
|
|
||||||
SetData<Color>((.)rawData);
|
|
||||||
|
|
||||||
LodePng.LodePng.Free(rawData);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void LoadDds(Stream stream)
|
protected void LoadDds(Stream stream)
|
||||||
{
|
{
|
||||||
LoadDdsPlatform(stream);
|
LoadDdsPlatform(stream);
|
||||||
|
|||||||
+21
-19
@@ -3,6 +3,7 @@ using GlitchyEngine.Math;
|
|||||||
using GlitchyEngine.Renderer;
|
using GlitchyEngine.Renderer;
|
||||||
using GlitchyEngine.Core;
|
using GlitchyEngine.Core;
|
||||||
using Box2D;
|
using Box2D;
|
||||||
|
using GlitchyEngine.Content;
|
||||||
|
|
||||||
namespace GlitchyEngine.World
|
namespace GlitchyEngine.World
|
||||||
{
|
{
|
||||||
@@ -21,7 +22,7 @@ namespace GlitchyEngine.World
|
|||||||
{
|
{
|
||||||
public readonly UUID ID;
|
public readonly UUID ID;
|
||||||
|
|
||||||
/// Create aa new IDComponent with a random UUID.
|
/// Create a new IDComponent with a random UUID.
|
||||||
public this()
|
public this()
|
||||||
{
|
{
|
||||||
ID = UUID();
|
ID = UUID();
|
||||||
@@ -44,27 +45,13 @@ namespace GlitchyEngine.World
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Component("Sprite Renderer")]
|
[Component("Sprite Renderer")]
|
||||||
struct SpriterRendererComponent : IDisposableComponent
|
struct SpriteRendererComponent
|
||||||
{
|
{
|
||||||
private Texture2D _sprite = null;
|
public AssetHandle<Texture2D> Sprite = .Invalid;
|
||||||
|
|
||||||
public Texture2D Sprite
|
|
||||||
{
|
|
||||||
get => _sprite;
|
|
||||||
set mut
|
|
||||||
{
|
|
||||||
if (_sprite == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SetReference!(_sprite, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ColorRGBA Color = .White;
|
public ColorRGBA Color = .White;
|
||||||
public Vector4 UvTransform = .(0, 0, 1, 1);
|
public Vector4 UvTransform = .(0, 0, 1, 1);
|
||||||
|
|
||||||
public bool IsCircle = false;
|
|
||||||
|
|
||||||
public this()
|
public this()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -73,10 +60,25 @@ namespace GlitchyEngine.World
|
|||||||
{
|
{
|
||||||
Color = color;
|
Color = color;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
[Component("Circle Renderer")]
|
||||||
|
struct CircleRendererComponent
|
||||||
|
{
|
||||||
|
public AssetHandle<Texture2D> Sprite = .Invalid;
|
||||||
|
|
||||||
|
public ColorRGBA Color = .White;
|
||||||
|
public Vector4 UvTransform = .(0, 0, 1, 1);
|
||||||
|
|
||||||
|
public float InnerRadius = 0.0f;
|
||||||
|
|
||||||
|
public this()
|
||||||
{
|
{
|
||||||
_sprite?.ReleaseRef();
|
}
|
||||||
|
|
||||||
|
public this(ColorRGBA color)
|
||||||
|
{
|
||||||
|
Color = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using GlitchyEngine.Renderer;
|
||||||
|
using System;
|
||||||
|
using GlitchyEngine.Content;
|
||||||
|
|
||||||
|
namespace GlitchyEngine.World
|
||||||
|
{
|
||||||
|
/// A component that allows to render a mesh.
|
||||||
|
public struct MeshRendererComponent
|
||||||
|
{
|
||||||
|
public AssetHandle<Material> Material = .Invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
namespace GlitchyEngine.World
|
||||||
|
{
|
||||||
|
struct NameComponent : IDisposableComponent
|
||||||
|
{
|
||||||
|
private String _name;
|
||||||
|
|
||||||
|
public StringView Name
|
||||||
|
{
|
||||||
|
get => _name;
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
if (_name == null)
|
||||||
|
_name = new String(value);
|
||||||
|
else
|
||||||
|
_name.Set(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() mut
|
||||||
|
{
|
||||||
|
DeleteAndNullify!(_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
@@ -20,6 +20,7 @@ namespace GlitchyEngine.World
|
|||||||
/// The frame when the transform was recalculated
|
/// The frame when the transform was recalculated
|
||||||
public uint Frame;
|
public uint Frame;
|
||||||
|
|
||||||
|
// TODO: probably use UUID
|
||||||
public EcsEntity Parent
|
public EcsEntity Parent
|
||||||
{
|
{
|
||||||
get => _parent;
|
get => _parent;
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
using System;
|
|
||||||
namespace GlitchyEngine.World
|
|
||||||
{
|
|
||||||
struct DebugNameComponent : IDisposableComponent
|
|
||||||
{
|
|
||||||
private String _debugName;
|
|
||||||
|
|
||||||
public String DebugName
|
|
||||||
{
|
|
||||||
get => _debugName;
|
|
||||||
set mut => SetName(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetName(StringView name) mut
|
|
||||||
{
|
|
||||||
delete _debugName;
|
|
||||||
|
|
||||||
_debugName = new String(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() mut
|
|
||||||
{
|
|
||||||
DeleteAndNullify!(_debugName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -66,6 +66,12 @@ namespace GlitchyEngine.World
|
|||||||
|
|
||||||
public UUID UUID => GetComponent<IDComponent>().ID;
|
public UUID UUID => GetComponent<IDComponent>().ID;
|
||||||
|
|
||||||
|
public StringView Name
|
||||||
|
{
|
||||||
|
get => GetComponent<NameComponent>().Name;
|
||||||
|
set => GetComponent<NameComponent>().Name = value;
|
||||||
|
}
|
||||||
|
|
||||||
public TransformComponent* Transform => GetComponent<TransformComponent>();
|
public TransformComponent* Transform => GetComponent<TransformComponent>();
|
||||||
|
|
||||||
public T* AddComponent<T>(T value = T()) where T: struct, new
|
public T* AddComponent<T>(T value = T()) where T: struct, new
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
using GlitchyEngine.Renderer;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace GlitchyEngine.World
|
|
||||||
{
|
|
||||||
/// A component that allows to render a mesh.
|
|
||||||
public struct MeshRendererComponent : IDisposableComponent
|
|
||||||
{
|
|
||||||
private Material _material;
|
|
||||||
|
|
||||||
public Material Material
|
|
||||||
{
|
|
||||||
[Inline]
|
|
||||||
get => _material;
|
|
||||||
set mut
|
|
||||||
{
|
|
||||||
if(_material == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_material?.ReleaseRef();
|
|
||||||
_material = value;
|
|
||||||
_material?.AddRef();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() mut
|
|
||||||
{
|
|
||||||
_material?.ReleaseRef();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace GlitchyEngine.World
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* A Component that allows to specify a parent entity.
|
|
||||||
*/
|
|
||||||
public struct ParentComponent
|
|
||||||
{
|
|
||||||
public EcsEntity Entity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+144
-364
@@ -11,7 +11,7 @@ namespace GlitchyEngine.World
|
|||||||
using internal ScriptableEntity;
|
using internal ScriptableEntity;
|
||||||
using internal GlitchyEngine.World;
|
using internal GlitchyEngine.World;
|
||||||
|
|
||||||
class Scene
|
class Scene : RefCounter
|
||||||
{
|
{
|
||||||
internal EcsWorld _ecsWorld = new .() ~ delete _;
|
internal EcsWorld _ecsWorld = new .() ~ delete _;
|
||||||
|
|
||||||
@@ -19,12 +19,7 @@ namespace GlitchyEngine.World
|
|||||||
|
|
||||||
private Dictionary<Type, function void(Entity entity, Type componentType, void* component)> _onComponentAddedHandlers = new .() ~ delete _;
|
private Dictionary<Type, function void(Entity entity, Type componentType, void* component)> _onComponentAddedHandlers = new .() ~ delete _;
|
||||||
|
|
||||||
private RenderTargetGroup _compositeTarget ~ _.ReleaseRef();
|
private uint32 _viewportWidth, _viewportHeight;
|
||||||
|
|
||||||
// Temporary target for camera. Needs to change as soon as we support multiple cameras
|
|
||||||
private RenderTargetGroup _cameraTarget ~ _.ReleaseRef();
|
|
||||||
|
|
||||||
private Effect _gammaCorrectEffect ~ _.ReleaseRef();
|
|
||||||
|
|
||||||
// Maps ids to the entities they represent.
|
// Maps ids to the entities they represent.
|
||||||
private Dictionary<UUID, EcsEntity> _idToEntity = new .() ~ delete _;
|
private Dictionary<UUID, EcsEntity> _idToEntity = new .() ~ delete _;
|
||||||
@@ -45,43 +40,71 @@ namespace GlitchyEngine.World
|
|||||||
|
|
||||||
public this()
|
public this()
|
||||||
{
|
{
|
||||||
/*Entity entity = CreateEntity("Green Quad");
|
|
||||||
entity.AddComponent<SpriterRendererComponent>(.(ColorRGBA.SRgbToLinear(.(0.2f, 0.9f, 0.15f))));
|
|
||||||
|
|
||||||
Entity entity2 = CreateEntity("Red Square");
|
|
||||||
var v = entity2.AddComponent<SpriterRendererComponent>(.(ColorRGBA.SRgbToLinear(.(0.95f, 0.1f, 0.3f))));
|
|
||||||
v.Sprite = new Texture2D("Textures/rocket.dds");
|
|
||||||
v.Sprite.SamplerState = SamplerStateManager.PointClamp;*/
|
|
||||||
|
|
||||||
_onComponentAddedHandlers.Add(typeof(CameraComponent), (e, t, c) => {
|
_onComponentAddedHandlers.Add(typeof(CameraComponent), (e, t, c) => {
|
||||||
CameraComponent* cameraComponent = (.)c;
|
CameraComponent* cameraComponent = (.)c;
|
||||||
|
|
||||||
cameraComponent.Camera.SetViewportSize(e.Scene.ViewportWidth, e.Scene.ViewportHeight);
|
cameraComponent.Camera.SetViewportSize(e.Scene._viewportWidth, e.Scene._viewportHeight);
|
||||||
});
|
});
|
||||||
|
|
||||||
RenderTargetGroupDescription desc = .(100, 100,
|
|
||||||
TargetDescription[](
|
|
||||||
RenderTargetFormat.R16G16B16A16_Float,
|
|
||||||
.(RenderTargetFormat.R32_UInt) {ClearColor = .UInt(uint32.MaxValue)}),
|
|
||||||
RenderTargetFormat.D24_UNorm_S8_UInt);
|
|
||||||
_compositeTarget = new RenderTargetGroup(desc);
|
|
||||||
|
|
||||||
_cameraTarget = new RenderTargetGroup(.(){
|
|
||||||
Width = 100,
|
|
||||||
Height = 100,
|
|
||||||
ColorTargetDescriptions = TargetDescription[](
|
|
||||||
.(.R16G16B16A16_Float),
|
|
||||||
.(.R32_UInt)
|
|
||||||
),
|
|
||||||
DepthTargetDescription = .(.D24_UNorm_S8_UInt)
|
|
||||||
});
|
|
||||||
|
|
||||||
_gammaCorrectEffect = Content.LoadAsset<Effect>("Shaders/GammaCorrect.hlsl");//Application.Get().EffectLibrary.Load("content/Shaders/GammaCorrect.hlsl");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ~this()
|
public ~this()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CopyTo(Scene target)
|
||||||
|
{
|
||||||
|
// Copy entities
|
||||||
|
for (let sourceHandle in _ecsWorld.Enumerate())
|
||||||
|
{
|
||||||
|
Entity sourceEntity = .(sourceHandle, this);
|
||||||
|
|
||||||
|
target.CreateEntity(sourceEntity.Name, sourceEntity.UUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: perhaps use reflection and comptime
|
||||||
|
// Copy components
|
||||||
|
//CopyComponents<TransformComponent>(this, target); /* Parent will be copied below*/
|
||||||
|
CopyComponents<MeshRendererComponent>(this, target);
|
||||||
|
CopyComponents<MeshComponent>(this, target);
|
||||||
|
CopyComponents<EditorComponent>(this, target);
|
||||||
|
CopyComponents<SpriteRendererComponent>(this, target);
|
||||||
|
CopyComponents<CircleRendererComponent>(this, target);
|
||||||
|
CopyComponents<CameraComponent>(this, target);
|
||||||
|
CopyComponents<NativeScriptComponent>(this, target);
|
||||||
|
CopyComponents<LightComponent>(this, target);
|
||||||
|
CopyComponents<Rigidbody2DComponent>(this, target);
|
||||||
|
CopyComponents<BoxCollider2DComponent>(this, target);
|
||||||
|
CopyComponents<CircleCollider2DComponent>(this, target);
|
||||||
|
|
||||||
|
// Copy transforms
|
||||||
|
for (let (sourceHandle, sourceTransform) in _ecsWorld.Enumerate<TransformComponent>())
|
||||||
|
{
|
||||||
|
Entity sourceEntity = Entity(sourceHandle, this);
|
||||||
|
Entity sourceParent = Entity(sourceTransform.Parent, this);
|
||||||
|
|
||||||
|
Entity targetEntity = target.GetEntityByID(sourceEntity.UUID);
|
||||||
|
*targetEntity.Transform = *sourceTransform;
|
||||||
|
|
||||||
|
if (sourceParent.IsValid)
|
||||||
|
{
|
||||||
|
Entity targetParent = target.GetEntityByID(sourceParent.UUID);
|
||||||
|
targetEntity.Parent = targetParent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
target.OnViewportResize(_viewportWidth, _viewportHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CopyComponents<TComponent>(Scene source, Scene target) where TComponent : struct, new
|
||||||
|
{
|
||||||
|
for (let (sourceHandle, sourceComponent) in source._ecsWorld.Enumerate<TComponent>())
|
||||||
|
{
|
||||||
|
Entity sourceEntity = .(sourceHandle, source);
|
||||||
|
|
||||||
|
Entity targetEntity = target.GetEntityByID(sourceEntity.UUID);
|
||||||
|
targetEntity.AddComponent<TComponent>(*sourceComponent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
b2Vec2 _gravity2D = .(0.0f, -9.8f);
|
b2Vec2 _gravity2D = .(0.0f, -9.8f);
|
||||||
|
|
||||||
@@ -102,6 +125,16 @@ namespace GlitchyEngine.World
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void OnRuntimeStart()
|
public void OnRuntimeStart()
|
||||||
|
{
|
||||||
|
OnSimulationStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnRuntimeStop()
|
||||||
|
{
|
||||||
|
OnSimulationStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnSimulationStart()
|
||||||
{
|
{
|
||||||
_physicsWorld2D = Box2D.World.Create(ref _gravity2D);
|
_physicsWorld2D = Box2D.World.Create(ref _gravity2D);
|
||||||
|
|
||||||
@@ -160,351 +193,83 @@ namespace GlitchyEngine.World
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnRuntimeStop()
|
public void OnSimulationStop()
|
||||||
{
|
{
|
||||||
Box2D.World.Delete(_physicsWorld2D);
|
Box2D.World.Delete(_physicsWorld2D);
|
||||||
_physicsWorld2D = null;
|
_physicsWorld2D = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateRuntime(GameTime gameTime, RenderTargetGroup finalTarget)
|
public enum UpdateMode
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileRendererFunction!();
|
/// No special update configuration (this does NOT mean nothing will be updated!)
|
||||||
|
None = 0x00,
|
||||||
finalTarget.AddRef();
|
/// Update editor-specific stuff
|
||||||
|
Editor = 0x01,
|
||||||
TransformSystem.Update(_ecsWorld);
|
/// Update the physics related stuff
|
||||||
|
Physics = 0x02,
|
||||||
// Run scripts
|
/// Update the runtume related stuff (e.g. execute scripts). Also run physics!
|
||||||
for (var (entity, script) in _ecsWorld.Enumerate<NativeScriptComponent>())
|
Runtime = 0x04 | Physics,
|
||||||
{
|
|
||||||
if (script.Instance == null)
|
|
||||||
{
|
|
||||||
script.Instance = script.InstantiateFunction();
|
|
||||||
script.Instance._entity = Entity(entity, this);
|
|
||||||
script.Instance.[Friend]OnCreate();
|
|
||||||
}
|
|
||||||
|
|
||||||
script.Instance.[Friend]OnUpdate(gameTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update 2D physics
|
|
||||||
{
|
|
||||||
const int32 velocityIterations = 6;
|
|
||||||
const int32 positionIterations = 2;
|
|
||||||
const int32 particleIterations = 2;
|
|
||||||
|
|
||||||
Box2D.World.Step(_physicsWorld2D, gameTime.DeltaTime, velocityIterations, positionIterations, particleIterations);
|
|
||||||
|
|
||||||
// Retrieve transform from Box2D
|
|
||||||
for (var entry in _ecsWorld.Enumerate<Rigidbody2DComponent>())
|
|
||||||
{
|
|
||||||
Entity entity = .(entry.Entity, this);
|
|
||||||
|
|
||||||
var transform = entity.Transform;
|
|
||||||
var rigidbody = entry.Component;
|
|
||||||
|
|
||||||
b2Body* body = rigidbody.RuntimeBody;
|
|
||||||
b2Vec2 position = Box2D.Body.GetPosition(body);
|
|
||||||
float angle = Box2D.Body.GetAngle(body);
|
|
||||||
|
|
||||||
transform.Position = .(position.x, position.y, transform.Position.Z);
|
|
||||||
transform.RotationEuler = .(transform.RotationEuler.XY, angle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find camera
|
|
||||||
Camera* primaryCamera = null;
|
|
||||||
Matrix primaryCameraTransform = default;
|
|
||||||
RenderTargetGroup renderTarget = null;
|
|
||||||
|
|
||||||
for (var (entity, transform, camera) in _ecsWorld.Enumerate<TransformComponent, CameraComponent>())
|
|
||||||
{
|
|
||||||
if (camera.Primary)// && camera.RenderTarget != null)
|
|
||||||
{
|
|
||||||
primaryCamera = &camera.Camera;
|
|
||||||
primaryCameraTransform = transform.WorldTransform;
|
|
||||||
// TODO: bind render targets to cameras
|
|
||||||
// renderTarget = camera.RenderTarget..AddRef();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderTarget = _cameraTarget..AddRef();
|
|
||||||
|
|
||||||
// 3D render
|
|
||||||
Renderer.BeginScene(*primaryCamera, primaryCameraTransform, renderTarget, _compositeTarget);
|
|
||||||
|
|
||||||
for (var (entity, transform, mesh, meshRenderer) in _ecsWorld.Enumerate<TransformComponent, MeshComponent, MeshRendererComponent>())
|
|
||||||
{
|
|
||||||
Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var (entity, transform, light) in _ecsWorld.Enumerate<TransformComponent, LightComponent>())
|
|
||||||
{
|
|
||||||
Renderer.Submit(light.SceneLight, transform.WorldTransform);
|
|
||||||
}
|
|
||||||
|
|
||||||
Renderer.EndScene();
|
|
||||||
|
|
||||||
renderTarget.ReleaseRef();
|
|
||||||
|
|
||||||
// TODO: alphablending (handle in Renderer2D)
|
|
||||||
// TODO: 2D-Postprocessing requires rendering into separate target instead of directly into compositeTarget
|
|
||||||
|
|
||||||
RenderCommand.SetRenderTargetGroup(_compositeTarget);
|
|
||||||
RenderCommand.BindRenderTargets();
|
|
||||||
|
|
||||||
// Sprite renderer
|
|
||||||
Renderer2D.BeginScene(*primaryCamera, primaryCameraTransform, .BackToFront);
|
|
||||||
|
|
||||||
for (var (entity, transform, sprite) in _ecsWorld.Enumerate<TransformComponent, SpriterRendererComponent>())
|
|
||||||
{
|
|
||||||
Renderer2D.DrawSprite(transform.WorldTransform, sprite, entity.Index);
|
|
||||||
}
|
|
||||||
|
|
||||||
Renderer2D.EndScene();
|
|
||||||
|
|
||||||
// Gamma correct composit target and draw it into viewport
|
|
||||||
{
|
|
||||||
RenderCommand.UnbindRenderTargets();
|
|
||||||
RenderCommand.SetRenderTargetGroup(finalTarget, false);
|
|
||||||
RenderCommand.BindRenderTargets();
|
|
||||||
|
|
||||||
_gammaCorrectEffect.SetTexture("Texture", _compositeTarget, 0);
|
|
||||||
// TODO: iiihhh
|
|
||||||
_gammaCorrectEffect.ApplyChanges();
|
|
||||||
_gammaCorrectEffect.Bind();
|
|
||||||
|
|
||||||
FullscreenQuad.Draw();
|
|
||||||
}
|
|
||||||
|
|
||||||
finalTarget.ReleaseRef();
|
|
||||||
|
|
||||||
|
|
||||||
/*Debug.Profiler.ProfileRendererFunction!();
|
|
||||||
|
|
||||||
finalTarget.AddRef();
|
|
||||||
|
|
||||||
TransformSystem.Update(_ecsWorld);
|
|
||||||
|
|
||||||
// Run scripts
|
|
||||||
for (var (entity, script) in _ecsWorld.Enumerate<NativeScriptComponent>())
|
|
||||||
{
|
|
||||||
if (script.Instance == null)
|
|
||||||
{
|
|
||||||
script.Instance = script.InstantiateFunction();
|
|
||||||
script.Instance._entity = Entity(entity, this);
|
|
||||||
script.Instance.[Friend]OnCreate();
|
|
||||||
}
|
|
||||||
|
|
||||||
script.Instance.[Friend]OnUpdate(gameTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find camera
|
|
||||||
Camera* primaryCamera = null;
|
|
||||||
Matrix primaryCameraTransform = default;
|
|
||||||
RenderTargetGroup renderTarget = null;
|
|
||||||
|
|
||||||
for (var (entity, transform, camera) in _ecsWorld.Enumerate<TransformComponent, CameraComponent>())
|
|
||||||
{
|
|
||||||
if (camera.Primary)// && camera.RenderTarget != null)
|
|
||||||
{
|
|
||||||
primaryCamera = &camera.Camera;
|
|
||||||
primaryCameraTransform = transform.WorldTransform;
|
|
||||||
//renderTarget = camera.RenderTarget..AddRef();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (primaryCamera != null)
|
|
||||||
{
|
|
||||||
// 3D render
|
|
||||||
Renderer.BeginScene(*primaryCamera, primaryCameraTransform, _compositeTarget, finalTarget);
|
|
||||||
|
|
||||||
for (var (entity, transform, mesh, meshRenderer) in _ecsWorld.Enumerate<TransformComponent, MeshComponent, MeshRendererComponent>())
|
|
||||||
{
|
|
||||||
Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var (entity, transform, light) in _ecsWorld.Enumerate<TransformComponent, LightComponent>())
|
|
||||||
{
|
|
||||||
Renderer.Submit(light.SceneLight, transform.WorldTransform);
|
|
||||||
}
|
|
||||||
|
|
||||||
Renderer.EndScene();
|
|
||||||
|
|
||||||
// TODO: alphablending (handle in Renderer2D)
|
|
||||||
// TODO: 2D-Postprocessing requires rendering into separate target instead of directly into compositeTarget
|
|
||||||
|
|
||||||
RenderCommand.SetRenderTargetGroup(_compositeTarget);
|
|
||||||
RenderCommand.BindRenderTargets();
|
|
||||||
|
|
||||||
// Sprite renderer
|
|
||||||
Renderer2D.BeginScene(*primaryCamera, primaryCameraTransform, .BackToFront);
|
|
||||||
|
|
||||||
for (var (entity, transform, sprite) in _ecsWorld.Enumerate<TransformComponent, SpriterRendererComponent>())
|
|
||||||
{
|
|
||||||
Renderer2D.DrawSprite(transform.WorldTransform, sprite, entity.Index);
|
|
||||||
}
|
|
||||||
|
|
||||||
Renderer2D.EndScene();
|
|
||||||
|
|
||||||
// Gamma correct composit target and draw it into viewport
|
|
||||||
{
|
|
||||||
RenderCommand.UnbindRenderTargets();
|
|
||||||
RenderCommand.SetRenderTargetGroup(finalTarget, false);
|
|
||||||
RenderCommand.BindRenderTargets();
|
|
||||||
|
|
||||||
_gammaCorrectEffect.SetTexture("Texture", _compositeTarget, 0);
|
|
||||||
// TODO: iiihhh
|
|
||||||
_gammaCorrectEffect.Bind(Application.Get().Window.Context);
|
|
||||||
|
|
||||||
FullscreenQuad.Draw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
finalTarget.ReleaseRef();*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Debug.Profiler.ProfileRendererFunction!();
|
|
||||||
|
|
||||||
TransformSystem.Update(_ecsWorld);
|
|
||||||
|
|
||||||
for (var (entity, script) in _ecsWorld.Enumerate<NativeScriptComponent>())
|
|
||||||
{
|
|
||||||
if (script.Instance == null)
|
|
||||||
{
|
|
||||||
script.Instance = script.InstantiateFunction();
|
|
||||||
script.Instance._entity = Entity(entity, this);
|
|
||||||
script.Instance.[Friend]OnCreate();
|
|
||||||
}
|
|
||||||
|
|
||||||
script.Instance.[Friend]OnUpdate(gameTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
Camera* primaryCamera = null;
|
|
||||||
Matrix primaryCameraTransform = default;
|
|
||||||
RenderTargetGroup renderTarget = null;
|
|
||||||
|
|
||||||
for (var (entity, transform, camera) in _ecsWorld.Enumerate<TransformComponent, CameraComponent>())
|
|
||||||
{
|
|
||||||
if (camera.Primary && camera.RenderTarget != null)
|
|
||||||
{
|
|
||||||
primaryCamera = &camera.Camera;
|
|
||||||
primaryCameraTransform = transform.WorldTransform;
|
|
||||||
renderTarget = camera.RenderTarget..AddRef();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (primaryCamera != null)
|
|
||||||
{
|
|
||||||
// 3D render
|
|
||||||
Renderer.BeginScene(*primaryCamera, primaryCameraTransform, renderTarget, finalTarget);
|
|
||||||
|
|
||||||
for (var (entity, transform, mesh, meshRenderer) in _ecsWorld.Enumerate<TransformComponent, MeshComponent, MeshRendererComponent>())
|
|
||||||
{
|
|
||||||
Renderer.Submit(mesh.Mesh, meshRenderer.Material, transform.WorldTransform);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var (entity, transform, light) in _ecsWorld.Enumerate<TransformComponent, LightComponent>())
|
|
||||||
{
|
|
||||||
Renderer.Submit(light.SceneLight, transform.WorldTransform);
|
|
||||||
}
|
|
||||||
|
|
||||||
Renderer.EndScene();
|
|
||||||
|
|
||||||
// Sprite renderer
|
|
||||||
Renderer2D.BeginScene(*primaryCamera, primaryCameraTransform);
|
|
||||||
|
|
||||||
for (var (entity, transform, sprite) in _ecsWorld.Enumerate<TransformComponent, SpriterRendererComponent>())
|
|
||||||
{
|
|
||||||
Renderer2D.DrawQuad(transform.WorldTransform, sprite.Sprite, sprite.Color);
|
|
||||||
}
|
|
||||||
|
|
||||||
Renderer2D.EndScene();
|
|
||||||
|
|
||||||
renderTarget?.ReleaseRef();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateEditor(GameTime gameTime, EditorCamera camera, RenderTargetGroup viewportTarget, delegate void() DebugDraw3D, delegate void() DrawDebug2D)
|
public void Update(GameTime gameTime, UpdateMode mode)
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileRendererFunction!();
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
|
|
||||||
viewportTarget.AddRef();
|
|
||||||
|
|
||||||
TransformSystem.Update(_ecsWorld);
|
TransformSystem.Update(_ecsWorld);
|
||||||
|
|
||||||
// 3D render
|
if (mode.HasFlag(.Runtime))
|
||||||
Renderer.BeginScene(camera, _compositeTarget);
|
|
||||||
|
|
||||||
for (var (entity, transform, mesh, meshRenderer) in _ecsWorld.Enumerate<TransformComponent, MeshComponent, MeshRendererComponent>())
|
|
||||||
{
|
{
|
||||||
if (mesh.Mesh == null || meshRenderer.Material == null)
|
// Run scripts
|
||||||
continue;
|
for (var (entity, script) in _ecsWorld.Enumerate<NativeScriptComponent>())
|
||||||
|
{
|
||||||
Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform);
|
if (script.Instance == null)
|
||||||
}
|
{
|
||||||
|
script.Instance = script.InstantiateFunction();
|
||||||
for (var (entity, transform, light) in _ecsWorld.Enumerate<TransformComponent, LightComponent>())
|
script.Instance._entity = Entity(entity, this);
|
||||||
{
|
script.Instance.[Friend]OnCreate();
|
||||||
Renderer.Submit(light.SceneLight, transform.WorldTransform);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
DebugDraw3D();
|
|
||||||
|
|
||||||
Renderer.EndScene();
|
|
||||||
|
|
||||||
// TODO: alphablending (handle in Renderer2D)
|
|
||||||
// TODO: 2D-Postprocessing requires rendering into separate target instead of directly into compositeTarget
|
|
||||||
|
|
||||||
RenderCommand.SetRenderTargetGroup(_compositeTarget);
|
|
||||||
RenderCommand.BindRenderTargets();
|
|
||||||
|
|
||||||
// Sprite renderer
|
|
||||||
Renderer2D.BeginScene(camera, .BackToFront);
|
|
||||||
|
|
||||||
for (var (entity, transform, sprite) in _ecsWorld.Enumerate<TransformComponent, SpriterRendererComponent>())
|
|
||||||
{
|
|
||||||
Renderer2D.DrawSprite(transform.WorldTransform, sprite, entity.Index);
|
|
||||||
}
|
|
||||||
|
|
||||||
Renderer2D.EndScene();
|
|
||||||
|
|
||||||
Renderer2D.BeginScene(camera, .BackToFront);
|
|
||||||
|
|
||||||
DrawDebug2D();
|
|
||||||
|
|
||||||
Renderer2D.EndScene();
|
|
||||||
|
|
||||||
// Gamma correct composit target and draw it into viewport
|
|
||||||
{
|
|
||||||
RenderCommand.UnbindRenderTargets();
|
|
||||||
RenderCommand.SetRenderTargetGroup(viewportTarget, false);
|
|
||||||
RenderCommand.BindRenderTargets();
|
|
||||||
|
|
||||||
_gammaCorrectEffect.SetTexture("Texture", _compositeTarget, 0);
|
script.Instance.[Friend]OnUpdate(gameTime);
|
||||||
// TODO: iiihhh
|
}
|
||||||
_gammaCorrectEffect.ApplyChanges();
|
|
||||||
_gammaCorrectEffect.Bind();
|
|
||||||
|
|
||||||
FullscreenQuad.Draw();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mode.HasFlag(.Physics))
|
||||||
|
{
|
||||||
|
// Update 2D physics
|
||||||
|
{
|
||||||
|
const int32 velocityIterations = 6;
|
||||||
|
const int32 positionIterations = 2;
|
||||||
|
const int32 particleIterations = 2;
|
||||||
|
|
||||||
viewportTarget.ReleaseRef();
|
Box2D.World.Step(_physicsWorld2D, gameTime.DeltaTime, velocityIterations, positionIterations, particleIterations);
|
||||||
|
|
||||||
|
// Retrieve transform from Box2D
|
||||||
|
for (var entry in _ecsWorld.Enumerate<Rigidbody2DComponent>())
|
||||||
|
{
|
||||||
|
Entity entity = .(entry.Entity, this);
|
||||||
|
|
||||||
|
var transform = entity.Transform;
|
||||||
|
var rigidbody = entry.Component;
|
||||||
|
|
||||||
|
b2Body* body = rigidbody.RuntimeBody;
|
||||||
|
b2Vec2 position = Box2D.Body.GetPosition(body);
|
||||||
|
float angle = Box2D.Body.GetAngle(body);
|
||||||
|
|
||||||
|
transform.Position = .(position.x, position.y, transform.Position.Z);
|
||||||
|
transform.RotationEuler = .(transform.RotationEuler.XY, angle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new Entity with the given name.
|
/// Creates a new Entity with the given name.
|
||||||
public Entity CreateEntity(String name = "", UUID id = default)
|
public Entity CreateEntity(StringView name = "", UUID id = default)
|
||||||
{
|
{
|
||||||
Entity entity = Entity(_ecsWorld.NewEntity(), this);
|
Entity entity = Entity(_ecsWorld.NewEntity(), this);
|
||||||
entity.AddComponent<TransformComponent>();
|
entity.AddComponent<TransformComponent>();
|
||||||
|
|
||||||
let nameComponent = entity.AddComponent<DebugNameComponent>();
|
let nameComponent = entity.AddComponent<NameComponent>();
|
||||||
nameComponent.SetName(name.IsEmpty ? "Entity" : name);
|
nameComponent.Name = (name.IsEmpty ? "Entity" : name);
|
||||||
|
|
||||||
// If no id is given generate a random one.
|
// If no id is given generate a random one.
|
||||||
IDComponent idComponent = (id == default) ? IDComponent() : IDComponent(id);
|
IDComponent idComponent = (id == default) ? IDComponent() : IDComponent(id);
|
||||||
@@ -545,13 +310,11 @@ namespace GlitchyEngine.World
|
|||||||
return .Err;
|
return .Err;
|
||||||
}
|
}
|
||||||
|
|
||||||
private uint32 ViewportWidth, ViewportHeight;
|
|
||||||
|
|
||||||
/// Sets the size of the viewport into which the scene will be rendered.
|
/// Sets the size of the viewport into which the scene will be rendered.
|
||||||
public void OnViewportResize(uint32 width, uint32 height)
|
public void OnViewportResize(uint32 width, uint32 height)
|
||||||
{
|
{
|
||||||
ViewportWidth = width;
|
_viewportWidth = width;
|
||||||
ViewportHeight = height;
|
_viewportHeight = height;
|
||||||
|
|
||||||
for (var (entity, cameraComponent) in _ecsWorld.Enumerate<CameraComponent>())
|
for (var (entity, cameraComponent) in _ecsWorld.Enumerate<CameraComponent>())
|
||||||
{
|
{
|
||||||
@@ -560,9 +323,6 @@ namespace GlitchyEngine.World
|
|||||||
cameraComponent.Camera.SetViewportSize(width, height);
|
cameraComponent.Camera.SetViewportSize(width, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_compositeTarget.Resize(ViewportWidth, ViewportHeight);
|
|
||||||
_cameraTarget.Resize(ViewportWidth, ViewportHeight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnComponentAdded(Entity entity, Type componentType, void* component)
|
private void OnComponentAdded(Entity entity, Type componentType, void* component)
|
||||||
@@ -572,5 +332,25 @@ namespace GlitchyEngine.World
|
|||||||
handler(entity, componentType, component);
|
handler(entity, componentType, component);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WorldEnumerator<TComponent> GetEntities<TComponent>() where TComponent : struct
|
||||||
|
{
|
||||||
|
return _ecsWorld.Enumerate<TComponent>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorldEnumerator<TComponent1, TComponent2> GetEntities<TComponent1, TComponent2>()
|
||||||
|
where TComponent1 : struct
|
||||||
|
where TComponent2 : struct
|
||||||
|
{
|
||||||
|
return _ecsWorld.Enumerate<TComponent1, TComponent2>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorldEnumerator<TComponent1, TComponent2, TComponent3> GetEntities<TComponent1, TComponent2, TComponent3>()
|
||||||
|
where TComponent1 : struct
|
||||||
|
where TComponent2 : struct
|
||||||
|
where TComponent3 : struct
|
||||||
|
{
|
||||||
|
return _ecsWorld.Enumerate<TComponent1, TComponent2, TComponent3>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,212 @@
|
|||||||
|
using GlitchyEngine.Renderer;
|
||||||
|
using GlitchyEngine.Content;
|
||||||
|
using GlitchyEngine.Math;
|
||||||
|
|
||||||
|
namespace GlitchyEngine.World;
|
||||||
|
|
||||||
|
using internal GlitchyEngine.World;
|
||||||
|
|
||||||
|
class SceneRenderer
|
||||||
|
{
|
||||||
|
public Scene Scene { get; set; }
|
||||||
|
|
||||||
|
private RenderTargetGroup _compositeTarget ~ _.ReleaseRef();
|
||||||
|
|
||||||
|
// Temporary target for camera. Needs to change as soon as we support multiple cameras
|
||||||
|
private RenderTargetGroup _cameraTarget ~ _.ReleaseRef();
|
||||||
|
|
||||||
|
private uint32 _viewportWidth;
|
||||||
|
private uint32 _viewportHeight;
|
||||||
|
|
||||||
|
private AssetHandle _gammaCorrectEffect;
|
||||||
|
|
||||||
|
public RenderTargetGroup CompositeTarget => _compositeTarget;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
RenderTargetGroupDescription desc = .(100, 100,
|
||||||
|
TargetDescription[](
|
||||||
|
RenderTargetFormat.R16G16B16A16_Float,
|
||||||
|
.(RenderTargetFormat.R32_UInt) {ClearColor = .UInt(uint32.MaxValue)}),
|
||||||
|
RenderTargetFormat.D24_UNorm_S8_UInt);
|
||||||
|
_compositeTarget = new RenderTargetGroup(desc);
|
||||||
|
|
||||||
|
_cameraTarget = new RenderTargetGroup(.(){
|
||||||
|
Width = 100,
|
||||||
|
Height = 100,
|
||||||
|
ColorTargetDescriptions = TargetDescription[](
|
||||||
|
.(.R16G16B16A16_Float),
|
||||||
|
.(.R32_UInt)
|
||||||
|
),
|
||||||
|
DepthTargetDescription = .(.D24_UNorm_S8_UInt)
|
||||||
|
});
|
||||||
|
|
||||||
|
_gammaCorrectEffect = Content.LoadAsset("Shaders/GammaCorrect.hlsl");//Application.Get().EffectLibrary.Load("content/Shaders/GammaCorrect.hlsl");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the size of the viewport into which the scene will be rendered.
|
||||||
|
public void OnViewportResize(uint32 width, uint32 height)
|
||||||
|
{
|
||||||
|
_viewportWidth = width;
|
||||||
|
_viewportHeight = height;
|
||||||
|
|
||||||
|
_compositeTarget.Resize(_viewportWidth, _viewportHeight);
|
||||||
|
_cameraTarget.Resize(_viewportWidth, _viewportHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RenderRuntime(GameTime gameTime, RenderTargetGroup finalTarget)
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
|
|
||||||
|
// Find camera
|
||||||
|
Camera* primaryCamera = null;
|
||||||
|
Matrix primaryCameraTransform = default;
|
||||||
|
RenderTargetGroup renderTarget = null;
|
||||||
|
|
||||||
|
for (var (entity, transform, camera) in Scene._ecsWorld.Enumerate<TransformComponent, CameraComponent>())
|
||||||
|
{
|
||||||
|
if (camera.Primary)// && camera.RenderTarget != null)
|
||||||
|
{
|
||||||
|
primaryCamera = &camera.Camera;
|
||||||
|
primaryCameraTransform = transform.WorldTransform;
|
||||||
|
// TODO: bind render targets to cameras
|
||||||
|
// renderTarget = camera.RenderTarget..AddRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (primaryCamera == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
finalTarget.AddRef();
|
||||||
|
|
||||||
|
renderTarget = _cameraTarget..AddRef();
|
||||||
|
|
||||||
|
// 3D render
|
||||||
|
Renderer.BeginScene(*primaryCamera, primaryCameraTransform, renderTarget, _compositeTarget);
|
||||||
|
|
||||||
|
for (var (entity, transform, mesh, meshRenderer) in Scene._ecsWorld.Enumerate<TransformComponent, MeshComponent, MeshRendererComponent>())
|
||||||
|
{
|
||||||
|
Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var (entity, transform, light) in Scene._ecsWorld.Enumerate<TransformComponent, LightComponent>())
|
||||||
|
{
|
||||||
|
Renderer.Submit(light.SceneLight, transform.WorldTransform);
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer.EndScene();
|
||||||
|
|
||||||
|
renderTarget.ReleaseRef();
|
||||||
|
|
||||||
|
// TODO: alphablending (handle in Renderer2D)
|
||||||
|
// TODO: 2D-Postprocessing requires rendering into separate target instead of directly into compositeTarget
|
||||||
|
|
||||||
|
RenderCommand.SetRenderTargetGroup(_compositeTarget);
|
||||||
|
RenderCommand.BindRenderTargets();
|
||||||
|
|
||||||
|
// Sprite renderer
|
||||||
|
Renderer2D.BeginScene(*primaryCamera, primaryCameraTransform, .BackToFront);
|
||||||
|
|
||||||
|
for (var (entity, transform, sprite) in Scene._ecsWorld.Enumerate<TransformComponent, SpriteRendererComponent>())
|
||||||
|
{
|
||||||
|
Renderer2D.DrawSprite(transform.WorldTransform, sprite, entity.Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var (entity, transform, circle) in Scene._ecsWorld.Enumerate<TransformComponent, CircleRendererComponent>())
|
||||||
|
{
|
||||||
|
Renderer2D.DrawCircle(transform.WorldTransform, circle, entity.Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer2D.EndScene();
|
||||||
|
|
||||||
|
// Gamma correct composit target and draw it into viewport
|
||||||
|
{
|
||||||
|
RenderCommand.UnbindRenderTargets();
|
||||||
|
RenderCommand.SetRenderTargetGroup(finalTarget, false);
|
||||||
|
RenderCommand.BindRenderTargets();
|
||||||
|
|
||||||
|
Effect gammaEffect = Content.GetAsset<Effect>(_gammaCorrectEffect);
|
||||||
|
|
||||||
|
gammaEffect.SetTexture("Texture", _compositeTarget, 0);
|
||||||
|
// TODO: iiihhh
|
||||||
|
gammaEffect.ApplyChanges();
|
||||||
|
gammaEffect.Bind();
|
||||||
|
|
||||||
|
FullscreenQuad.Draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
finalTarget.ReleaseRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RenderEditor(GameTime gameTime, EditorCamera camera, RenderTargetGroup viewportTarget, delegate void() DebugDraw3D, delegate void() DrawDebug2D)
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
|
|
||||||
|
viewportTarget.AddRef();
|
||||||
|
|
||||||
|
// 3D render
|
||||||
|
Renderer.BeginScene(camera, _compositeTarget);
|
||||||
|
|
||||||
|
for (var (entity, transform, mesh, meshRenderer) in Scene._ecsWorld.Enumerate<TransformComponent, MeshComponent, MeshRendererComponent>())
|
||||||
|
{
|
||||||
|
if (mesh.Mesh == .Invalid || meshRenderer.Material == .Invalid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var (entity, transform, light) in Scene._ecsWorld.Enumerate<TransformComponent, LightComponent>())
|
||||||
|
{
|
||||||
|
Renderer.Submit(light.SceneLight, transform.WorldTransform);
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugDraw3D();
|
||||||
|
|
||||||
|
Renderer.EndScene();
|
||||||
|
|
||||||
|
// TODO: alphablending (handle in Renderer2D)
|
||||||
|
// TODO: 2D-Postprocessing requires rendering into separate target instead of directly into compositeTarget
|
||||||
|
|
||||||
|
RenderCommand.SetRenderTargetGroup(_compositeTarget);
|
||||||
|
RenderCommand.BindRenderTargets();
|
||||||
|
|
||||||
|
// Sprite renderer
|
||||||
|
Renderer2D.BeginScene(camera, .BackToFront);
|
||||||
|
|
||||||
|
for (var (entity, transform, sprite) in Scene._ecsWorld.Enumerate<TransformComponent, SpriteRendererComponent>())
|
||||||
|
{
|
||||||
|
Renderer2D.DrawSprite(transform.WorldTransform, sprite, entity.Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var (entity, transform, circle) in Scene._ecsWorld.Enumerate<TransformComponent, CircleRendererComponent>())
|
||||||
|
{
|
||||||
|
Renderer2D.DrawCircle(transform.WorldTransform, circle, entity.Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer2D.EndScene();
|
||||||
|
|
||||||
|
Renderer2D.BeginScene(camera, .BackToFront);
|
||||||
|
|
||||||
|
DrawDebug2D();
|
||||||
|
|
||||||
|
Renderer2D.EndScene();
|
||||||
|
|
||||||
|
// Gamma correct composit target and draw it into viewport
|
||||||
|
{
|
||||||
|
RenderCommand.UnbindRenderTargets();
|
||||||
|
RenderCommand.SetRenderTargetGroup(viewportTarget, false);
|
||||||
|
RenderCommand.BindRenderTargets();
|
||||||
|
|
||||||
|
Effect gammaEffect = Content.GetAsset<Effect>(_gammaCorrectEffect);
|
||||||
|
|
||||||
|
gammaEffect.SetTexture("Texture", _compositeTarget, 0);
|
||||||
|
// TODO: iiihhh
|
||||||
|
gammaEffect.ApplyChanges();
|
||||||
|
gammaEffect.Bind();
|
||||||
|
|
||||||
|
FullscreenQuad.Draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
viewportTarget.ReleaseRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Vendored
+1
-1
Submodule GlitchyEngine/vendor/bon updated: 0c80e365cd...515b606cf3
Vendored
+1
-1
Submodule GlitchyEngine/vendor/directx updated: 4b9d0c5d7b...d1a21b6b88
Vendored
+1
-1
Submodule GlitchyEngine/vendor/gltf updated: 60b0a1be16...d881f985c2
Vendored
+1
-1
Submodule GlitchyEngine/vendor/imgui updated: 827764b98c...b1d891368e
+13
-10
@@ -1,4 +1,4 @@
|
|||||||
using GlitchyEngine.Renderer;
|
/*using GlitchyEngine.Renderer;
|
||||||
using GlitchyEngine.Events;
|
using GlitchyEngine.Events;
|
||||||
using GlitchyEngine.ImGui;
|
using GlitchyEngine.ImGui;
|
||||||
using GlitchyEngine.Math;
|
using GlitchyEngine.Math;
|
||||||
@@ -63,8 +63,8 @@ namespace Sandbox
|
|||||||
|
|
||||||
Material _checkerMaterial ~ _?.ReleaseRef();
|
Material _checkerMaterial ~ _?.ReleaseRef();
|
||||||
Material _logoMaterial ~ _?.ReleaseRef();
|
Material _logoMaterial ~ _?.ReleaseRef();
|
||||||
Texture2D _texture ~ _?.ReleaseRef();
|
AssetHandle _texture;
|
||||||
Texture2D _ge_logo ~ _?.ReleaseRef();
|
AssetHandle _ge_logo;
|
||||||
|
|
||||||
BlendState _alphaBlendState ~ _?.ReleaseRef();
|
BlendState _alphaBlendState ~ _?.ReleaseRef();
|
||||||
BlendState _opaqueBlendState ~ _?.ReleaseRef();
|
BlendState _opaqueBlendState ~ _?.ReleaseRef();
|
||||||
@@ -91,7 +91,7 @@ namespace Sandbox
|
|||||||
|
|
||||||
//effectLibrary.LoadNoRefInc("content\\Shaders\\testShader.hlsl");
|
//effectLibrary.LoadNoRefInc("content\\Shaders\\testShader.hlsl");
|
||||||
|
|
||||||
Effect textureEffect = Content.LoadAsset<Effect>("Shaders\\textureShader.hlsl");
|
Effect textureEffect = Content.GetAsset<Effect>(Content.LoadAsset("Shaders\\textureShader.hlsl"));
|
||||||
|
|
||||||
_depthTarget = new DepthStencilTarget(_context.SwapChain.Width, _context.SwapChain.Height);
|
_depthTarget = new DepthStencilTarget(_context.SwapChain.Width, _context.SwapChain.Height);
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ namespace Sandbox
|
|||||||
|
|
||||||
VertexLayout vertexLayout = new VertexLayout(VertexColorTexture.VertexElements, false);
|
VertexLayout vertexLayout = new VertexLayout(VertexColorTexture.VertexElements, false);
|
||||||
|
|
||||||
textureEffect.ReleaseRef();
|
//textureEffect.ReleaseRef();
|
||||||
|
|
||||||
// Create hexagon
|
// Create hexagon
|
||||||
{
|
{
|
||||||
@@ -174,8 +174,11 @@ namespace Sandbox
|
|||||||
rsDesc.FrontCounterClockwise = false;
|
rsDesc.FrontCounterClockwise = false;
|
||||||
_rasterizerStateClockWise = new RasterizerState(rsDesc);
|
_rasterizerStateClockWise = new RasterizerState(rsDesc);
|
||||||
|
|
||||||
_texture = Content.LoadAsset<Texture2D>("content/Textures/Checkerboard.dds");//new Texture2D("content/Textures/Checkerboard.dds");
|
_texture = Content.LoadAsset("content/Textures/Checkerboard.dds");//new Texture2D("content/Textures/Checkerboard.dds");
|
||||||
_ge_logo = Content.LoadAsset<Texture2D>("content/Textures/GE_Logo.dds");//new Texture2D("content/Textures/GE_Logo.dds");
|
_ge_logo = Content.LoadAsset("content/Textures/GE_Logo.dds");//new Texture2D("content/Textures/GE_Logo.dds");
|
||||||
|
|
||||||
|
Texture2D texture = Content.GetAsset<Texture2D>(_texture);
|
||||||
|
Texture2D ge_logo = Content.GetAsset<Texture2D>(_ge_logo);
|
||||||
|
|
||||||
let sampler = SamplerStateManager.GetSampler(
|
let sampler = SamplerStateManager.GetSampler(
|
||||||
SamplerStateDescription()
|
SamplerStateDescription()
|
||||||
@@ -183,8 +186,8 @@ namespace Sandbox
|
|||||||
MagFilter = .Point
|
MagFilter = .Point
|
||||||
});
|
});
|
||||||
|
|
||||||
_texture.SamplerState = sampler;
|
texture.SamplerState = sampler;
|
||||||
_ge_logo.SamplerState = sampler;
|
ge_logo.SamplerState = sampler;
|
||||||
|
|
||||||
sampler.ReleaseRef();
|
sampler.ReleaseRef();
|
||||||
|
|
||||||
@@ -518,4 +521,4 @@ namespace Sandbox
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}*/
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
/*using System;
|
||||||
using GlitchyEngine;
|
using GlitchyEngine;
|
||||||
using GlitchyEngine.Events;
|
using GlitchyEngine.Events;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@@ -12,6 +12,7 @@ using GlitchyEngine.Renderer.Text;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using msdfgen;
|
using msdfgen;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using GlitchyEngine.Content;
|
||||||
|
|
||||||
namespace Sandbox
|
namespace Sandbox
|
||||||
{
|
{
|
||||||
@@ -282,4 +283,4 @@ namespace Sandbox
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
@@ -21,7 +21,7 @@ namespace Sandbox
|
|||||||
#if GAMMA_TEST
|
#if GAMMA_TEST
|
||||||
PushLayer(new GammaTestLayer());
|
PushLayer(new GammaTestLayer());
|
||||||
#elif SANDBOX_2D
|
#elif SANDBOX_2D
|
||||||
PushLayer(new ExampleLayer2D());
|
//PushLayer(new ExampleLayer2D());
|
||||||
#else
|
#else
|
||||||
PushLayer(new ExampleLayer());
|
PushLayer(new ExampleLayer());
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user