mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75513bea3d | ||
|
|
16c3d7c44d | ||
|
|
7ae069baf6 | ||
|
|
00dc3faa19 | ||
|
|
f39acdadb3 | ||
|
|
1254d01545 | ||
|
|
0bc517842f | ||
|
|
3e63281508 | ||
|
|
ef486b7082 | ||
|
|
81a61d5a90 | ||
|
|
37197cbdf1 | ||
|
|
b53ed2d8f2 |
@@ -11,9 +11,9 @@ namespace Sandbox
|
||||
|
||||
public enum MyEnum
|
||||
{
|
||||
Yes,
|
||||
Yes = 1,
|
||||
No,
|
||||
Maybe
|
||||
Maybe = 1337
|
||||
}
|
||||
|
||||
public struct MyStruct
|
||||
@@ -25,36 +25,38 @@ namespace Sandbox
|
||||
|
||||
class MyTestEntity : Entity
|
||||
{
|
||||
//[ShowInEditor]
|
||||
[ShowInEditor]
|
||||
RigidBody2D _rigidBody;
|
||||
|
||||
public bool Bo;
|
||||
//public bool Bo;
|
||||
|
||||
public byte By;
|
||||
public ushort Us;
|
||||
public uint Ui;
|
||||
public ulong Ul;
|
||||
//public byte By;
|
||||
//public ushort Us;
|
||||
//public uint Ui;
|
||||
//public ulong Ul;
|
||||
|
||||
public sbyte Sb;
|
||||
public short Sh;
|
||||
public int In;
|
||||
public long Lo;
|
||||
//public sbyte Sb;
|
||||
//public short Sh;
|
||||
//public int In;
|
||||
//public long Lo;
|
||||
|
||||
public float Fl;
|
||||
public double Do;
|
||||
public float2 V2;
|
||||
public float3 V3;
|
||||
public float4 V4;
|
||||
//public float Fl;
|
||||
//public double Do;
|
||||
//public float2 V2;
|
||||
//public float3 V3;
|
||||
//public float4 V4;
|
||||
|
||||
public Entity TheEntity;
|
||||
|
||||
public float JumpForce = 2000;
|
||||
[ShowInEditor] float MoveForce = 1000;
|
||||
[ShowInEditor] private int MyNumber = 1337;
|
||||
[ShowInEditor] public double MyDouble = 1000.0f;
|
||||
//[ShowInEditor] public double MyDouble = 1000.0f;
|
||||
|
||||
public MyStruct AStruct;
|
||||
|
||||
public MyEnum AEnum = MyEnum.Maybe;
|
||||
|
||||
public Camera Camera;
|
||||
|
||||
/// <summary>
|
||||
@@ -66,14 +68,39 @@ namespace Sandbox
|
||||
|
||||
Log.Info($"Jump Force: {JumpForce}");
|
||||
|
||||
_rigidBody ??= GetComponent<RigidBody2D>() ?? AddComponent<RigidBody2D>();
|
||||
//_rigidBody ??= GetComponent<RigidBody2D>() ?? AddComponent<RigidBody2D>();
|
||||
|
||||
Camera = FindEntityWithName("Camera").As<Camera>();
|
||||
if (_rigidBody == null)
|
||||
{
|
||||
Log.Error("_rigidBody was not set in editor.");
|
||||
}
|
||||
|
||||
if (Camera == null)
|
||||
{
|
||||
Log.Error("Camera not found.");
|
||||
Log.Warning("Camera wasn't set in editor. Searching...");
|
||||
Camera = FindEntityWithName("Camera").As<Camera>();
|
||||
|
||||
if (Camera == null)
|
||||
{
|
||||
Log.Error("Camera not found.");
|
||||
}
|
||||
}
|
||||
Log.Warning("Achtung.");
|
||||
|
||||
try
|
||||
{
|
||||
SubVoid();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
void SubVoid()
|
||||
{
|
||||
throw new Exception("Ouha!", new IndexOutOfRangeException("Bist du jecke2?!", new AccessViolationException("Haleluja")));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -99,11 +126,14 @@ namespace Sandbox
|
||||
|
||||
if (Input.IsKeyPressed(Key.E))
|
||||
Camera.DistanceFromPlayer += deltaTime;
|
||||
|
||||
|
||||
if (Input.IsKeyPressing(Key.Space))
|
||||
{
|
||||
force.Y += JumpForce;
|
||||
}
|
||||
|
||||
if (Input.IsKeyPressing(Key.N))
|
||||
SubVoid();
|
||||
|
||||
_rigidBody.ApplyForceToCenter(force);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<DebugType>portable</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
|
||||
@@ -71,8 +71,8 @@
|
||||
SpriteRendererComponent = {
|
||||
Color = {
|
||||
R = 1,
|
||||
G = 0.941886961,
|
||||
B = 0.401484549,
|
||||
G = 0.941887021,
|
||||
B = 0.401484489,
|
||||
A = 1
|
||||
},
|
||||
Sprite = "",
|
||||
@@ -162,7 +162,7 @@
|
||||
OrthographicHeight = 10,
|
||||
OrthographicNearPlane = 0,
|
||||
OrthographicFarPlane = 10,
|
||||
AspectRatio = 0.884925187,
|
||||
AspectRatio = 2.05582929,
|
||||
FixedAspectRatio = false
|
||||
},
|
||||
ScriptComponent = {
|
||||
@@ -195,8 +195,8 @@
|
||||
},
|
||||
TransformComponent = {
|
||||
Position = {
|
||||
X = -0.121203184,
|
||||
Y = 0.660160959,
|
||||
X = -0.121203206,
|
||||
Y = 0.660161078,
|
||||
Z = 0
|
||||
},
|
||||
Rotation = {
|
||||
@@ -234,37 +234,12 @@
|
||||
ScriptComponent = {
|
||||
ScriptClass = "Sandbox.MyTestEntity",
|
||||
Fields = [
|
||||
Bo = (Bool)false,
|
||||
By = (Byte)0,
|
||||
Us = (UShort)57,
|
||||
Ui = (UInt)54,
|
||||
Ul = (ULong)53,
|
||||
Sb = (SByte)-128,
|
||||
Sh = (Short)95,
|
||||
In = (Int)-149,
|
||||
Lo = (Long)82,
|
||||
Fl = (Float)-98.122963,
|
||||
Do = (Double)118,
|
||||
V2 = (float2){
|
||||
X = 11,
|
||||
Y = 12
|
||||
},
|
||||
V3 = (float3){
|
||||
X = 13,
|
||||
Y = 14,
|
||||
Z = 15
|
||||
},
|
||||
V4 = (float4){
|
||||
X = 14,
|
||||
Y = 17,
|
||||
Z = 18,
|
||||
W = 19
|
||||
},
|
||||
_rigidBody = (Component)15710354273720487680,
|
||||
TheEntity = (Entity)0,
|
||||
JumpForce = (Float)200,
|
||||
MoveForce = (Float)148,
|
||||
MyNumber = (Int)22,
|
||||
MyDouble = (Double)23
|
||||
Camera = (Entity)1491484622542812645
|
||||
] }
|
||||
},
|
||||
{
|
||||
@@ -301,7 +276,7 @@
|
||||
Color = {
|
||||
R = 0.985467017,
|
||||
G = 1,
|
||||
B = 0.569978058
|
||||
B = 0.569977939
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -348,8 +323,8 @@
|
||||
SpriteRendererComponent = {
|
||||
Color = {
|
||||
R = 0.425658971,
|
||||
G = 0.855207562,
|
||||
B = 0.0558161102,
|
||||
G = 0.855207443,
|
||||
B = 0.0558161177,
|
||||
A = 1
|
||||
},
|
||||
Sprite = "",
|
||||
@@ -363,14 +338,14 @@
|
||||
TransformComponent = {
|
||||
Position = {
|
||||
X = 6.74610233,
|
||||
Y = -2.03225899,
|
||||
Y = -2.03225946,
|
||||
Z = 0
|
||||
},
|
||||
Rotation = {
|
||||
X = 0,
|
||||
Y = 0,
|
||||
Z = -0.331792623,
|
||||
W = 0.943352342
|
||||
W = 0.94335258
|
||||
},
|
||||
Scale = {
|
||||
X = 5.29557419,
|
||||
@@ -409,7 +384,7 @@
|
||||
},
|
||||
SpriteRendererComponent = {
|
||||
Color = {
|
||||
R = 0.666116953,
|
||||
R = 0.666117013,
|
||||
G = 0.0600316115,
|
||||
B = 1,
|
||||
A = 1
|
||||
@@ -424,8 +399,8 @@
|
||||
},
|
||||
TransformComponent = {
|
||||
Position = {
|
||||
X = 15.2321301,
|
||||
Y = -1.98709249,
|
||||
X = 15.2321281,
|
||||
Y = -1.98709273,
|
||||
Z = 0
|
||||
},
|
||||
Rotation = {
|
||||
@@ -435,7 +410,7 @@
|
||||
W = 0.990847468
|
||||
},
|
||||
Scale = {
|
||||
X = 13.9764566,
|
||||
X = 13.9764528,
|
||||
Y = 1,
|
||||
Z = 1
|
||||
},
|
||||
@@ -471,7 +446,7 @@
|
||||
},
|
||||
SpriteRendererComponent = {
|
||||
Color = {
|
||||
R = 0.176544324,
|
||||
R = 0.176544309,
|
||||
G = 0.666713238,
|
||||
B = 0.687030852,
|
||||
A = 1
|
||||
@@ -487,24 +462,24 @@
|
||||
TransformComponent = {
|
||||
Position = {
|
||||
X = -6.27842855,
|
||||
Y = 2.62550211,
|
||||
Y = 2.62550163,
|
||||
Z = 0
|
||||
},
|
||||
Rotation = {
|
||||
X = 0,
|
||||
Y = 0,
|
||||
Z = 0.187087834,
|
||||
Z = 0.187087879,
|
||||
W = 0.982343197
|
||||
},
|
||||
Scale = {
|
||||
X = 0.999999523,
|
||||
X = 0.999999464,
|
||||
Y = 6.49634314,
|
||||
Z = 1
|
||||
},
|
||||
EditorEulerRotation = {
|
||||
X = 0,
|
||||
Y = 0,
|
||||
Z = 0.376393586
|
||||
Z = 0.376393616
|
||||
}
|
||||
},
|
||||
Rigidbody2D = {
|
||||
@@ -522,7 +497,7 @@
|
||||
},
|
||||
Density = 1,
|
||||
Friction = 0.5,
|
||||
Restitution = 0.899999976,
|
||||
Restitution = 0.899999857,
|
||||
RestitutionThreshold = 0.5
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -9,8 +9,8 @@
|
||||
AddressModeU = .Clamp,
|
||||
AddressModeV = .Clamp,
|
||||
AddressModeW = .Clamp,
|
||||
MipMinLOD = -340282346638528859811704183484516925440,
|
||||
MipMaxLOD = 340282346638528859811704183484516925440,
|
||||
MipMinLOD = -3.40282347e+38,
|
||||
MipMaxLOD = 3.40282347e+38,
|
||||
MaxAnisotropy = 1,
|
||||
BorderColor = {
|
||||
R = 1,
|
||||
|
||||
Binary file not shown.
@@ -9,12 +9,21 @@
|
||||
".NETStandard,Version=v2.0/": {
|
||||
"ScriptCore/1.0.0": {
|
||||
"dependencies": {
|
||||
"Half": "1.0.0",
|
||||
"NETStandard.Library": "2.0.3"
|
||||
},
|
||||
"runtime": {
|
||||
"ScriptCore.dll": {}
|
||||
}
|
||||
},
|
||||
"Half/1.0.0": {
|
||||
"runtime": {
|
||||
"lib/netstandard2.0/System.Half.dll": {
|
||||
"assemblyVersion": "1.0.0.0",
|
||||
"fileVersion": "1.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.NETCore.Platforms/1.1.0": {},
|
||||
"NETStandard.Library/2.0.3": {
|
||||
"dependencies": {
|
||||
@@ -29,6 +38,13 @@
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"Half/1.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-EPLLPQA1UjF9QM3ymNhWLhgcnBNc8e1po4qWRWTD3Hd9xiohYlkCob0QjDIbJs6Nvfd4eAbsjxIwRyh7httyXA==",
|
||||
"path": "half/1.0.0",
|
||||
"hashPath": "half.1.0.0.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.NETCore.Platforms/1.1.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
|
||||
@@ -33,7 +33,7 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
|
||||
|
||||
if (ImGui.BeginDragDropTarget())
|
||||
{
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM");
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.ContentBrowserItem);
|
||||
|
||||
if (payload != null)
|
||||
{
|
||||
@@ -78,7 +78,7 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
|
||||
|
||||
if (ImGui.BeginDragDropTarget())
|
||||
{
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM");
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.ContentBrowserItem);
|
||||
|
||||
if (payload != null)
|
||||
{
|
||||
@@ -120,7 +120,7 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
|
||||
|
||||
value = (float3)ColorRGB.LinearToSRGB((ColorRGB)value);
|
||||
|
||||
if (ImGui.ColorEdit3(displayName.Ptr, *(float[3]*)&value))
|
||||
if (ImGui.ColorEdit3(displayName.Ptr, ref *(float[3]*)&value))
|
||||
{
|
||||
value = (float3)ColorRGB.SRgbToLinear((ColorRGB)value);
|
||||
material.SetVariable(variable.Name, value);
|
||||
@@ -132,7 +132,7 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
|
||||
|
||||
value = (float4)ColorRGBA.LinearToSRGB((ColorRGBA)value);
|
||||
|
||||
if (ImGui.ColorEdit4(displayName.Ptr, *(float[4]*)&value))
|
||||
if (ImGui.ColorEdit4(displayName.Ptr, ref *(float[4]*)&value))
|
||||
{
|
||||
value = (float4)ColorRGBA.SRgbToLinear((ColorRGBA)value);
|
||||
material.SetVariable(variable.Name, value);
|
||||
@@ -149,7 +149,7 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
|
||||
|
||||
value = (float3)ColorRGB.LinearToSRGB((ColorRGB)value);
|
||||
|
||||
if (ImGui.ColorEdit3(displayName.Ptr, *(float[3]*)&value, .HDR | .Float))
|
||||
if (ImGui.ColorEdit3(displayName.Ptr, ref *(float[3]*)&value, .HDR | .Float))
|
||||
{
|
||||
value = (float3)ColorRGB.SRgbToLinear((ColorRGB)value);
|
||||
material.SetVariable(variable.Name, value);
|
||||
@@ -161,7 +161,7 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
|
||||
|
||||
value = (float4)ColorRGBA.LinearToSRGB((ColorRGBA)value);
|
||||
|
||||
if (ImGui.ColorEdit4(displayName.Ptr, *(float[4]*)&value, .HDR | .Float))
|
||||
if (ImGui.ColorEdit4(displayName.Ptr, ref *(float[4]*)&value, .HDR | .Float))
|
||||
{
|
||||
value = (float4)ColorRGBA.SRgbToLinear((ColorRGBA)value);
|
||||
material.SetVariable(variable.Name, value);
|
||||
|
||||
@@ -31,7 +31,58 @@ class AssetViewer : EditorWindow
|
||||
|
||||
ImGui.PushStyleVar(.CellPadding, .(0, 0));
|
||||
|
||||
bool alt_pressed = ImGui.GetIO().KeyAlt;
|
||||
ImGui.Columns(2);
|
||||
|
||||
if (ImGui.BeginChild("Assets"))
|
||||
{
|
||||
DrawAssetList();
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
|
||||
ImGui.NextColumn();
|
||||
|
||||
if (ImGui.BeginChild("Files"))
|
||||
{
|
||||
DrawAssetViewer();
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
|
||||
ImGui.Columns(1);
|
||||
|
||||
/*if (ImGui.BeginTable("AssetViewerTable", 2, .BordersInnerV | .Resizable | .Reorderable | .NoPadOuterX))
|
||||
{
|
||||
if (alt_pressed)
|
||||
{
|
||||
// Header anzeigen, damit sie neu angeordnet werden können
|
||||
ImGui.TableSetupColumn("Assets");
|
||||
ImGui.TableSetupColumn("Viewer");
|
||||
ImGui.TableHeadersRow();
|
||||
}
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
|
||||
if (ImGui.BeginChild("Assets"))
|
||||
{
|
||||
//DrawAssetList();
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
if (ImGui.BeginChild("Files"))
|
||||
{
|
||||
//DrawAssetViewer();
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
|
||||
ImGui.EndTable();
|
||||
}*/
|
||||
|
||||
/*bool alt_pressed = ImGui.GetIO().KeyAlt;
|
||||
|
||||
if (ImGui.BeginTable("AssetViewerTable", 2, .BordersInnerV | .Resizable | .Reorderable | .NoPadOuterX))
|
||||
{
|
||||
@@ -42,13 +93,12 @@ class AssetViewer : EditorWindow
|
||||
ImGui.TableSetupColumn("Viewer");
|
||||
ImGui.TableHeadersRow();
|
||||
}
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
|
||||
|
||||
if (ImGui.BeginChild("Assets"))
|
||||
{
|
||||
DrawAssetList();
|
||||
//DrawAssetList();
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
@@ -57,13 +107,13 @@ class AssetViewer : EditorWindow
|
||||
|
||||
if (ImGui.BeginChild("Files"))
|
||||
{
|
||||
DrawAssetViewer();
|
||||
//DrawAssetViewer();
|
||||
|
||||
ImGui.EndChild();
|
||||
}
|
||||
|
||||
ImGui.EndTable();
|
||||
}
|
||||
}*/
|
||||
|
||||
ImGui.PopStyleVar(1);
|
||||
|
||||
@@ -211,7 +261,7 @@ class TexturererViewerer
|
||||
|
||||
float maxDimension = max(width, height);
|
||||
|
||||
ImGui.SliderFloat2("Position", *(float[2]*)&_position, 2 * -maxDimension * _zoom, 2 * maxDimension * _zoom);
|
||||
ImGui.SliderFloat2("Position", ref *(float[2]*)&_position, 2 * -maxDimension * _zoom, 2 * maxDimension * _zoom);
|
||||
|
||||
ImGui.Separator();
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ using GlitchyEngine.Renderer;
|
||||
using GlitchyEngine;
|
||||
using GlitchyEngine.Content;
|
||||
using GlitchyEngine.Scripting;
|
||||
using GlitchyEngine.Core;
|
||||
using Mono;
|
||||
|
||||
namespace GlitchyEditor.EditWindows
|
||||
{
|
||||
@@ -278,7 +280,7 @@ namespace GlitchyEditor.EditWindows
|
||||
|
||||
if (ImGui.BeginDragDropTarget())
|
||||
{
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM");
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.ContentBrowserItem);
|
||||
|
||||
if (payload != null)
|
||||
{
|
||||
@@ -306,7 +308,7 @@ namespace GlitchyEditor.EditWindows
|
||||
|
||||
if (ImGui.BeginDragDropTarget())
|
||||
{
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM");
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.ContentBrowserItem);
|
||||
|
||||
if (payload != null)
|
||||
{
|
||||
@@ -338,7 +340,7 @@ namespace GlitchyEditor.EditWindows
|
||||
|
||||
if (ImGui.BeginDragDropTarget())
|
||||
{
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM");
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.ContentBrowserItem);
|
||||
|
||||
if (payload != null)
|
||||
{
|
||||
@@ -512,11 +514,89 @@ namespace GlitchyEditor.EditWindows
|
||||
scriptInstance.SetFieldValue<T>(scriptField, value);
|
||||
}
|
||||
|
||||
T GetData<T>(void* instance, ScriptField scriptField)
|
||||
{
|
||||
T data = default;
|
||||
Mono.mono_field_get_value((.)instance, scriptField.[Friend]_monoField, &data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void GetData<T>(void* instance, ScriptField scriptField, T* data)
|
||||
{
|
||||
Mono.mono_field_get_value((.)instance, scriptField.[Friend]_monoField, data);
|
||||
}
|
||||
|
||||
void SetData<T>(void* instance, ScriptField scriptField, in T value)
|
||||
{
|
||||
Mono.mono_field_set_value((.)instance, scriptField.[Friend]_monoField, &value);
|
||||
}
|
||||
|
||||
void SetData<T>(void* instance, ScriptField scriptField, T* data)
|
||||
{
|
||||
Mono.mono_field_set_value((.)instance, scriptField.[Friend]_monoField, data);
|
||||
}
|
||||
|
||||
if (scriptComponent.Instance?.IsInitialized == true)
|
||||
{
|
||||
SharpClass sharpClass = scriptComponent.Instance.ScriptClass;
|
||||
ScriptInstance scriptInstance = scriptComponent.Instance;
|
||||
|
||||
/*void DoFunnyStuff(void* instance, SharpType sharpType)
|
||||
{
|
||||
for (let (fieldName, scriptField) in sharpType.Fields)
|
||||
{
|
||||
var monoField = scriptField.[Friend]_monoField;
|
||||
|
||||
switch (scriptField.FieldType)
|
||||
{
|
||||
case .Float:
|
||||
var value = GetData<float>(instance, scriptField);
|
||||
if (ImGui.DragScalar(fieldName.ToScopeCStr!(), .Float, &value))
|
||||
SetData(instance, scriptField, value);
|
||||
|
||||
case .Struct:
|
||||
{
|
||||
var v = Mono.mono_field_get_value_object(ScriptEngine.[Friend]s_AppDomain, scriptField.[Friend]_monoField, (.)instance);
|
||||
|
||||
void* dataPtr = Mono.mono_object_unbox(v);
|
||||
|
||||
Span<uint8> data = .((.)dataPtr, scriptField.SizeInBytes);
|
||||
|
||||
if (ImGui.CollapsingHeader(fieldName.Ptr))
|
||||
{
|
||||
DoFunnyStuff(dataPtr, scriptField.SharpType);
|
||||
}
|
||||
|
||||
SetData<MonoObject>(instance, scriptField, v);
|
||||
|
||||
//Mono.mono_field_set_value_object(ScriptEngine.[Friend]s_AppDomain, scriptField.[Friend]_monoField, (.)instance);
|
||||
//uint8* data = ;
|
||||
|
||||
/*uint8[] data = scope .[scriptField.SizeInBytes];
|
||||
|
||||
GetData(instance, scriptField, data.Ptr);
|
||||
|
||||
if (ImGui.CollapsingHeader(fieldName.Ptr))
|
||||
{
|
||||
DoFunnyStuff(data.Ptr, scriptField.SharpType);
|
||||
}
|
||||
|
||||
MonoObject* boxed = Mono.mono_value_box(ScriptEngine.[Friend]s_AppDomain, ((SharpClass)scriptField.SharpType).[Friend]_monoClass, data.Ptr);
|
||||
|
||||
SetData<MonoObject>(instance, scriptField, boxed);*/
|
||||
|
||||
//Mono.mono_field_get_value(instance, scriptField.[Friend]_monoField, data.Ptr);
|
||||
|
||||
}
|
||||
default:
|
||||
//Log.EngineLogger.Error($"Unhandled field type {scriptField.FieldType}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DoFunnyStuff(scriptInstance.[Friend]_instance, sharpClass);*/
|
||||
|
||||
for (let (fieldName, scriptField) in sharpClass.Fields)
|
||||
{
|
||||
var monoField = scriptField.[Friend]_monoField;
|
||||
@@ -592,6 +672,22 @@ namespace GlitchyEditor.EditWindows
|
||||
// TODO!
|
||||
case .Struct:
|
||||
// TODO!
|
||||
/*{
|
||||
uint8[] data = scope .[scriptField.SizeInBytes];
|
||||
|
||||
Mono.mono_field_get_value(scriptInstance.[Friend]_instance, scriptField.[Friend]_monoField, data.Ptr);
|
||||
|
||||
//scriptField.
|
||||
|
||||
//scriptInstance.GetFieldValue();
|
||||
|
||||
//scriptInstance.ScriptClass.Fields[]
|
||||
/*
|
||||
var value = GetFieldValue<double>(scriptInstance, scriptField);
|
||||
if (ImGui.DragScalar(fieldName.ToScopeCStr!(), .Double, &value))
|
||||
SetFieldValue(scriptInstance, scriptField, value);
|
||||
*/
|
||||
}*/
|
||||
default:
|
||||
Log.EngineLogger.Error($"Unhandled field type {scriptField.FieldType}");
|
||||
}
|
||||
@@ -601,107 +697,111 @@ namespace GlitchyEditor.EditWindows
|
||||
{
|
||||
let scriptFields = ScriptEngine.GetScriptFieldMap(entity);
|
||||
|
||||
for (var (name, field) in ref scriptFields)
|
||||
for (var (fieldName, field) in ref scriptFields)
|
||||
{
|
||||
switch (field.Type)
|
||||
{
|
||||
case .Bool:
|
||||
var value = field.GetData<bool>();
|
||||
if (ImGui.Checkbox(name.CStr(), &value))
|
||||
if (ImGui.Checkbox(fieldName.CStr(), &value))
|
||||
field.SetData(value);
|
||||
|
||||
case .SByte:
|
||||
var value = field.GetData<int8>();
|
||||
if (ImGui.DragScalar(name.CStr(), .S8, &value))
|
||||
if (ImGui.DragScalar(fieldName.CStr(), .S8, &value))
|
||||
field.SetData(value);
|
||||
case .Short:
|
||||
var value = field.GetData<int16>();
|
||||
if (ImGui.DragScalar(fieldName.CStr(), .S16, &value))
|
||||
field.SetData(value);
|
||||
case .Short:
|
||||
var value = field.GetData<int16>();
|
||||
if (ImGui.DragScalar(name.CStr(), .S16, &value))
|
||||
field.SetData(value);
|
||||
case .Int:
|
||||
var value = field.GetData<int32>();
|
||||
if (ImGui.DragScalar(name.CStr(), .S32, &value))
|
||||
field.SetData(value);
|
||||
var value = field.GetData<int32>();
|
||||
if (ImGui.DragScalar(fieldName.CStr(), .S32, &value))
|
||||
field.SetData(value);
|
||||
case .Int2:
|
||||
var value = field.GetData<int2>();
|
||||
if (ImGui.DragScalarN(name.CStr(), .S32, &value, 2))
|
||||
field.SetData(value);
|
||||
var value = field.GetData<int2>();
|
||||
if (ImGui.DragScalarN(fieldName.CStr(), .S32, &value, 2))
|
||||
field.SetData(value);
|
||||
case .Int3:
|
||||
var value = field.GetData<int3>();
|
||||
if (ImGui.DragScalarN(name.CStr(), .S32, &value, 3))
|
||||
field.SetData(value);
|
||||
var value = field.GetData<int3>();
|
||||
if (ImGui.DragScalarN(fieldName.CStr(), .S32, &value, 3))
|
||||
field.SetData(value);
|
||||
case .Int4:
|
||||
var value = field.GetData<int4>();
|
||||
if (ImGui.DragScalarN(name.CStr(), .S32, &value, 4))
|
||||
field.SetData(value);
|
||||
var value = field.GetData<int4>();
|
||||
if (ImGui.DragScalarN(fieldName.CStr(), .S32, &value, 4))
|
||||
field.SetData(value);
|
||||
case .Long:
|
||||
var value = field.GetData<int64>();
|
||||
if (ImGui.DragScalar(name.CStr(), .S64, &value))
|
||||
field.SetData(value);
|
||||
var value = field.GetData<int64>();
|
||||
if (ImGui.DragScalar(fieldName.CStr(), .S64, &value))
|
||||
field.SetData(value);
|
||||
|
||||
case .Byte:
|
||||
var value = field.GetData<uint8>();
|
||||
if (ImGui.DragScalar(name.CStr(), .U8, &value))
|
||||
field.SetData(value);
|
||||
var value = field.GetData<uint8>();
|
||||
if (ImGui.DragScalar(fieldName.CStr(), .U8, &value))
|
||||
field.SetData(value);
|
||||
case .UShort:
|
||||
var value = field.GetData<uint16>();
|
||||
if (ImGui.DragScalar(name.CStr(), .U16, &value))
|
||||
field.SetData(value);
|
||||
var value = field.GetData<uint16>();
|
||||
if (ImGui.DragScalar(fieldName.CStr(), .U16, &value))
|
||||
field.SetData(value);
|
||||
case .UInt:
|
||||
var value = field.GetData<uint32>();
|
||||
if (ImGui.DragScalar(name.CStr(), .U32, &value))
|
||||
field.SetData(value);
|
||||
var value = field.GetData<uint32>();
|
||||
if (ImGui.DragScalar(fieldName.CStr(), .U32, &value))
|
||||
field.SetData(value);
|
||||
case .ULong:
|
||||
var value = field.GetData<uint64>();
|
||||
if (ImGui.DragScalar(name.CStr(), .U64, &value))
|
||||
field.SetData(value);
|
||||
var value = field.GetData<uint64>();
|
||||
if (ImGui.DragScalar(fieldName.CStr(), .U64, &value))
|
||||
field.SetData(value);
|
||||
|
||||
case .Float:
|
||||
var value = field.GetData<float>();
|
||||
if (ImGui.DragScalar(name.CStr(), .Float, &value))
|
||||
field.SetData(value);
|
||||
var value = field.GetData<float>();
|
||||
if (ImGui.DragScalar(fieldName.CStr(), .Float, &value))
|
||||
field.SetData(value);
|
||||
case .float2:
|
||||
var value = field.GetData<float2>();
|
||||
if (ImGui.Editfloat2(name, ref value))
|
||||
field.SetData(value);
|
||||
var value = field.GetData<float2>();
|
||||
if (ImGui.Editfloat2(fieldName, ref value))
|
||||
field.SetData(value);
|
||||
case .float3:
|
||||
var value = field.GetData<float3>();
|
||||
if (ImGui.Editfloat3(name, ref value))
|
||||
field.SetData(value);
|
||||
var value = field.GetData<float3>();
|
||||
if (ImGui.Editfloat3(fieldName, ref value))
|
||||
field.SetData(value);
|
||||
case .float4:
|
||||
var value = field.GetData<float4>();
|
||||
if (ImGui.Editfloat4(name, ref value))
|
||||
field.SetData(value);
|
||||
var value = field.GetData<float4>();
|
||||
if (ImGui.Editfloat4(fieldName, ref value))
|
||||
field.SetData(value);
|
||||
|
||||
case .Double:
|
||||
var value = field.GetData<double>();
|
||||
if (ImGui.DragScalar(name.CStr(), .Double, &value))
|
||||
field.SetData(value);
|
||||
var value = field.GetData<double>();
|
||||
if (ImGui.DragScalar(fieldName.CStr(), .Double, &value))
|
||||
field.SetData(value);
|
||||
case .Double2:
|
||||
var value = field.GetData<double2>();
|
||||
if (ImGui.DragScalarN(name.CStr(), .Double, &value, 2))
|
||||
field.SetData(value);
|
||||
var value = field.GetData<double2>();
|
||||
if (ImGui.DragScalarN(fieldName.CStr(), .Double, &value, 2))
|
||||
field.SetData(value);
|
||||
case .Double3:
|
||||
var value = field.GetData<double3>();
|
||||
if (ImGui.DragScalarN(name.CStr(), .Double, &value, 3))
|
||||
field.SetData(value);
|
||||
var value = field.GetData<double3>();
|
||||
if (ImGui.DragScalarN(fieldName.CStr(), .Double, &value, 3))
|
||||
field.SetData(value);
|
||||
case .Double4:
|
||||
var value = field.GetData<double4>();
|
||||
if (ImGui.DragScalarN(name.CStr(), .Double, &value, 4))
|
||||
field.SetData(value);
|
||||
var value = field.GetData<double4>();
|
||||
if (ImGui.DragScalarN(fieldName.CStr(), .Double, &value, 4))
|
||||
field.SetData(value);
|
||||
|
||||
case .Enum:
|
||||
// TODO!
|
||||
|
||||
ShowEnumSelector(field, fieldName, scriptClass);
|
||||
//case .String:
|
||||
// TODO!
|
||||
|
||||
case .Entity:
|
||||
// TODO!
|
||||
ShowEntityReceiver(field, fieldName, scriptClass);
|
||||
case .Component:
|
||||
ShowComponentReceiver(field, fieldName, scriptClass);
|
||||
|
||||
case .Struct:
|
||||
// TODO!
|
||||
|
||||
case .Class:
|
||||
// We don't support editing classes
|
||||
|
||||
default:
|
||||
Log.EngineLogger.Error($"Unhandled field type {field.Type}");
|
||||
}
|
||||
@@ -709,6 +809,201 @@ namespace GlitchyEditor.EditWindows
|
||||
}
|
||||
}
|
||||
|
||||
private static void ShowEnumSelector(ScriptFieldInstance* field, StringView fieldName, ScriptClass scriptClass)
|
||||
{
|
||||
ScriptField scriptField = scriptClass.Fields[fieldName];
|
||||
SharpEnum enumType = scriptField.SharpType as SharpEnum;
|
||||
|
||||
Log.EngineLogger.Assert(enumType != null, "Enum must have a SharpEnum!");
|
||||
|
||||
// Simply get Enum as a uint64
|
||||
var fieldValue = field.GetData<uint64>();
|
||||
|
||||
StringView valueName = "<Invalid Value>";
|
||||
|
||||
if (enumType.Values.TryGetValue(fieldValue, let enumValue))
|
||||
valueName = enumValue.Name;
|
||||
|
||||
if (ImGui.BeginCombo(fieldName.Ptr, valueName.Ptr))
|
||||
{
|
||||
for (let (entryValue, enumEntry) in enumType.Values)
|
||||
{
|
||||
if (ImGui.Selectable(enumEntry.Name.Ptr, fieldValue == entryValue))
|
||||
field.SetData(entryValue);
|
||||
}
|
||||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
}
|
||||
|
||||
private static Entity? ShowEntitySelector()
|
||||
{
|
||||
static char8[128] entitySearch = .();
|
||||
|
||||
Entity? result = null;
|
||||
|
||||
if (ImGui.BeginPopup("ENTITY_SELECTOR"))
|
||||
{
|
||||
ImGui.TextUnformatted("Search:");
|
||||
ImGui.SameLine();
|
||||
|
||||
if (ImGui.InputText("##entitySearcher", &entitySearch, (uint64)entitySearch.Count))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void ShowEntityReceiver(ScriptFieldInstance* field, StringView fieldName, ScriptClass scriptClass)
|
||||
{
|
||||
var entityId = field.GetData<UUID>();
|
||||
|
||||
Result<Entity> fieldEntity = Editor.Instance.CurrentScene.GetEntityByID(entityId);
|
||||
|
||||
String entityName = scope .(32);
|
||||
|
||||
if (entityId == UUID(0))
|
||||
entityName.Set("None");
|
||||
else if (fieldEntity case .Ok(Entity e))
|
||||
entityName.Set(e.Name);
|
||||
else
|
||||
entityName..Clear().AppendF($"Missing entity ({entityId})");
|
||||
|
||||
ImGui.Text($"{fieldName}: ");
|
||||
ImGui.SameLine();
|
||||
|
||||
if (ImGui.Button(entityName))
|
||||
{
|
||||
if (fieldEntity case .Ok)
|
||||
Editor.Instance.EntityHierarchyWindow.HighlightEntity(fieldEntity);
|
||||
}
|
||||
|
||||
if (ImGui.BeginDragDropTarget())
|
||||
{
|
||||
ImGui.Payload* peekPayload = ImGui.AcceptDragDropPayload(.Entity, .AcceptPeekOnly);
|
||||
|
||||
bool allowDrop = false;
|
||||
|
||||
if (peekPayload != null)
|
||||
{
|
||||
Entity draggedEntity = *(Entity*)peekPayload.Data;
|
||||
|
||||
ScriptClass draggedScriptClass = ScriptEngine.[Friend]s_EntityRoot;
|
||||
|
||||
if (draggedEntity.TryGetComponent<ScriptComponent>(let draggedScript))
|
||||
{
|
||||
var draggedClassName = draggedScript.ScriptClassName;
|
||||
draggedScriptClass = ScriptEngine.GetScriptClass(draggedClassName);
|
||||
|
||||
}
|
||||
|
||||
// TODO: I don't like the fact, that we are using mono directly
|
||||
|
||||
ScriptField scriptField = scriptClass.Fields[fieldName];
|
||||
var fieldMonoClass = Mono.mono_type_get_class(scriptField.GetMonoType());
|
||||
|
||||
allowDrop = draggedScriptClass.[Friend]IsSubclass(fieldMonoClass);
|
||||
}
|
||||
|
||||
if (allowDrop)
|
||||
{
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.Entity);
|
||||
|
||||
if (payload != null)
|
||||
{
|
||||
Log.EngineLogger.AssertDebug(payload.DataSize == sizeof(Entity));
|
||||
|
||||
Entity droppedEntity = *(Entity*)payload.Data;
|
||||
|
||||
if (droppedEntity.IsValid)
|
||||
field.SetData<UUID>(droppedEntity.UUID);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndDragDropTarget();
|
||||
}
|
||||
}
|
||||
|
||||
//private static Entity?
|
||||
|
||||
private static void ShowComponentReceiver(ScriptFieldInstance* field, StringView fieldName, ScriptClass scriptClass)
|
||||
{
|
||||
var entityId = field.GetData<UUID>();
|
||||
|
||||
Result<Entity> fieldEntity = Editor.Instance.CurrentScene.GetEntityByID(entityId);
|
||||
|
||||
String entityName = scope .(32);
|
||||
|
||||
if (entityId == UUID(0))
|
||||
entityName.Set("None");
|
||||
else if (fieldEntity case .Ok(Entity e))
|
||||
entityName.Set(e.Name);
|
||||
else
|
||||
entityName..Clear().AppendF($"Missing reference ({entityId})");
|
||||
|
||||
ImGui.Text($"{fieldName}: ");
|
||||
ImGui.SameLine();
|
||||
|
||||
if (ImGui.Button(entityName))
|
||||
{
|
||||
if (fieldEntity case .Ok)
|
||||
Editor.Instance.EntityHierarchyWindow.HighlightEntity(fieldEntity);
|
||||
}
|
||||
|
||||
if (ImGui.BeginDragDropTarget())
|
||||
{
|
||||
ImGui.Payload* peekPayload = ImGui.AcceptDragDropPayload(.Entity, .AcceptPeekOnly);
|
||||
|
||||
bool allowDrop = false;
|
||||
|
||||
if (peekPayload != null)
|
||||
{
|
||||
Entity draggedEntity = *(Entity*)peekPayload.Data;
|
||||
|
||||
// TODO: I don't like the fact, that we are using mono directly
|
||||
|
||||
ScriptField scriptField = scriptClass.Fields[fieldName];
|
||||
|
||||
// For some reason we have to retrieve the MonoType like this. Using scriptField.GetMonoType() directly returns the wrong type...
|
||||
MonoReflectionType* reflectionType = Mono.mono_type_get_object(ScriptEngine.[Friend]s_AppDomain, scriptField.GetMonoType());
|
||||
MonoType* actualMonoType = Mono.mono_reflection_type_get_type(reflectionType);
|
||||
|
||||
// TODO: We shouldn't abuse the script glue like that.
|
||||
// ScriptGlue should only be called by C#, not by Beef.
|
||||
if (ScriptGlue.[Friend]s_HasComponentMethods.TryGetValue(actualMonoType, let has_component))
|
||||
{
|
||||
allowDrop = has_component(draggedEntity);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.EngineLogger.Warning($"No HasComponent-Function found for field {scriptField.Name}");
|
||||
allowDrop = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (allowDrop)
|
||||
{
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.Entity);
|
||||
|
||||
if (payload != null)
|
||||
{
|
||||
Log.EngineLogger.AssertDebug(payload.DataSize == sizeof(Entity));
|
||||
|
||||
Entity droppedEntity = *(Entity*)payload.Data;
|
||||
|
||||
if (droppedEntity.IsValid)
|
||||
field.SetData<UUID>(droppedEntity.UUID);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndDragDropTarget();
|
||||
}
|
||||
}
|
||||
|
||||
private static void LabelColumn(StringView label)
|
||||
{
|
||||
ImGui.TextUnformatted(label);
|
||||
@@ -773,7 +1068,7 @@ namespace GlitchyEditor.EditWindows
|
||||
|
||||
if (ImGui.BeginDragDropTarget())
|
||||
{
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM");
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.ContentBrowserItem);
|
||||
|
||||
if (payload != null)
|
||||
{
|
||||
|
||||
@@ -270,7 +270,7 @@ namespace GlitchyEditor.EditWindows
|
||||
|
||||
SubTexture2D image = s_FolderTexture;
|
||||
|
||||
ImGui.ImageButton(image, (.)(DirectoryItemSize - padding));
|
||||
ImGui.ImageButton("", image, (.)(DirectoryItemSize - padding));
|
||||
|
||||
ImGui.PopStyleColor();
|
||||
|
||||
@@ -310,7 +310,7 @@ namespace GlitchyEditor.EditWindows
|
||||
// TODO: preview images
|
||||
SubTexture2D image = entry->IsDirectory ? s_FolderTexture : s_FileTexture;
|
||||
|
||||
ImGui.ImageButton(image, (.)(DirectoryItemSize - padding));
|
||||
ImGui.ImageButton("FileImage", image, (.)(DirectoryItemSize - padding));
|
||||
|
||||
ImGui.PopStyleColor();
|
||||
|
||||
@@ -324,7 +324,7 @@ namespace GlitchyEditor.EditWindows
|
||||
|
||||
Path.Fixup(fullpath);
|
||||
|
||||
ImGui.SetDragDropPayload("CONTENT_BROWSER_ITEM", fullpath.CStr(), (.)fullpath.Length, .Once);
|
||||
ImGui.SetDragDropPayload(.ContentBrowserItem, fullpath.CStr(), (.)fullpath.Length, .Once);
|
||||
|
||||
ImGui.EndDragDropSource();
|
||||
}
|
||||
@@ -370,7 +370,7 @@ namespace GlitchyEditor.EditWindows
|
||||
String fullpath = scope String(entry->Path);
|
||||
fullpath.AppendF($"#{subAsset.Name}");
|
||||
|
||||
ImGui.SetDragDropPayload("CONTENT_BROWSER_ITEM", fullpath.CStr(), (.)fullpath.Length, .Once);
|
||||
ImGui.SetDragDropPayload(.ContentBrowserItem, fullpath.CStr(), (.)fullpath.Length, .Once);
|
||||
|
||||
ImGui.EndDragDropSource();
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace GlitchyEditor.EditWindows
|
||||
{
|
||||
if (ImGui.BeginDragDropTarget())
|
||||
{
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM");
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.ContentBrowserItem);
|
||||
|
||||
if (payload != null)
|
||||
{
|
||||
|
||||
@@ -21,8 +21,26 @@ namespace GlitchyEditor.EditWindows
|
||||
|
||||
private List<Entity> _selectedEntities = new .() ~ delete _;
|
||||
|
||||
private Entity _entityToHighlight;
|
||||
|
||||
public List<Entity> SelectedEntities => _selectedEntities;
|
||||
|
||||
private List<Entity> _entitiesToUnfold = new .() ~ delete _;
|
||||
|
||||
public void HighlightEntity(Entity e)
|
||||
{
|
||||
_entityToHighlight = e;
|
||||
|
||||
Entity walker = _entityToHighlight;
|
||||
|
||||
while (walker.Parent != null)
|
||||
{
|
||||
walker = walker.Parent.Value;
|
||||
|
||||
_entitiesToUnfold.Add(walker);
|
||||
}
|
||||
}
|
||||
|
||||
public this(Editor editor, Scene scene)
|
||||
{
|
||||
_editor = editor;
|
||||
@@ -322,8 +340,21 @@ namespace GlitchyEditor.EditWindows
|
||||
if(inSelectedList)
|
||||
flags |= .Selected;
|
||||
|
||||
if (_entitiesToUnfold.Contains(tree.Value))
|
||||
{
|
||||
_entitiesToUnfold.Remove(tree.Value);
|
||||
|
||||
ImGui.SetNextItemOpen(true, .None);
|
||||
}
|
||||
|
||||
bool isOpen = ImGui.TreeNodeEx((void*)(uint)tree.Value.Handle.[Friend]Index, flags, $"{name}");
|
||||
|
||||
if (_entityToHighlight == tree.Value)
|
||||
{
|
||||
ImGui.SetScrollHereY(0);
|
||||
_entityToHighlight = .();
|
||||
}
|
||||
|
||||
ImGui.PushID((void*)(uint)tree.Value.Handle.[Friend]Index);
|
||||
|
||||
bool deleted = false;
|
||||
@@ -341,9 +372,13 @@ namespace GlitchyEditor.EditWindows
|
||||
if (deleted)
|
||||
return;
|
||||
|
||||
bool isDragged = false;
|
||||
|
||||
if(ImGui.BeginDragDropSource())
|
||||
{
|
||||
ImGui.SetDragDropPayload("DND_Entity", &tree.Value, sizeof(Entity));
|
||||
isDragged = true;
|
||||
|
||||
ImGui.SetDragDropPayload(.Entity, &tree.Value, sizeof(Entity));
|
||||
|
||||
ImGui.Text(name);
|
||||
|
||||
@@ -352,7 +387,7 @@ namespace GlitchyEditor.EditWindows
|
||||
|
||||
if(ImGui.BeginDragDropTarget())
|
||||
{
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("DND_Entity");
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.Entity);
|
||||
|
||||
if(payload != null)
|
||||
{
|
||||
@@ -395,7 +430,7 @@ namespace GlitchyEditor.EditWindows
|
||||
|
||||
bool clicked = ImGui.IsItemClicked(.Left);
|
||||
bool clickedRight = ImGui.IsItemClicked(.Right);
|
||||
|
||||
|
||||
if(isOpen)
|
||||
{
|
||||
for(var child in tree.Children)
|
||||
@@ -407,6 +442,12 @@ namespace GlitchyEditor.EditWindows
|
||||
}
|
||||
|
||||
if (clicked || clickedRight)
|
||||
{
|
||||
lastClickedEntity = tree.Value;
|
||||
}
|
||||
|
||||
//if (!isDragged && (clicked || clickedRight))
|
||||
if (!isDragged && (!ImGui.IsMouseDown(.Left) && !ImGui.IsMouseDown(.Right) && ImGui.IsItemHovered()) && tree.Value == lastClickedEntity)
|
||||
{
|
||||
if (inSelectedList && !clickedRight)
|
||||
{
|
||||
@@ -418,9 +459,13 @@ namespace GlitchyEditor.EditWindows
|
||||
SelectEntity(tree.Value, !ImGui.GetIO().KeyCtrl && !clickedRight);
|
||||
inSelectedList = true;
|
||||
}
|
||||
|
||||
lastClickedEntity = .();
|
||||
}
|
||||
}
|
||||
|
||||
private static Entity lastClickedEntity;
|
||||
|
||||
private void ShowEntityHierarchy()
|
||||
{
|
||||
StringView searchString = StringView(&_entitySearchChars);
|
||||
@@ -464,7 +509,7 @@ namespace GlitchyEditor.EditWindows
|
||||
{
|
||||
if(ImGui.BeginDragDropTarget())
|
||||
{
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("DND_Entity");
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.Entity);
|
||||
|
||||
if(payload != null)
|
||||
{
|
||||
@@ -527,6 +572,10 @@ namespace GlitchyEditor.EditWindows
|
||||
ImGuiPrintEntityTree(scope .(entity));
|
||||
}
|
||||
}
|
||||
|
||||
// If the mouse was released and no entity took the chance to become selected we probably hovered the background while releasing -> select no entity
|
||||
if (!ImGui.IsMouseDown(.Left) && !ImGui.IsMouseDown(.Right))
|
||||
lastClickedEntity = .();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace GlitchyEditor.EditWindows
|
||||
{
|
||||
if (ImGui.BeginDragDropTarget())
|
||||
{
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM");
|
||||
ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.ContentBrowserItem);
|
||||
|
||||
if (payload != null)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,375 @@
|
||||
using System;
|
||||
using ImGui;
|
||||
using System.Collections;
|
||||
using GlitchyEngine.Core;
|
||||
using GlitchyEngine.World;
|
||||
using GlitchLog;
|
||||
using GlitchyEngine.Scripting;
|
||||
using GlitchyEngine.Renderer;
|
||||
|
||||
namespace GlitchyEditor.EditWindows;
|
||||
|
||||
enum MessageType
|
||||
{
|
||||
case None = 0;
|
||||
case Trace = 1;
|
||||
case Info = 2;
|
||||
case Warning = 4;
|
||||
case Error = 8;
|
||||
|
||||
public this(LogLevel level)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case .Error:
|
||||
this = Error;
|
||||
case .Warning:
|
||||
this = Warning;
|
||||
case .Info:
|
||||
this = Info;
|
||||
case .Trace:
|
||||
this = Trace;
|
||||
default:
|
||||
this = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MessageSource
|
||||
{
|
||||
public UUID? Entity = null;
|
||||
public StringView? ScriptName = null;
|
||||
public int? Line = null;
|
||||
|
||||
/// If true, the message is only meant for engine developers... so only me :(
|
||||
public bool IsEngineMessage = false;
|
||||
|
||||
public MonoExceptionHelper Exception = null ~ _?.ReleaseRef();
|
||||
|
||||
public String AdditionalData = null ~ delete _;
|
||||
}
|
||||
|
||||
class LogMessage
|
||||
{
|
||||
private String _message ~ delete _;
|
||||
|
||||
public MessageType MessageType { get; private set; }
|
||||
|
||||
public DateTime Timestamp { get; private set; }
|
||||
|
||||
public MessageSource Source { get; private set; } ~ delete _;
|
||||
|
||||
public StringView Message => _message;
|
||||
|
||||
public this(DateTime timestamp, StringView message, MessageType logLevel, MessageSource ownSource)
|
||||
{
|
||||
Timestamp = timestamp;
|
||||
_message = new String(message);
|
||||
MessageType = logLevel;
|
||||
Source = ownSource;
|
||||
}
|
||||
}
|
||||
|
||||
class LogWindow : EditorWindow
|
||||
{
|
||||
public const String s_WindowTitle = "Log";
|
||||
|
||||
private append List<LogMessage> _messages = .() ~ ClearAndDeleteItems!(_);
|
||||
|
||||
public static SubTexture2D s_ErrorIcon;
|
||||
public static SubTexture2D s_WarningIcon;
|
||||
public static SubTexture2D s_InfoIcon;
|
||||
public static SubTexture2D s_TraceIcon;
|
||||
|
||||
private bool _showGameMessages = true;
|
||||
private bool _showEngineMessages = false;
|
||||
private bool _autoScroll = true;
|
||||
private bool _collapseMessages = true;
|
||||
|
||||
private MessageType _visibleMessageTypes = .Error | .Warning | .Info | .Trace;
|
||||
|
||||
protected override void InternalShow()
|
||||
{
|
||||
defer { ImGui.End(); }
|
||||
if(!ImGui.Begin(s_WindowTitle, &_open, .MenuBar))
|
||||
return;
|
||||
|
||||
ShowMenuBar();
|
||||
|
||||
ShowMessages();
|
||||
}
|
||||
|
||||
private void ShowMenuBar()
|
||||
{
|
||||
if(ImGui.BeginMenuBar())
|
||||
{
|
||||
if (ImGui.MenuItem("Clear"))
|
||||
{
|
||||
ClearLog();
|
||||
}
|
||||
|
||||
if (ImGui.BeginMenu("Filter"))
|
||||
{
|
||||
ImGui.Checkbox("Show game messages", &_showGameMessages);
|
||||
ImGui.AttachTooltip("If checked, the log will show messages generated by the game (e.g. scripts).");
|
||||
|
||||
ImGui.Checkbox("Show engine messages", &_showEngineMessages);
|
||||
ImGui.AttachTooltip("""
|
||||
If checked, the log will show messages generated by the engine.
|
||||
These messages are usually only necessary for engine debugging/development and don't provide practical information for game developers.
|
||||
""");
|
||||
|
||||
ImGui.EndMenu();
|
||||
}
|
||||
|
||||
ImGui.Checkbox("Collapse", &_collapseMessages);
|
||||
ImGui.AttachTooltip("If checked, identical messages will be collapsed into one.");
|
||||
|
||||
var maxSpace = ImGui.GetFontSize();
|
||||
|
||||
ImGui.Vec2 buttonSize = .(maxSpace, maxSpace);
|
||||
|
||||
var col = ImGui.GetStyleColorVec4(.Button);
|
||||
ImGui.PushStyleVar(.FramePadding, ImGui.Vec2(2, 2));
|
||||
|
||||
if (_visibleMessageTypes.HasFlag(.Trace))
|
||||
ImGui.PushStyleColor(.Button, *col);
|
||||
else
|
||||
ImGui.PushStyleColor(.Button, .(0, 0, 0, 0));
|
||||
|
||||
if (ImGui.ImageButtonEx(1, s_TraceIcon, buttonSize, .Zero, .Ones))
|
||||
_visibleMessageTypes ^= .Trace;
|
||||
|
||||
ImGui.PopStyleColor();
|
||||
|
||||
if (_visibleMessageTypes.HasFlag(.Info))
|
||||
ImGui.PushStyleColor(.Button, *col);
|
||||
else
|
||||
ImGui.PushStyleColor(.Button, .(0, 0, 0, 0));
|
||||
|
||||
if (ImGui.ImageButtonEx(2, s_InfoIcon, buttonSize, .Zero, .Ones))
|
||||
_visibleMessageTypes ^= .Info;
|
||||
|
||||
ImGui.PopStyleColor();
|
||||
|
||||
if (_visibleMessageTypes.HasFlag(.Warning))
|
||||
ImGui.PushStyleColor(.Button, *col);
|
||||
else
|
||||
ImGui.PushStyleColor(.Button, .(0, 0, 0, 0));
|
||||
|
||||
if (ImGui.ImageButtonEx(3, s_WarningIcon, buttonSize, .Zero, .Ones))
|
||||
_visibleMessageTypes ^= .Warning;
|
||||
|
||||
ImGui.PopStyleColor();
|
||||
|
||||
if (_visibleMessageTypes.HasFlag(.Error))
|
||||
ImGui.PushStyleColor(.Button, *col);
|
||||
else
|
||||
ImGui.PushStyleColor(.Button, .(0, 0, 0, 0));
|
||||
|
||||
|
||||
if (ImGui.ImageButtonEx(4, s_ErrorIcon, buttonSize, .Zero, .Ones))
|
||||
_visibleMessageTypes ^= .Error;
|
||||
|
||||
ImGui.PopStyleColor();
|
||||
|
||||
ImGui.PopStyleVar();
|
||||
|
||||
ImGui.EndMenuBar();
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowMessages()
|
||||
{
|
||||
if (ImGui.BeginTable("Messages", 3, .BordersInnerH | .SizingFixedFit))
|
||||
{
|
||||
ImGui.TableSetupColumn("", .WidthFixed);
|
||||
ImGui.TableSetupColumn("", .WidthStretch);
|
||||
ImGui.TableSetupColumn("", .WidthFixed);
|
||||
|
||||
//LogMessage lastMessage = null;
|
||||
int count = 1;
|
||||
|
||||
// Message ID for ImGui
|
||||
int imGuiMessageId = 0;
|
||||
|
||||
for (let message in _messages)
|
||||
{
|
||||
if (!_visibleMessageTypes.HasFlag(message.MessageType))
|
||||
continue;
|
||||
|
||||
if ((message.Source.IsEngineMessage && !_showEngineMessages) || (!message.Source.IsEngineMessage && !_showGameMessages))
|
||||
continue;
|
||||
|
||||
/*defer
|
||||
{
|
||||
lastMessage = message;
|
||||
}*/
|
||||
|
||||
do
|
||||
{
|
||||
LogMessage lastMessage = (message != _messages.Back) ? _messages[@message.Index + 1] : null;
|
||||
|
||||
if (_collapseMessages && lastMessage != null)
|
||||
{
|
||||
if (message.MessageType != lastMessage.MessageType)
|
||||
break;
|
||||
|
||||
if (message.Message != lastMessage.Message)
|
||||
break;
|
||||
|
||||
if (message.Source.Entity != lastMessage.Source.Entity)
|
||||
break;
|
||||
|
||||
// For exceptions the stack trace is basically the only relevant thing
|
||||
if (message.Source.Exception?.StackTrace != lastMessage.Source.Exception?.StackTrace)
|
||||
break;
|
||||
|
||||
// We collapse this message with the previous one:
|
||||
// Increment counter and go to next message.
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Push current index as ID
|
||||
ImGui.PushID((void*)++imGuiMessageId);
|
||||
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
|
||||
switch (message.MessageType)
|
||||
{
|
||||
case .Error:
|
||||
ImGui.Image(s_ErrorIcon, ImGui.Vec2(32, 32));
|
||||
ImGui.AttachTooltip("Error");
|
||||
case .Warning:
|
||||
ImGui.Image(s_WarningIcon, ImGui.Vec2(32, 32));
|
||||
ImGui.AttachTooltip("Warning");
|
||||
case .Info:
|
||||
ImGui.Image(s_InfoIcon, ImGui.Vec2(32, 32));
|
||||
ImGui.AttachTooltip("Info");
|
||||
case .Trace:
|
||||
ImGui.Image(s_TraceIcon, ImGui.Vec2(32, 32));
|
||||
ImGui.AttachTooltip("Trace");
|
||||
default:
|
||||
ImGui.TextUnformatted("Unknown");
|
||||
}
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
|
||||
// Timestamp
|
||||
ImGui.TextWrapped($"[{message.Timestamp:HH:mm:ss.fff}]");
|
||||
|
||||
if (message.Source.IsEngineMessage)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGui.TextUnformatted("Engine");
|
||||
}
|
||||
|
||||
// Show entity
|
||||
if (message.Source?.Entity != null)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
|
||||
Result<Entity> entity = Editor.Instance.CurrentScene.GetEntityByID(message.Source.Entity.Value);
|
||||
|
||||
if (entity case .Ok(let e))
|
||||
{
|
||||
ImGui.Text($"Entity: \"{e.Name}\" (ID: {message.Source.Entity})");
|
||||
|
||||
if (ImGui.IsItemClicked())
|
||||
Editor.Instance.EntityHierarchyWindow.HighlightEntity(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.Text($"Entity: (ID: {message.Source.Entity})");
|
||||
}
|
||||
}
|
||||
|
||||
if (message.Source.Exception != null)
|
||||
{
|
||||
if (ImGui.CollapsingHeader(message.Message.Ptr))
|
||||
{
|
||||
// Show the native to managed entry point only if we show engine messages
|
||||
|
||||
if (_showEngineMessages)
|
||||
ImGui.TextUnformatted(message.Source.Exception.StackTrace);
|
||||
else
|
||||
ImGui.TextUnformatted(message.Source.Exception.CleanStackTrace);
|
||||
|
||||
ImGui.NewLine();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.TextUnformatted(message.Message);
|
||||
}
|
||||
|
||||
// Dont show the counter if we only have one message.
|
||||
if (count > 1)
|
||||
{
|
||||
// the message is not collapsible with the previous one.
|
||||
// Print message count for last message and reset counter.
|
||||
// This message will be printed normally.
|
||||
|
||||
ImGui.TableNextColumn();
|
||||
ImGui.Text($"{count}");
|
||||
}
|
||||
|
||||
count = 1;
|
||||
|
||||
ImGui.PopID();
|
||||
}
|
||||
|
||||
if (_autoScroll)
|
||||
{
|
||||
if (ImGui.GetIO().MouseWheel > 0)
|
||||
{
|
||||
_autoScroll = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.SetScrollY(ImGui.GetScrollMaxY());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ImGui.GetScrollMaxY() == ImGui.GetScrollY())
|
||||
{
|
||||
_autoScroll = true;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearLog()
|
||||
{
|
||||
ClearAndDeleteItems!(_messages);
|
||||
}
|
||||
|
||||
public void Log(DateTime timestamp, LogLevel severity, StringView message, MessageSource source)
|
||||
{
|
||||
LogMessage logMessage = new LogMessage(timestamp, message, MessageType(severity), source);
|
||||
_messages.Add(logMessage);
|
||||
}
|
||||
|
||||
public void LogException(DateTime timestamp, MonoExceptionHelper exception)
|
||||
{
|
||||
StringView firstLine = exception.StackTrace;
|
||||
|
||||
int firstInIndex = exception.StackTrace.IndexOf("\n");
|
||||
|
||||
if (firstInIndex != -1)
|
||||
firstLine = firstLine.Substring(0, firstInIndex);
|
||||
|
||||
String message = scope .(128);
|
||||
message.AppendF($"Exception: \"{exception.FullName}\" | Message: \"{exception.Message}\" {firstLine}\0");
|
||||
|
||||
// TODO: are mono exceptions never engine only?
|
||||
LogMessage logMessage = new LogMessage(timestamp, message, .Error, new MessageSource(){Entity = exception.Instance, Exception = exception..AddRef(), IsEngineMessage = false});
|
||||
_messages.Add(logMessage);
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ namespace GlitchyEditor
|
||||
private ContentBrowserWindow _contentBrowserWindow ~ delete _;
|
||||
private PropertiesWindow _propertiesWindow ~ delete _;
|
||||
private AssetViewer _assetViewer ~ delete _;
|
||||
private LogWindow _logWindow ~ delete _;
|
||||
|
||||
public Scene CurrentScene
|
||||
{
|
||||
@@ -45,6 +46,7 @@ namespace GlitchyEditor
|
||||
public ContentBrowserWindow ContentBrowserWindow => _contentBrowserWindow;
|
||||
public PropertiesWindow PropertiesWindow => _propertiesWindow;
|
||||
public AssetViewer AssetViewer => _assetViewer;
|
||||
public LogWindow LogWindow => _logWindow;
|
||||
|
||||
public EditorCamera* CurrentCamera { get; set; }
|
||||
|
||||
@@ -53,15 +55,27 @@ namespace GlitchyEditor
|
||||
public SceneRenderer GameSceneRenderer {get; set;}
|
||||
public SceneRenderer EditorSceneRenderer {get; set;}
|
||||
|
||||
private static Editor s_Instance;
|
||||
|
||||
public static Editor Instance => s_Instance;
|
||||
|
||||
/// Creates a new editor for the given world
|
||||
public this(Scene scene, EditorContentManager contentManager)
|
||||
{
|
||||
Log.EngineLogger.AssertDebug(s_Instance == null, "Cannot create a second instance of a singleton.");
|
||||
s_Instance = this;
|
||||
|
||||
_scene = scene;
|
||||
_contentManager = contentManager;
|
||||
|
||||
InitWindows();
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
s_Instance = null;
|
||||
}
|
||||
|
||||
private void InitWindows()
|
||||
{
|
||||
_sceneViewportWindow = new EditorViewportWindow(this);
|
||||
@@ -71,6 +85,7 @@ namespace GlitchyEditor
|
||||
_contentBrowserWindow = new ContentBrowserWindow((.)Application.Get().ContentManager);
|
||||
_propertiesWindow = new PropertiesWindow(this);
|
||||
_assetViewer = new AssetViewer((.)Application.Get().ContentManager);
|
||||
_logWindow = new LogWindow();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
@@ -82,6 +97,7 @@ namespace GlitchyEditor
|
||||
_contentBrowserWindow.Show();
|
||||
_propertiesWindow.Show();
|
||||
_assetViewer.Show();
|
||||
_logWindow.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,9 @@ namespace GlitchyEditor
|
||||
public this(String[] args)
|
||||
{
|
||||
PushLayer(new EditorLayer(args, _contentManager));
|
||||
|
||||
Log.ClientLogger = new EditorLogger();
|
||||
Log.EngineLogger = new EditorLogger() { IsEngineLogger = true };
|
||||
}
|
||||
|
||||
protected override IContentManager InitContentManager()
|
||||
|
||||
@@ -19,6 +19,10 @@ namespace GlitchyEditor
|
||||
public SubTexture2D Simulate ~ _.ReleaseRef();
|
||||
public SubTexture2D Pause ~ _.ReleaseRef();
|
||||
public SubTexture2D SingleStep ~ _.ReleaseRef();
|
||||
public SubTexture2D Error ~ _.ReleaseRef();
|
||||
public SubTexture2D Warning ~ _.ReleaseRef();
|
||||
public SubTexture2D Info ~ _.ReleaseRef();
|
||||
public SubTexture2D Trace ~ _.ReleaseRef();
|
||||
|
||||
public SamplerState SamplerState
|
||||
{
|
||||
@@ -41,6 +45,10 @@ namespace GlitchyEditor
|
||||
Simulate = GetNextGridTexture(ref pen, iconSize);
|
||||
Pause = GetNextGridTexture(ref pen, iconSize);
|
||||
SingleStep = GetNextGridTexture(ref pen, iconSize);
|
||||
Error = GetNextGridTexture(ref pen, iconSize);
|
||||
Warning = GetNextGridTexture(ref pen, iconSize);
|
||||
Info = GetNextGridTexture(ref pen, iconSize);
|
||||
Trace = GetNextGridTexture(ref pen, iconSize);
|
||||
}
|
||||
|
||||
private SubTexture2D GetNextGridTexture(ref float2 pen, float2 iconSize)
|
||||
|
||||
@@ -171,6 +171,11 @@ namespace GlitchyEditor
|
||||
|
||||
ContentBrowserWindow.s_FolderTexture = _editorIcons.Folder;
|
||||
ContentBrowserWindow.s_FileTexture = _editorIcons.File;
|
||||
|
||||
LogWindow.s_ErrorIcon = _editorIcons.Error;
|
||||
LogWindow.s_WarningIcon = _editorIcons.Warning;
|
||||
LogWindow.s_InfoIcon = _editorIcons.Info;
|
||||
LogWindow.s_TraceIcon = _editorIcons.Trace;
|
||||
}
|
||||
|
||||
private void InitEditor()
|
||||
@@ -365,17 +370,8 @@ namespace GlitchyEditor
|
||||
dispatcher.Dispatch<MouseScrolledEvent>(scope (e) => OnMouseScrolled(e));
|
||||
}
|
||||
|
||||
ImGui.ID _mainDockspaceId;
|
||||
|
||||
TextureViewer viewer = new TextureViewer() ~ delete _;
|
||||
|
||||
private bool OnImGuiRender(ImGuiRenderEvent event)
|
||||
{
|
||||
// TODO: make window
|
||||
//Input.ImGuiDebugDraw();
|
||||
|
||||
//viewer.ViewTexture(Renderer.[Friend]_gBuffer.Target);
|
||||
|
||||
ImGui.Viewport* viewport = ImGui.GetMainViewport();
|
||||
ImGui.DockSpaceOverViewport(viewport);
|
||||
|
||||
@@ -427,9 +423,13 @@ namespace GlitchyEditor
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.SetCursorPosX(centerX - totalWidth / 2);
|
||||
|
||||
ImGui.PushID(0);
|
||||
|
||||
if (ImGui.ImageButton(_editorIcons.Play, .(size, size), .Zero, .Ones, 0))
|
||||
if (ImGui.ImageButton("", _editorIcons.Play, .(size, size), .Zero, .Ones))
|
||||
OnScenePlay();
|
||||
|
||||
ImGui.PopID();
|
||||
|
||||
ImGui.AttachTooltip("Play the game.");
|
||||
|
||||
@@ -437,7 +437,7 @@ namespace GlitchyEditor
|
||||
|
||||
ImGui.PushID(1);
|
||||
|
||||
if (ImGui.ImageButton(_editorIcons.Simulate, .(size, size), .Zero, .Ones, 0))
|
||||
if (ImGui.ImageButton("", _editorIcons.Simulate, .(size, size), .Zero, .Ones))
|
||||
OnSceneSimulate();
|
||||
|
||||
ImGui.PopID();
|
||||
@@ -456,7 +456,7 @@ namespace GlitchyEditor
|
||||
//ImGui.SameLine(penX += size + 2 * padding);
|
||||
ImGui.SameLine();
|
||||
|
||||
if (ImGui.ImageButton(_editorIcons.Pause, .(size, size), .Zero, .Ones, 0))
|
||||
if (ImGui.ImageButton("", _editorIcons.Pause, .(size, size), .Zero, .Ones))
|
||||
_isPaused = !_isPaused;
|
||||
|
||||
ImGui.PopID();
|
||||
@@ -480,7 +480,7 @@ namespace GlitchyEditor
|
||||
|
||||
SubTexture2D pauseButtonIcon = _isPaused ? _editorIcons.Play : _editorIcons.Pause;
|
||||
|
||||
if (ImGui.ImageButton(pauseButtonIcon, .(size, size), .Zero, .Ones, 0))
|
||||
if (ImGui.ImageButton("PlayPause", pauseButtonIcon, .(size, size), .Zero, .Ones))
|
||||
{
|
||||
if (_isPaused)
|
||||
OnSceneResume();
|
||||
@@ -498,7 +498,7 @@ namespace GlitchyEditor
|
||||
|
||||
SubTexture2D singleStepButtonIcon = _editorIcons.SingleStep;
|
||||
|
||||
if (ImGui.ImageButton(singleStepButtonIcon, .(size, size), .Zero, .Ones, 0))
|
||||
if (ImGui.ImageButton("Step", singleStepButtonIcon, .(size, size), .Zero, .Ones))
|
||||
{
|
||||
DoSingleStep();
|
||||
}
|
||||
@@ -529,7 +529,7 @@ namespace GlitchyEditor
|
||||
ImGui.SameLine();
|
||||
ImGui.PushID(1);
|
||||
|
||||
if (ImGui.ImageButton(_editorIcons.Stop, .(size, size), .Zero, .Ones, 0))
|
||||
if (ImGui.ImageButton("Stop", _editorIcons.Stop, .(size, size), .Zero, .Ones))
|
||||
OnSceneStop();
|
||||
|
||||
ImGui.PopID();
|
||||
@@ -807,6 +807,9 @@ namespace GlitchyEditor
|
||||
|
||||
if(ImGui.MenuItem(AssetViewer.s_WindowTitle))
|
||||
_editor.AssetViewer.Open = true;
|
||||
|
||||
if(ImGui.MenuItem(LogWindow.s_WindowTitle))
|
||||
_editor.LogWindow.Open = true;
|
||||
|
||||
ImGui.EndMenu();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
using GlitchLog;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using GlitchyEngine.Scripting;
|
||||
|
||||
namespace GlitchyEditor;
|
||||
|
||||
public class EditorLogger : Logger
|
||||
{
|
||||
// {l} = log level (first parameter)
|
||||
// {t} = current date time (second parameter)
|
||||
// {n} = logger name (third parameter)
|
||||
// {m} = message
|
||||
|
||||
private String _name;
|
||||
|
||||
public override String Name
|
||||
{
|
||||
get => _name;
|
||||
set => _name = value;
|
||||
}
|
||||
|
||||
public bool IsEngineLogger {get; set;}
|
||||
|
||||
public this()
|
||||
{
|
||||
//Debug.Assert(Debug.IsDebuggerPresent, "The DebugLogger requires a debugger to be present.");
|
||||
}
|
||||
|
||||
#if GL_NOLOG || GL_LOG_NOTRACE
|
||||
[SkipCall]
|
||||
#endif
|
||||
[Inline]
|
||||
public override void Trace(StringView format, params Object[] args)
|
||||
{
|
||||
InternalLog(.Trace, format, params args);
|
||||
}
|
||||
|
||||
#if GL_NOLOG || GL_LOG_NOINFO
|
||||
[SkipCall]
|
||||
#endif
|
||||
[Inline]
|
||||
public override void Info(StringView format, params Object[] args)
|
||||
{
|
||||
InternalLog(.Info, format, params args);
|
||||
}
|
||||
|
||||
#if GL_NOLOG || GL_LOG_NOWARNING
|
||||
[SkipCall]
|
||||
#endif
|
||||
[Inline]
|
||||
public override void Warning(StringView format, params Object[] args)
|
||||
{
|
||||
InternalLog(.Warning, format, params args);
|
||||
}
|
||||
|
||||
#if GL_NOLOG || GL_LOG_NOERROR
|
||||
[SkipCall]
|
||||
#endif
|
||||
[Inline]
|
||||
public override void Error(StringView format, params Object[] args)
|
||||
{
|
||||
InternalLog(.Error, format, params args);
|
||||
}
|
||||
|
||||
#if GL_NOLOG || GL_LOG_NOCRITICAL
|
||||
[SkipCall]
|
||||
#endif
|
||||
[Inline]
|
||||
public override void Critical(StringView format, params Object[] args)
|
||||
{
|
||||
InternalLog(.Critical, format, params args);
|
||||
}
|
||||
|
||||
#if GL_NOLOG
|
||||
[SkipCall]
|
||||
#endif
|
||||
[Inline]
|
||||
public override void Log(LogLevel level, StringView format, params Object[] args)
|
||||
{
|
||||
InternalLog(level, format, params args);
|
||||
}
|
||||
|
||||
public override void Assert(bool condition, String error = Compiler.CallerExpression[0], String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum)
|
||||
{
|
||||
if (!condition)
|
||||
{
|
||||
String failStr = scope .()..AppendF("Assert failed: {} at line {} in {}", error, line, filePath);
|
||||
InternalLog(.Critical, failStr);
|
||||
Internal.FatalError(failStr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public override void AssertDebug(bool condition, String error = Compiler.CallerExpression[0], String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum)
|
||||
{
|
||||
if (!condition)
|
||||
{
|
||||
String failStr = scope .()..AppendF("Assert failed: {} at line {} in {}", error, line, filePath);
|
||||
InternalLog(.Critical, failStr);
|
||||
Internal.FatalError(failStr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void InternalLog(LogLevel level, StringView format, params Object[] args)
|
||||
{
|
||||
if(_logLevel > level)
|
||||
return;
|
||||
|
||||
DateTime timestamp = DateTime.Now;
|
||||
|
||||
String message = scope String(4096);
|
||||
message.AppendF(format, params args);
|
||||
|
||||
Debug.Write($"[{timestamp:HH:mm:ss.fff}] ({_name})|{level.UpperString}: {message}");
|
||||
|
||||
if (Editor.Instance == null)
|
||||
return;
|
||||
|
||||
if (args.Count > 0 && (var ex = args[^1] as MonoExceptionHelper))
|
||||
{
|
||||
Editor.Instance.LogWindow.LogException(timestamp, ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Editor.Instance.LogWindow.Log(timestamp, level, message, new .() {IsEngineMessage = IsEngineLogger});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
|
||||
namespace ImGui;
|
||||
|
||||
enum DragDropPayloadType
|
||||
{
|
||||
case ContentBrowserItem;
|
||||
case Entity;
|
||||
|
||||
public String GetName()
|
||||
{
|
||||
switch (this)
|
||||
{
|
||||
case .ContentBrowserItem:
|
||||
return "CONTENT_BROWSER_ITEM";
|
||||
case .Entity:
|
||||
return "ENTITY";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ImGui
|
||||
{
|
||||
public static Payload* AcceptDragDropPayload(DragDropPayloadType type, DragDropFlags flags = .None)
|
||||
{
|
||||
return AcceptDragDropPayload(type.GetName(), flags);
|
||||
}
|
||||
|
||||
public static bool SetDragDropPayload(DragDropPayloadType type, void* data, size sz, Cond cond = .None)
|
||||
{
|
||||
return SetDragDropPayload(type.GetName(), data, sz, cond);
|
||||
}
|
||||
}
|
||||
@@ -1,247 +0,0 @@
|
||||
using GlitchyEngine.Renderer;
|
||||
using GlitchyEngine;
|
||||
using ImGui;
|
||||
using GlitchyEngine.Math;
|
||||
using System;
|
||||
|
||||
namespace GlitchyEditor
|
||||
{
|
||||
class TextureViewer
|
||||
{
|
||||
enum BackgroundMode : int32
|
||||
{
|
||||
White,
|
||||
Black,
|
||||
Checkerboard
|
||||
}
|
||||
|
||||
enum SampleMode : int32
|
||||
{
|
||||
Point,
|
||||
Linear
|
||||
}
|
||||
|
||||
GraphicsContext _context ~ _.ReleaseRef();
|
||||
|
||||
Effect _effect ~ _.ReleaseRef();
|
||||
|
||||
float _zoom = 1.0f;
|
||||
|
||||
BackgroundMode _backgroundMode = .Checkerboard;
|
||||
|
||||
SampleMode _sampleMode = .Linear;
|
||||
|
||||
RenderTarget2D _target ~ _?.ReleaseRef();
|
||||
// TODO: we don't need depth!
|
||||
DepthStencilTarget _depth ~ _?.ReleaseRef();
|
||||
|
||||
SamplerState _samplerPoint ~ _.ReleaseRef();
|
||||
SamplerState _samplerLinear ~ _.ReleaseRef();
|
||||
|
||||
public this()
|
||||
{
|
||||
_context = Application.Get().Window.Context..AddRef();
|
||||
|
||||
InitEffect();
|
||||
InitState();
|
||||
// TODO: rasterizerstate and depthstencilstate
|
||||
}
|
||||
|
||||
private void InitEffect()
|
||||
{
|
||||
_effect = new Effect("content\\Shaders\\textureViewerShader.hlsl");
|
||||
}
|
||||
|
||||
private void InitState()
|
||||
{
|
||||
SamplerStateDescription desc = .();
|
||||
desc.MagFilter = .Linear;
|
||||
desc.MinFilter = .Linear;
|
||||
_samplerLinear = SamplerStateManager.GetSampler(desc);
|
||||
|
||||
desc.MagFilter = .Point;
|
||||
desc.MinFilter = .Point;
|
||||
_samplerPoint = SamplerStateManager.GetSampler(desc);
|
||||
}
|
||||
|
||||
float2 _position;
|
||||
|
||||
bool _moving;
|
||||
|
||||
float _colorOffset = 0;
|
||||
float _colorScale = 1;
|
||||
float _alphaOffset = 0;
|
||||
float _alphaScale = 1;
|
||||
|
||||
public void ViewTexture(Texture viewedTexture)
|
||||
{
|
||||
ImGui.Begin("Texture Viewer");
|
||||
|
||||
ImGui.SliderFloat("Zoom", &_zoom, 0.01f, 100.0f);
|
||||
|
||||
char8*[] items = scope .("White", "Black", "Checkerboard");
|
||||
|
||||
ImGui.Combo("Background", (.)&_backgroundMode, items.Ptr, (.)items.Count);
|
||||
|
||||
items = scope .("Point", "Linear");
|
||||
|
||||
ImGui.Combo("Sampler", (.)&_sampleMode, items.Ptr, (.)items.Count);
|
||||
|
||||
ImGui.SliderFloat2("Color offset and scale", *(float[2]*)&_colorOffset, -1.0f, 1.0f);
|
||||
ImGui.SliderFloat2("Alpha offset and scale", *(float[2]*)&_alphaOffset, -1.0f, 1.0f);
|
||||
|
||||
ImGui.SliderFloat2("Position", *(float[2]*)&_position, 2 * -Math.Max(viewedTexture.Width, viewedTexture.Height) * _zoom, 2 * Math.Max(viewedTexture.Width, viewedTexture.Height) * _zoom);
|
||||
|
||||
ImGui.BeginChild("imageChild");
|
||||
|
||||
UpdateInput();
|
||||
|
||||
var viewportSize = ImGui.GetContentRegionAvail();
|
||||
|
||||
viewportSize.x = Math.Max(viewportSize.x, 1);
|
||||
viewportSize.y = Math.Max(viewportSize.y, 1);
|
||||
|
||||
if(_target == null || viewportSize.x != _target.Width || viewportSize.y != _target.Height)
|
||||
{
|
||||
_target?.ReleaseRef();
|
||||
_target = new RenderTarget2D(.(.R8G8B8A8_UNorm, (.)viewportSize.x, (.)viewportSize.y));
|
||||
_target.SamplerState = SamplerStateManager.PointClamp;
|
||||
_depth?.ReleaseRef();
|
||||
_depth = new DepthStencilTarget((.)viewportSize.x, (.)viewportSize.y, .D16_UNorm);
|
||||
}
|
||||
|
||||
RenderTexture(viewedTexture);
|
||||
|
||||
ImGui.Image(_target, viewportSize);
|
||||
|
||||
ImGui.EndChild();
|
||||
|
||||
ImGui.End();
|
||||
}
|
||||
|
||||
float lastWheel;
|
||||
|
||||
private void UpdateInput()
|
||||
{
|
||||
var windowPos = ImGui.GetWindowPos();
|
||||
var mousePos = ImGui.GetIO().MousePos;
|
||||
float2 mouseInWindow = .(mousePos.x - windowPos.x, mousePos.y - windowPos.y);
|
||||
|
||||
bool windowHovered = ImGui.IsWindowHovered();
|
||||
|
||||
if(windowHovered && Input.IsMouseButtonPressing(.MiddleButton))
|
||||
{
|
||||
_moving = true;
|
||||
}
|
||||
else if(Input.IsMouseButtonReleased(.MiddleButton))
|
||||
{
|
||||
_moving = false;
|
||||
}
|
||||
|
||||
if(windowHovered || _moving)
|
||||
{
|
||||
float mouseWheel = ImGui.GetIO().MouseWheel;
|
||||
|
||||
float delta = mouseWheel - lastWheel;
|
||||
|
||||
if(delta != 0)
|
||||
{
|
||||
_position -= mouseInWindow;
|
||||
_position /= _zoom;
|
||||
|
||||
_zoom *= Math.Pow(1.1f, delta);
|
||||
|
||||
_position *= _zoom;
|
||||
_position += mouseInWindow;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(_moving)
|
||||
{
|
||||
int2 movement = Input.GetMouseMovement();
|
||||
|
||||
_position.X += movement.X;
|
||||
_position.Y += movement.Y;
|
||||
}
|
||||
}
|
||||
|
||||
OrthographicCamera _camera = new OrthographicCamera() ~ delete _;
|
||||
|
||||
private void RenderTexture(Texture viewedTexture)
|
||||
{
|
||||
Viewport vp = .(0, 0, _target.Width, _target.Height);
|
||||
RenderCommand.SetViewport(vp);
|
||||
|
||||
// TODO: don't clear pink!
|
||||
RenderCommand.Clear(_target, .Pink);
|
||||
RenderCommand.Clear(_depth, .Depth, 1.0f, 0);
|
||||
|
||||
//_target.Bind();
|
||||
_context.SetRenderTarget(_target);
|
||||
_context.SetDepthStencilTarget(_depth);
|
||||
_context.BindRenderTargets();
|
||||
|
||||
float2 textureSize = float2(viewedTexture.Width, viewedTexture.Height);
|
||||
float2 zoomedTextureSize = textureSize * _zoom;
|
||||
|
||||
float2 targetSize = float2(_target.Width, _target.Height);
|
||||
|
||||
_effect.Variables["ColorOffset"].SetData(_colorOffset);
|
||||
_effect.Variables["ColorScale"].SetData(_colorScale);
|
||||
_effect.Variables["AlphaOffset"].SetData(_alphaOffset);
|
||||
_effect.Variables["AlphaScale"].SetData(_alphaScale);
|
||||
|
||||
_camera.Left = 0;
|
||||
_camera.Top = 0;
|
||||
_camera.Right = targetSize.X;
|
||||
_camera.Bottom = -targetSize.Y;
|
||||
_camera.NearPlane = -5;
|
||||
_camera.FarPlane = 5;
|
||||
_camera.Update();
|
||||
|
||||
Renderer2D.BeginScene(_camera);
|
||||
|
||||
switch(_backgroundMode)
|
||||
{
|
||||
case .Black:
|
||||
Renderer2D.DrawQuadPivotCorner(float3(0, 0, 1), targetSize, 0, .Black);
|
||||
case .White:
|
||||
Renderer2D.DrawQuadPivotCorner(float3(0, 0, 1), targetSize, 0, .White);
|
||||
case .Checkerboard:
|
||||
float quadSize = 50.0f;
|
||||
|
||||
float2 numQuads = (targetSize / 500f) * 10f;
|
||||
|
||||
for(float x = 0; x < numQuads.X; x++)
|
||||
{
|
||||
for(float y = 0; y < numQuads.Y; y++)
|
||||
{
|
||||
Renderer2D.DrawQuadPivotCorner(float3(x * quadSize, -y * quadSize, 1), quadSize.XX, 0, ((x + y) % 2 == 0) ? .White : .Gray);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Renderer2D.EndScene();
|
||||
|
||||
var sampler = viewedTexture.SamplerState;
|
||||
|
||||
switch(_sampleMode)
|
||||
{
|
||||
case .Point:
|
||||
viewedTexture.SamplerState = _samplerPoint;
|
||||
case .Linear:
|
||||
viewedTexture.SamplerState = _samplerLinear;
|
||||
}
|
||||
|
||||
Renderer2D.BeginScene(_camera, .SortByTexture, _effect);
|
||||
|
||||
Renderer2D.DrawQuad(float3(_position * .(1, -1), 0), zoomedTextureSize, 0, viewedTexture);
|
||||
|
||||
Renderer2D.EndScene();
|
||||
|
||||
viewedTexture.SamplerState = sampler;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,5 +70,25 @@ namespace GlitchyEngine
|
||||
delete dictionary;
|
||||
}
|
||||
}
|
||||
|
||||
public static mixin ClearDictionaryAndReleaseKeys(var dictionary)
|
||||
{
|
||||
if (dictionary != null)
|
||||
{
|
||||
for (var value in dictionary)
|
||||
value.key?.ReleaseRef();
|
||||
dictionary.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static mixin ClearDictionaryAndReleaseValues(var dictionary)
|
||||
{
|
||||
if (dictionary != null)
|
||||
{
|
||||
for (var value in dictionary)
|
||||
value.value?.ReleaseRef();
|
||||
dictionary.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,18 +87,30 @@ namespace ImGui
|
||||
|
||||
public static extern void Image(TextureViewBinding textureViewBinding, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 tint_col = Vec4.Ones, Vec4 border_col = Vec4.Zero);
|
||||
|
||||
public static bool ImageButton(SubTexture2D subTexture, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, int32 frame_padding = -1, Vec4 bg_col = Vec4.Zero, Vec4 tint_col = Vec4.Ones)
|
||||
public static bool ImageButton(char8* id, SubTexture2D subTexture, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 bg_col = Vec4.Zero, Vec4 tint_col = Vec4.Ones)
|
||||
{
|
||||
if (uv0 != .Zero || uv1 != .Ones)
|
||||
Runtime.NotImplemented();
|
||||
|
||||
float2 v = (.)subTexture.TexCoords.XY + subTexture.TexCoords.ZW;
|
||||
|
||||
return ImageButton(subTexture.Texture.GetViewBinding(), size, (.)subTexture.TexCoords.XY, (.)v, frame_padding, bg_col, tint_col);
|
||||
return ImageButton(id, subTexture.Texture.GetViewBinding(), size, (.)subTexture.TexCoords.XY, (.)v, bg_col, tint_col);
|
||||
}
|
||||
|
||||
public static extern bool ImageButton(TextureViewBinding textureViewBinding, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, int32 frame_padding = -1, Vec4 bg_col = Vec4.Zero, Vec4 tint_col = Vec4.Ones);
|
||||
|
||||
|
||||
public static extern bool ImageButton(char8* id, TextureViewBinding textureViewBinding, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 bg_col = Vec4.Zero, Vec4 tint_col = Vec4.Ones);
|
||||
|
||||
public static bool ImageButtonEx(uint32 id, SubTexture2D subTexture, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 bg_col = Vec4.Zero, Vec4 tint_col = Vec4.Ones)
|
||||
{
|
||||
if (uv0 != .Zero || uv1 != .Ones)
|
||||
Runtime.NotImplemented();
|
||||
|
||||
float2 v = (.)subTexture.TexCoords.XY + subTexture.TexCoords.ZW;
|
||||
|
||||
return ImageButtonEx(id, subTexture.Texture.GetViewBinding(), size, (.)subTexture.TexCoords.XY, (.)v, bg_col, tint_col);
|
||||
}
|
||||
|
||||
public static extern bool ImageButtonEx(uint32 id, TextureViewBinding textureViewBinding, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 bg_col = Vec4.Zero, Vec4 tint_col = Vec4.Ones);
|
||||
|
||||
public static void TextUnformatted(StringView text) => TextUnformattedImpl(text.Ptr, text.Ptr + text.Length);
|
||||
|
||||
public static void PushID(StringView id) => PushID(id.Ptr, id.Ptr + id.Length);
|
||||
|
||||
@@ -86,29 +86,42 @@ namespace GlitchyEngine.ImGui
|
||||
ImGuizmo.BeginFrame();
|
||||
}
|
||||
|
||||
private void LoadFont()
|
||||
{
|
||||
var settings = Application.Instance.Settings.ImGuiSettings;
|
||||
|
||||
ImGui.GetIO().Fonts.Clear();
|
||||
|
||||
Stream fontFile = Application.Instance.ContentManager.GetStream(settings.FontName);
|
||||
|
||||
if (fontFile != null)
|
||||
{
|
||||
// We need to use ImGuis memory allocator because ImGui takes ownership
|
||||
uint8* fontData = (uint8*)ImGui.MemAlloc((uint64)fontFile.Length);
|
||||
var result = fontFile.TryRead(Span<uint8>(fontData, fontFile.Length));
|
||||
|
||||
if (result case .Err)
|
||||
Log.EngineLogger.Error($"Failed to load font \"{settings.FontName}\" from stream.");
|
||||
|
||||
ImGui.GetIO().Fonts.AddFontFromMemoryTTF(fontData, (int32)fontFile.Length, settings.FontSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.GetIO().Fonts.AddFontDefault();
|
||||
}
|
||||
|
||||
ImGui.GetIO().Fonts.AddFontDefault();
|
||||
|
||||
delete fontFile;
|
||||
}
|
||||
|
||||
public void ImGuiRender()
|
||||
{
|
||||
Debug.Profiler.ProfileFunction!();
|
||||
|
||||
if (SettingsInvalid)
|
||||
{
|
||||
var settings = Application.Get().Settings.ImGuiSettings;
|
||||
|
||||
ImGui.GetIO().Fonts.Clear();
|
||||
|
||||
// TODO: Fix fonts
|
||||
//String fullpath = scope String();
|
||||
//Application.Get().ContentManager.GetFilePath(fullpath, settings.FontName);
|
||||
/*Application.Get().ContentManager.GetStream(settings.FontName);
|
||||
if (File.Exists(fullpath))
|
||||
{
|
||||
ImGui.GetIO().Fonts.AddFontFromMemoryTTF();
|
||||
ImGui.GetIO().Fonts.AddFontFromFileTTF(fullpath, settings.FontSize);
|
||||
}
|
||||
else
|
||||
{*/
|
||||
ImGui.GetIO().Fonts.AddFontDefault();
|
||||
//}
|
||||
LoadFont();
|
||||
|
||||
#if GE_GRAPHICS_DX11
|
||||
ImGuiImplDX11.CreateDeviceObjects();
|
||||
|
||||
@@ -8,10 +8,33 @@ namespace GlitchyEngine
|
||||
static Logger _engineLogger ~ delete _;
|
||||
static Logger _clientLogger ~ delete _;
|
||||
|
||||
[Inline]
|
||||
public static Logger EngineLogger => _engineLogger;
|
||||
[Inline]
|
||||
public static Logger ClientLogger => _clientLogger;
|
||||
public static Logger EngineLogger
|
||||
{
|
||||
[Inline]
|
||||
get => _engineLogger;
|
||||
set
|
||||
{
|
||||
if (_engineLogger == value)
|
||||
return;
|
||||
|
||||
delete _engineLogger;
|
||||
_engineLogger = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static Logger ClientLogger
|
||||
{
|
||||
[Inline]
|
||||
get => _clientLogger;
|
||||
set
|
||||
{
|
||||
if (_clientLogger == value)
|
||||
return;
|
||||
|
||||
delete _clientLogger;
|
||||
_clientLogger = value;
|
||||
}
|
||||
}
|
||||
|
||||
static this()
|
||||
{
|
||||
|
||||
+14
-2
@@ -22,12 +22,24 @@ namespace ImGui
|
||||
textureViewBinding.Release();
|
||||
}
|
||||
|
||||
public static override bool ImageButton(TextureViewBinding textureViewBinding, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, int32 frame_padding = -1, Vec4 bg_col = Vec4.Zero, Vec4 tint_col = Vec4.Ones)
|
||||
public static override bool ImageButton(char8* id, TextureViewBinding textureViewBinding, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 bg_col = Vec4.Zero, Vec4 tint_col = Vec4.Ones)
|
||||
{
|
||||
var view = textureViewBinding._nativeShaderResourceView..AddRef();
|
||||
_resourceViews.Add(view);
|
||||
|
||||
bool pressed = ImGui.ImageButton(view, size, uv0, uv1, frame_padding, bg_col, tint_col);
|
||||
bool pressed = ImGui.ImageButton(id, view, size, uv0, uv1, bg_col, tint_col);
|
||||
|
||||
textureViewBinding.Release();
|
||||
|
||||
return pressed;
|
||||
}
|
||||
|
||||
public static override bool ImageButtonEx(uint32 id, TextureViewBinding textureViewBinding, Vec2 size, Vec2 uv0 = Vec2.Zero, Vec2 uv1 = Vec2.Ones, Vec4 bg_col = Vec4.Zero, Vec4 tint_col = Vec4.Ones)
|
||||
{
|
||||
var view = textureViewBinding._nativeShaderResourceView..AddRef();
|
||||
_resourceViews.Add(view);
|
||||
|
||||
bool pressed = ImGui.ImageButtonEx(id, view, size, uv0, uv1, bg_col, tint_col);
|
||||
|
||||
textureViewBinding.Release();
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using GlitchyEngine.Core;
|
||||
using Mono;
|
||||
|
||||
namespace GlitchyEngine.Scripting;
|
||||
|
||||
|
||||
public class MonoExceptionHelper : RefCounter
|
||||
{
|
||||
private String _fullName ~ delete _;
|
||||
|
||||
private String _message ~ delete _;
|
||||
|
||||
private String _stackTrace ~ delete _;
|
||||
/// The clean stack trace only contains the Managed Stack (the full trace contains one line for the native-to-managed entry)
|
||||
private StringView _cleanStackTrace;
|
||||
|
||||
private MonoExceptionHelper _innerException ~ _?.ReleaseRef();
|
||||
|
||||
public StringView FullName => _fullName;
|
||||
public StringView Message => _message;
|
||||
|
||||
public StringView StackTrace => _stackTrace;
|
||||
public StringView CleanStackTrace => _cleanStackTrace;
|
||||
|
||||
public MonoExceptionHelper InnerException => _innerException;
|
||||
|
||||
public UUID Instance { get; set; }
|
||||
|
||||
public this(MonoException* exception)
|
||||
{
|
||||
MonoObject* exObject = (MonoObject*)exception;
|
||||
|
||||
MonoClass* monoClass = Mono.mono_object_get_class(exObject);
|
||||
|
||||
StringView classNamespace = .(Mono.mono_class_get_namespace(monoClass));
|
||||
StringView className = .(Mono.mono_class_get_name(monoClass));
|
||||
_fullName = new $"{classNamespace}.{className}";
|
||||
|
||||
GetMessage(exObject, monoClass);
|
||||
|
||||
GetStackTrace(exception);
|
||||
|
||||
GetInnerException(exObject, monoClass);
|
||||
}
|
||||
|
||||
private void GetMessage(MonoObject* exceptionObject, MonoClass* monoClass)
|
||||
{
|
||||
var messageProperty = Mono.mono_class_get_property_from_name(monoClass, "Message");
|
||||
|
||||
MonoObject* message = Mono.mono_property_get_value(messageProperty, exceptionObject, null, null);
|
||||
char8* exMessage = Mono.mono_string_to_utf8((.)message);
|
||||
|
||||
_message = new String(exMessage);
|
||||
|
||||
Mono.mono_free(exMessage);
|
||||
}
|
||||
|
||||
private void GetStackTrace(MonoException* exception)
|
||||
{
|
||||
char8* stacktracePtr = Mono.mono_exception_get_managed_backtrace(exception);
|
||||
_stackTrace = new String(stacktracePtr);
|
||||
|
||||
int entryIndex = _stackTrace.IndexOf("at (wrapper native-to-managed)");
|
||||
|
||||
if (entryIndex != -1)
|
||||
_cleanStackTrace = _stackTrace.Substring(0, entryIndex);
|
||||
else
|
||||
_cleanStackTrace = _stackTrace;
|
||||
}
|
||||
|
||||
private void GetInnerException(MonoObject* exceptionObject, MonoClass* monoClass)
|
||||
{
|
||||
MonoProperty* innerExceptionProperty = Mono.mono_class_get_property_from_name(monoClass, "InnerException");
|
||||
|
||||
MonoObject* innerException = Mono.mono_property_get_value(innerExceptionProperty, exceptionObject, null, null);
|
||||
|
||||
if (innerException != null)
|
||||
_innerException = new MonoExceptionHelper((MonoException*)innerException);
|
||||
}
|
||||
}
|
||||
@@ -13,13 +13,44 @@ public struct ScriptField
|
||||
internal MonoClassField* _monoField;
|
||||
public bool IsStatic;
|
||||
public ScriptFieldType FieldType;
|
||||
public SharpType SharpType;
|
||||
public int SizeInBytes;
|
||||
|
||||
internal this(StringView name, MonoClassField* monoField, bool isStatic, ScriptFieldType fieldType)
|
||||
internal this(StringView name, MonoClassField* monoField, bool isStatic, ScriptFieldType fieldType, int sizeInBytes, SharpType sharpType)
|
||||
{
|
||||
Name = name;
|
||||
_monoField = monoField;
|
||||
IsStatic = isStatic;
|
||||
FieldType = fieldType;
|
||||
SharpType = sharpType;
|
||||
SizeInBytes = sizeInBytes;
|
||||
}
|
||||
|
||||
public bool IsType(SharpClass otherClass, bool checkIfSubtype)
|
||||
{
|
||||
return IsType(otherClass.GetMonoType(), checkIfSubtype);
|
||||
}
|
||||
|
||||
public bool IsType(MonoType* otherType, bool checkIfSubtype)
|
||||
{
|
||||
MonoType* myType = GetMonoType();
|
||||
|
||||
if (checkIfSubtype)
|
||||
{
|
||||
MonoClass* myClass = Mono.mono_type_get_class(myType);
|
||||
MonoClass* otherClass = Mono.mono_type_get_class(otherType);
|
||||
|
||||
return Mono.mono_class_is_subclass_of(myClass, otherClass, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
return myType == otherType;
|
||||
}
|
||||
}
|
||||
|
||||
public MonoType* GetMonoType()
|
||||
{
|
||||
return Mono.mono_field_get_type(_monoField);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,9 +121,19 @@ class SharpClass : SharpType
|
||||
ExtractFields();
|
||||
}
|
||||
|
||||
internal MonoType* GetMonoType()
|
||||
{
|
||||
return Mono.mono_class_get_type(_monoClass);
|
||||
}
|
||||
|
||||
internal bool IsType(MonoType* type)
|
||||
{
|
||||
return Mono.mono_class_get_type(_monoClass) == type;
|
||||
return GetMonoType() == type;
|
||||
}
|
||||
|
||||
internal bool IsSubclass(MonoClass* @class)
|
||||
{
|
||||
return Mono.mono_class_is_subclass_of(_monoClass, @class, false);
|
||||
}
|
||||
|
||||
private void ExtractFields()
|
||||
@@ -110,10 +151,12 @@ class SharpClass : SharpType
|
||||
|
||||
ScriptFieldType fieldType = ScriptEngineHelper.GetScriptFieldType(type);
|
||||
|
||||
SharpType sharpType = null;
|
||||
|
||||
// If field type is none the field might be a struct, class or enum
|
||||
if (fieldType == .None)
|
||||
{
|
||||
SharpType sharpType = ScriptEngine.GetSharpType(type);
|
||||
sharpType = ScriptEngine.GetSharpType(type);
|
||||
fieldType = sharpType?.ScriptType ?? .None;
|
||||
|
||||
if (sharpType == null)
|
||||
@@ -132,7 +175,79 @@ class SharpClass : SharpType
|
||||
(attributes != null &&
|
||||
Mono.mono_custom_attrs_has_attr(attributes, ScriptEngine.Attributes.s_ShowInEditorAttribute)))
|
||||
{
|
||||
_monoFields[name] = .(name, currentField, flags.HasFlag(.Static), fieldType);
|
||||
MonoClass* fieldClass = Mono.mono_type_get_class(type);
|
||||
|
||||
int sizeInBytes = 8;
|
||||
|
||||
if (fieldClass != null)
|
||||
{
|
||||
sizeInBytes = Mono.mono_class_instance_size(fieldClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
_monoFields[name] = .(name, currentField, flags.HasFlag(.Static), fieldType, sizeInBytes, sharpType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct EnumValue
|
||||
{
|
||||
public StringView Name;
|
||||
|
||||
public uint64 Value;
|
||||
|
||||
public this(StringView name, uint64 value)
|
||||
{
|
||||
Name = name;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
class SharpEnum : SharpClass
|
||||
{
|
||||
private append Dictionary<uint64, EnumValue> _values = .();
|
||||
|
||||
public Dictionary<uint64, EnumValue> Values => _values;
|
||||
|
||||
private int _underlyingSize = 0;
|
||||
|
||||
public this(StringView classNamespace, StringView className, MonoImage* image)
|
||||
: base(classNamespace, className, image, .Enum)
|
||||
{
|
||||
ExtractEnumValues();
|
||||
}
|
||||
|
||||
private void ExtractEnumValues()
|
||||
{
|
||||
_underlyingSize = Mono.mono_class_instance_size(_monoClass);
|
||||
Log.EngineLogger.Assert(_underlyingSize != 0);
|
||||
|
||||
var vtable = Mono.mono_class_vtable(ScriptEngine.[Friend]s_AppDomain, _monoClass);
|
||||
|
||||
void* iterator = null;
|
||||
MonoClassField* currentField = null;
|
||||
while ((currentField = Mono.mono_class_get_fields(_monoClass, &iterator)) != null)
|
||||
{
|
||||
MonoType* fieldType = Mono.mono_field_get_type(currentField);
|
||||
MonoClass* fieldClass = Mono.mono_type_get_class(fieldType);
|
||||
|
||||
FieldAttribute fieldFlags = (.)Mono.mono_field_get_flags(currentField);
|
||||
|
||||
if (fieldFlags.HasFlag(.Public) && fieldFlags.HasFlag(.Static) &&
|
||||
fieldClass != null && Mono.mono_class_is_subclass_of(fieldClass, _monoClass, false))
|
||||
{
|
||||
StringView fieldName = StringView(Mono.mono_field_get_name(currentField));
|
||||
|
||||
uint64 value = 0;
|
||||
Mono.mono_field_static_get_value(vtable, currentField, &value);
|
||||
|
||||
EnumValue enumValue = .(fieldName, value);
|
||||
|
||||
_values.Add(value, enumValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,8 +295,8 @@ class ScriptClass : SharpClass
|
||||
public Dictionary<StringView, ScriptField> Fields => _monoFields;*/
|
||||
|
||||
[AllowAppend]
|
||||
public this(StringView classNamespace, StringView className, MonoImage* image) :
|
||||
base(classNamespace, className, image)
|
||||
public this(StringView classNamespace, StringView className, MonoImage* image, ScriptFieldType scriptFieldType = .Class) :
|
||||
base(classNamespace, className, image, scriptFieldType)
|
||||
{
|
||||
//_constructor = (ConstructorMethod)GetMethodThunk(".ctor", 1); // GetMethod(".ctor", 1);//
|
||||
_constructor = GetMethod(".ctor", 1);
|
||||
@@ -190,59 +305,50 @@ class ScriptClass : SharpClass
|
||||
_onDestroy = (OnDestroyMethod)GetMethodThunk("OnDestroy");
|
||||
}
|
||||
|
||||
public void OnCreate(MonoObject* instance)
|
||||
public void OnCreate(MonoObject* instance, out MonoException* exception)
|
||||
{
|
||||
MonoException* exception = null;
|
||||
exception = null;
|
||||
|
||||
if (_onCreate != null)
|
||||
_onCreate(instance, &exception);
|
||||
}
|
||||
|
||||
public void OnUpdate(MonoObject* instance, float deltaTime)
|
||||
public void OnUpdate(MonoObject* instance, float deltaTime, out MonoException* exception)
|
||||
{
|
||||
MonoException* exception = null;
|
||||
exception = null;
|
||||
|
||||
if (_onUpdate != null)
|
||||
_onUpdate(instance, deltaTime, &exception);
|
||||
|
||||
if (exception != null)
|
||||
{
|
||||
char8* str = Mono.mono_string_to_utf8(exception.Message);
|
||||
|
||||
Log.EngineLogger.Error($"Exception in \"{_fullName}.OnUpdate\". Message:\"{StringView(str)}\"");
|
||||
|
||||
Mono.mono_free(str);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDestroy(MonoObject* instance)
|
||||
public void OnDestroy(MonoObject* instance, out MonoException* exception)
|
||||
{
|
||||
MonoException* exception;
|
||||
exception = null;
|
||||
|
||||
if (_onDestroy != null)
|
||||
_onDestroy(instance, &exception);
|
||||
}
|
||||
|
||||
public MonoObject* CreateInstance(UUID uuid)
|
||||
public MonoObject* CreateInstance(UUID uuid, out MonoException* exception)
|
||||
{
|
||||
MonoObject* instance = Mono.mono_object_new(ScriptEngine.[Friend]s_AppDomain, _monoClass);
|
||||
|
||||
// TODO: I think this is a bit dirty
|
||||
// Invoke empty constructor to fill fields
|
||||
Mono.mono_runtime_object_init(instance);
|
||||
|
||||
// Invoke constructor with UUID
|
||||
#unwarn
|
||||
ScriptEngine.[Friend]s_EngineObject.Invoke(ScriptEngine.[Friend]s_EngineObject._constructor, instance, &uuid);
|
||||
ScriptEngine.[Friend]s_EngineObject.Invoke(ScriptEngine.[Friend]s_EngineObject._constructor, instance, out exception, &uuid);
|
||||
|
||||
//MonoException* exception = null;
|
||||
//#unwarn
|
||||
//ScriptEngine.[Friend]s_EntityRoot._constructor(instance, uuid, &exception);
|
||||
//ScriptEngine.[Friend]s_EntityRoot.Invoke(_constructor, instance, &uuid);
|
||||
return instance;
|
||||
}
|
||||
|
||||
/*MonoObject* exception = null;
|
||||
#unwarn*/
|
||||
//Mono.mono_runtime_invoke(_constructor, instance, (.)&uuid, &exception);
|
||||
//Mono.mono_runtime_object_init(instance);
|
||||
//MonoException* exception;
|
||||
//_constructor(instance, uuid, &exception);
|
||||
public MonoObject* CreateInstance()
|
||||
{
|
||||
MonoObject* instance = Mono.mono_object_new(ScriptEngine.[Friend]s_AppDomain, _monoClass);
|
||||
|
||||
// Invoke empty constructor to fill fields
|
||||
Mono.mono_runtime_object_init(instance);
|
||||
|
||||
return instance;
|
||||
}
|
||||
@@ -265,12 +371,22 @@ class ScriptClass : SharpClass
|
||||
public MonoObject* Invoke(MonoMethod* method, MonoObject* instance, void** args = null)
|
||||
{
|
||||
MonoObject* exception = null;
|
||||
return Mono.mono_runtime_invoke(method, instance, args, &exception);
|
||||
|
||||
MonoObject* result = Mono.mono_runtime_invoke(method, instance, args, &exception);
|
||||
|
||||
if (exception != null)
|
||||
ScriptEngine.HandleMonoException((MonoException*)exception);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public MonoObject* Invoke(MonoMethod* method, MonoObject* instance, params void*[] args)
|
||||
public MonoObject* Invoke(MonoMethod* method, MonoObject* instance, out MonoException* exception, params void*[] args)
|
||||
{
|
||||
return Mono.mono_runtime_invoke(method, instance, args.Ptr, null);
|
||||
exception = null;
|
||||
|
||||
MonoObject* result = Mono.mono_runtime_invoke(method, instance, args.Ptr, (.)&exception);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public T Invoke<T>(MonoMethod* method, MonoObject* instance, params void*[] args)
|
||||
@@ -282,12 +398,17 @@ class ScriptClass : SharpClass
|
||||
public T GetFieldValue<T>(MonoObject* instance, MonoClassField* field)
|
||||
{
|
||||
T value = default;
|
||||
Mono.Mono.mono_field_get_value(instance, field, &value);
|
||||
Mono.mono_field_get_value(instance, field, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public void SetFieldValue<T>(MonoObject* instance, MonoClassField* field, in T value)
|
||||
{
|
||||
Mono.Mono.mono_field_set_value(instance, field, &value);
|
||||
Mono.mono_field_set_value(instance, field, &value);
|
||||
}
|
||||
|
||||
public void SetFieldValue<T>(MonoObject* instance, MonoClassField* field, in T value) where T : struct*
|
||||
{
|
||||
Mono.mono_field_set_value(instance, field, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,12 +58,14 @@ static class ScriptEngine
|
||||
|
||||
private static Scene s_Context ~ _?.ReleaseRef();
|
||||
|
||||
private static ScriptClass s_ComponentRoot ~ _?.ReleaseRef();
|
||||
private static ScriptClass s_EntityRoot ~ _?.ReleaseRef();
|
||||
private static ScriptClass s_EngineObject ~ _?.ReleaseRef();
|
||||
|
||||
private static Dictionary<StringView, SharpType> _sharpClasses = new .() ~ DeleteDictionaryAndReleaseValues!(_);
|
||||
|
||||
private static Dictionary<StringView, ScriptClass> _entityScripts = new .() ~ DeleteDictionaryAndReleaseValues!(_);
|
||||
private static Dictionary<StringView, ScriptClass> _componentClasses = new .() ~ DeleteDictionaryAndReleaseValues!(_);
|
||||
|
||||
private static Dictionary<UUID, ScriptInstance> _entityScriptInstances = new .() ~ {
|
||||
for (var entry in _)
|
||||
@@ -74,6 +76,7 @@ static class ScriptEngine
|
||||
}
|
||||
|
||||
public static Dictionary<StringView, ScriptClass> EntityClasses => _entityScripts;
|
||||
public static Dictionary<StringView, ScriptClass> ComponentClasses => _componentClasses;
|
||||
|
||||
public static Scene Context => s_Context;
|
||||
|
||||
@@ -170,6 +173,13 @@ static class ScriptEngine
|
||||
CreateAppDomain("GlitchyEngineScriptRuntime");
|
||||
(s_CoreAssembly, s_CoreAssemblyImage) = LoadAssembly("resources/scripts/ScriptCore.dll", _debuggingEnabled);
|
||||
(s_AppAssembly, s_AppAssemblyImage) = LoadAssembly("SandboxProject/Assets/Scripts/bin/Sandbox.dll", _debuggingEnabled);
|
||||
|
||||
ClearDictionaryAndReleaseValues!(_sharpClasses);
|
||||
|
||||
GetCoreAttributes();
|
||||
GetCoreClasses();
|
||||
|
||||
GetComponentsFromAssemblies();
|
||||
|
||||
GetEntitiesFromAssemblies();
|
||||
|
||||
@@ -199,20 +209,22 @@ static class ScriptEngine
|
||||
if (scriptClass == null)
|
||||
return false;
|
||||
|
||||
script.Instance = new ScriptInstance(scriptClass);
|
||||
UUID entityId = entity.UUID;
|
||||
|
||||
script.Instance = new ScriptInstance(entityId, scriptClass);
|
||||
script.Instance..ReleaseRef();
|
||||
|
||||
_entityScriptInstances[entity.UUID] = script.Instance..AddRef();
|
||||
_entityScriptInstances[entityId] = script.Instance..AddRef();
|
||||
|
||||
script.Instance.Instantiate(entity.UUID);
|
||||
|
||||
CopyEditorFieldsToInstance(entity, script);
|
||||
script.Instance.Instantiate(entityId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void CopyEditorFieldsToInstance(Entity entity, ScriptComponent* script)
|
||||
public static void CopyEditorFieldsToInstance(Entity entity, ScriptComponent* script)
|
||||
{
|
||||
Log.EngineLogger.AssertDebug(script.Instance != null);
|
||||
|
||||
// Technically the map is for a different entity (namely the editor-entity),
|
||||
// however the UUID is the same, so we get the correct field map
|
||||
let fields = GetScriptFieldMap(entity);
|
||||
@@ -220,10 +232,34 @@ static class ScriptEngine
|
||||
for (var (fieldName, field) in fields)
|
||||
{
|
||||
// TODO: a litte assertion maybe?
|
||||
|
||||
|
||||
ScriptField scriptField = script.Instance.ScriptClass.Fields[fieldName];
|
||||
|
||||
script.Instance.SetFieldValue(scriptField, field._data);
|
||||
switch (scriptField.FieldType)
|
||||
{
|
||||
case .Entity:
|
||||
// On the C# side we actually differentiate between an Entity and the Script
|
||||
// in the sense that getting an entity and a script yields two different results (one creates a new Entity-Class instance, the other returns the actual instance).
|
||||
// But here its just easier to always use the script instance.
|
||||
// Obviously breaks once we support multiple scripts per entity.
|
||||
UUID referencedId = field.GetData<UUID>();
|
||||
MonoObject* referencedEntity = GetManagedInstance(referencedId);
|
||||
script.Instance.SetFieldValue(scriptField, referencedEntity);
|
||||
case .Component:
|
||||
// We create a new instance of a component class
|
||||
MonoType* type = scriptField.GetMonoType();
|
||||
|
||||
SharpType sharpType = ScriptEngine.GetSharpType(type);
|
||||
|
||||
var componentClass = ComponentClasses[sharpType.FullName];
|
||||
|
||||
MonoObject* componentInstance = script.Instance.CreateComponentInstance(componentClass);
|
||||
script.Instance.SetFieldValue(scriptField, componentInstance);
|
||||
|
||||
sharpType.ReleaseRef();
|
||||
default:
|
||||
script.Instance.SetFieldValue(scriptField, field._data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,32 +333,27 @@ static class ScriptEngine
|
||||
return (assembly, image);
|
||||
}
|
||||
|
||||
/// Retrieves the base classes from which every Component or Entity inherits
|
||||
static void GetCoreClasses()
|
||||
{
|
||||
s_EngineObject?.ReleaseRef();
|
||||
s_EntityRoot?.ReleaseRef();
|
||||
s_ComponentRoot?.ReleaseRef();
|
||||
|
||||
s_EngineObject = new ScriptClass("GlitchyEngine.Core", "EngineObject", s_CoreAssemblyImage, .Class);
|
||||
s_EntityRoot = new ScriptClass("GlitchyEngine", "Entity", s_CoreAssemblyImage, .Entity);
|
||||
s_ComponentRoot = new ScriptClass("GlitchyEngine", "Component", s_CoreAssemblyImage, .Component);
|
||||
}
|
||||
|
||||
/// Retrieves the classes for Attributes that are defined in the Core library
|
||||
static void GetCoreAttributes()
|
||||
{
|
||||
Attributes.s_ShowInEditorAttribute = Mono.mono_class_from_name(s_CoreAssemblyImage, "GlitchyEngine.Editor", "ShowInEditorAttribute");
|
||||
}
|
||||
|
||||
private static void GetEntitiesFromAssemblies()
|
||||
{
|
||||
for (var entry in _entityScripts)
|
||||
{
|
||||
entry.value.ReleaseRef();
|
||||
}
|
||||
_entityScripts.Clear();
|
||||
|
||||
for (var sharpClass in _sharpClasses)
|
||||
{
|
||||
sharpClass.value.ReleaseRef();
|
||||
}
|
||||
_sharpClasses.Clear();
|
||||
|
||||
if (s_EngineObject != null)
|
||||
{
|
||||
s_EngineObject.ReleaseRef();
|
||||
s_EntityRoot.ReleaseRef();
|
||||
}
|
||||
|
||||
s_EngineObject = new ScriptClass("GlitchyEngine.Core", "EngineObject", s_CoreAssemblyImage);
|
||||
s_EntityRoot = new ScriptClass("GlitchyEngine", "Entity", s_CoreAssemblyImage);
|
||||
|
||||
Log.EngineLogger.Assert(s_EntityRoot != null);
|
||||
|
||||
Attributes.s_ShowInEditorAttribute = Mono.mono_class_from_name(s_CoreAssemblyImage, "GlitchyEngine.Editor", "ShowInEditorAttribute");
|
||||
ClearDictionaryAndReleaseValues!(_entityScripts);
|
||||
|
||||
MonoTableInfo* typeDefinitionsTable = Mono.mono_image_get_table_info(s_AppAssemblyImage, .MONO_TABLE_TYPEDEF);
|
||||
int32 numTypes = Mono.mono_table_info_get_rows(typeDefinitionsTable);
|
||||
@@ -336,16 +367,44 @@ static class ScriptEngine
|
||||
char8* name = Mono.mono_metadata_string_heap(s_AppAssemblyImage, (.)cols[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_NAME]);
|
||||
|
||||
MonoClass* monoClass = Mono.mono_class_from_name(s_AppAssemblyImage, nameSpace, name);
|
||||
|
||||
|
||||
// Check if it is an entity
|
||||
if (monoClass != null && Mono.mono_class_is_subclass_of(monoClass, s_EntityRoot.[Friend]_monoClass, false))
|
||||
{
|
||||
ScriptClass entityScript = new ScriptClass(StringView(nameSpace), StringView(name), s_AppAssemblyImage);
|
||||
ScriptClass entityScript = new ScriptClass(StringView(nameSpace), StringView(name), s_AppAssemblyImage, .Entity);
|
||||
_entityScripts.Add(entityScript.FullName, entityScript);
|
||||
|
||||
Log.EngineLogger.Info($"Added entity \"{entityScript.FullName}\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
private static void GetComponentsFromAssemblies()
|
||||
{
|
||||
ClearDictionaryAndReleaseValues!(_componentClasses);
|
||||
|
||||
MonoTableInfo* typeDefinitionsTable = Mono.mono_image_get_table_info(s_CoreAssemblyImage, .MONO_TABLE_TYPEDEF);
|
||||
int32 numTypes = Mono.mono_table_info_get_rows(typeDefinitionsTable);
|
||||
|
||||
for (int32 i = 0; i < numTypes; i++)
|
||||
{
|
||||
int32[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_SIZE] cols = .();
|
||||
Mono.mono_metadata_decode_row(typeDefinitionsTable, i, (.)&cols, (.)SOME_RANDOM_ENUM.MONO_TYPEDEF_SIZE);
|
||||
|
||||
char8* nameSpace = Mono.mono_metadata_string_heap(s_CoreAssemblyImage, (.)cols[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_NAMESPACE]);
|
||||
char8* name = Mono.mono_metadata_string_heap(s_CoreAssemblyImage, (.)cols[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_NAME]);
|
||||
|
||||
MonoClass* monoClass = Mono.mono_class_from_name(s_CoreAssemblyImage, nameSpace, name);
|
||||
|
||||
// Check if it is a component but not the root Component class
|
||||
if (monoClass != null && monoClass != s_ComponentRoot.[Friend]_monoClass && Mono.mono_class_is_subclass_of(monoClass, s_ComponentRoot.[Friend]_monoClass, false))
|
||||
{
|
||||
ScriptClass componentClass = new ScriptClass(StringView(nameSpace), StringView(name), s_CoreAssemblyImage, .Component);
|
||||
_componentClasses.Add(componentClass.FullName, componentClass);
|
||||
|
||||
Log.EngineLogger.Info($"Added component \"{componentClass.FullName}\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReloadAssemblies()
|
||||
{
|
||||
@@ -399,27 +458,40 @@ static class ScriptEngine
|
||||
StringView classNamespace = StringView(Mono.mono_class_get_namespace(monoClass));
|
||||
|
||||
// TODO: at the moment only allow user-structs
|
||||
if (classNamespace.StartsWith("GlitchyEngine"))
|
||||
return null;
|
||||
//if (classNamespace.StartsWith("GlitchyEngine"))
|
||||
// return null;
|
||||
|
||||
ScriptFieldType scriptType = .None;
|
||||
|
||||
switch (fieldType)
|
||||
if (Mono.mono_class_is_enum(monoClass))
|
||||
{
|
||||
case .Class, .Valuetype, .Enum:
|
||||
ScriptFieldType scriptType = .None;
|
||||
scriptType = .Enum;
|
||||
|
||||
if (fieldType == .Class)
|
||||
scriptType = .Class;
|
||||
else if (fieldType == .Enum)
|
||||
scriptType = .Enum;
|
||||
else if (fieldType == .Valuetype)
|
||||
scriptType = .Struct;
|
||||
|
||||
Log.EngineLogger.AssertDebug(scriptType != .None);
|
||||
|
||||
return new SharpClass(classNamespace, className, Mono.mono_class_get_image(monoClass), scriptType);
|
||||
default:
|
||||
return null;
|
||||
return new SharpEnum(classNamespace, className, Mono.mono_class_get_image(monoClass));
|
||||
}
|
||||
else if (fieldType == .Class)
|
||||
{
|
||||
if (Mono.mono_class_is_subclass_of(monoClass, s_EntityRoot._monoClass, false))
|
||||
{
|
||||
scriptType = .Entity;
|
||||
}
|
||||
else if (Mono.mono_class_is_subclass_of(monoClass, s_ComponentRoot._monoClass, false))
|
||||
{
|
||||
scriptType = .Component;
|
||||
}
|
||||
else
|
||||
{
|
||||
scriptType = .Class;
|
||||
}
|
||||
}
|
||||
else if (fieldType == .Valuetype)
|
||||
{
|
||||
scriptType = .Struct;
|
||||
}
|
||||
|
||||
Log.EngineLogger.AssertDebug(scriptType != .None);
|
||||
|
||||
return new SharpClass(classNamespace, className, Mono.mono_class_get_image(monoClass), scriptType);
|
||||
}
|
||||
|
||||
public static void CreateScriptFieldMap(Entity entity)
|
||||
@@ -442,10 +514,24 @@ static class ScriptEngine
|
||||
|
||||
Log.EngineLogger.AssertDebug(scriptClass != null);
|
||||
|
||||
for (let (fieldName, field) in scriptClass.Fields)
|
||||
void AddFieldsToMap(Dictionary<StringView, ScriptField> classFields, StringView baseName)
|
||||
{
|
||||
entityFields.Add(new String(fieldName), ScriptFieldInstance(field.FieldType));
|
||||
for (let (fieldName, field) in classFields)
|
||||
{
|
||||
/*if (field.FieldType == .Struct && field.SharpType != null)
|
||||
{
|
||||
AddFieldsToMap(field.SharpType.Fields, scope $"{baseName}{fieldName}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
entityFields.Add(new $"{baseName}{fieldName}", ScriptFieldInstance(field.FieldType));
|
||||
}*/
|
||||
|
||||
entityFields.Add(new String(fieldName), ScriptFieldInstance(field.FieldType));
|
||||
}
|
||||
}
|
||||
|
||||
AddFieldsToMap(scriptClass.Fields, "");
|
||||
}
|
||||
|
||||
public static ScriptFieldMap GetScriptFieldMap(Entity entity)
|
||||
@@ -474,4 +560,27 @@ static class ScriptEngine
|
||||
|
||||
return scriptClass;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void HandleMonoException(MonoException* exception, ScriptInstance sourceInstance = null)
|
||||
{
|
||||
MonoExceptionHelper wrappedException = new MonoExceptionHelper(exception);
|
||||
|
||||
String entityInfo = scope .();
|
||||
|
||||
if (sourceInstance != null)
|
||||
{
|
||||
wrappedException.Instance = sourceInstance.EntityId;
|
||||
|
||||
Result<Entity> sourceEntity = Context.GetEntityByID(sourceInstance.EntityId);
|
||||
|
||||
if (sourceEntity case .Ok(let e))
|
||||
{
|
||||
entityInfo.AppendF($" ({e.Name} | {sourceInstance.EntityId})");
|
||||
}
|
||||
}
|
||||
|
||||
Log.ClientLogger.Error($"Mono Exception \"{wrappedException.FullName}\": \"{wrappedException.Message}\"{entityInfo}\nStackTrace:\n{wrappedException.StackTrace}", wrappedException);
|
||||
|
||||
wrappedException.ReleaseRef();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ enum ScriptFieldType
|
||||
case Double, Double2, Double3, Double4;
|
||||
|
||||
case Entity;
|
||||
case Component;
|
||||
|
||||
public Type GetBeefType()
|
||||
{
|
||||
@@ -79,6 +80,8 @@ enum ScriptFieldType
|
||||
|
||||
case .Entity:
|
||||
return typeof(UUID);
|
||||
case .Component:
|
||||
return typeof(UUID);
|
||||
|
||||
default:
|
||||
return null;
|
||||
|
||||
@@ -4,6 +4,8 @@ using System;
|
||||
|
||||
namespace GlitchyEngine.Scripting;
|
||||
|
||||
using internal GlitchyEngine.Scripting;
|
||||
|
||||
class ScriptInstance : RefCounter
|
||||
{
|
||||
private ScriptClass _scriptClass;
|
||||
@@ -11,6 +13,8 @@ class ScriptInstance : RefCounter
|
||||
private MonoObject* _instance;
|
||||
private uint32 _gcHandle;
|
||||
|
||||
private UUID _entityId;
|
||||
|
||||
public ScriptClass ScriptClass => _scriptClass;
|
||||
|
||||
/// Gets whether or not the instance has ben initialized.
|
||||
@@ -21,9 +25,15 @@ class ScriptInstance : RefCounter
|
||||
|
||||
private bool _isCreated = false;
|
||||
|
||||
public this(ScriptClass scriptClass)
|
||||
internal MonoObject* MonoInstance => _instance;
|
||||
|
||||
public UUID EntityId => _entityId;
|
||||
|
||||
public this(UUID entityId, ScriptClass scriptClass)
|
||||
{
|
||||
Log.EngineLogger.AssertDebug(scriptClass != null);
|
||||
|
||||
_entityId = entityId;
|
||||
_scriptClass = scriptClass..AddRef();
|
||||
}
|
||||
|
||||
@@ -31,34 +41,44 @@ class ScriptInstance : RefCounter
|
||||
{
|
||||
if (_instance != null)
|
||||
{
|
||||
_scriptClass.OnDestroy(_instance);
|
||||
InvokeOnDestroy();
|
||||
Mono.mono_gchandle_free(_gcHandle);
|
||||
}
|
||||
_scriptClass?.ReleaseRef();
|
||||
}
|
||||
|
||||
internal MonoObject* MonoInstance => _instance;
|
||||
|
||||
public void Instantiate(UUID uuid)
|
||||
{
|
||||
_instance = _scriptClass.CreateInstance(uuid);
|
||||
_instance = _scriptClass.CreateInstance(uuid, let exception);
|
||||
_gcHandle = Mono.mono_gchandle_new(_instance, true);
|
||||
|
||||
if (exception != null)
|
||||
ScriptEngine.HandleMonoException(exception, this);
|
||||
}
|
||||
|
||||
public void InvokeOnCreate()
|
||||
{
|
||||
_scriptClass.OnCreate(_instance);
|
||||
_scriptClass.OnCreate(_instance, let exception);
|
||||
_isCreated = true;
|
||||
|
||||
if (exception != null)
|
||||
ScriptEngine.HandleMonoException(exception, this);
|
||||
}
|
||||
|
||||
public void InvokeOnUpdate(float deltaTime)
|
||||
{
|
||||
_scriptClass.OnUpdate(_instance, deltaTime);
|
||||
_scriptClass.OnUpdate(_instance, deltaTime, let exception);
|
||||
|
||||
if (exception != null)
|
||||
ScriptEngine.HandleMonoException(exception, this);
|
||||
}
|
||||
|
||||
public void InvokeOnDestroy()
|
||||
{
|
||||
_scriptClass.OnDestroy(_instance);
|
||||
_scriptClass.OnDestroy(_instance, let exception);
|
||||
|
||||
if (exception != null)
|
||||
ScriptEngine.HandleMonoException(exception, this);
|
||||
}
|
||||
|
||||
public T GetFieldValue<T>(ScriptField field)
|
||||
@@ -70,4 +90,22 @@ class ScriptInstance : RefCounter
|
||||
{
|
||||
_scriptClass.SetFieldValue<T>(_instance, field.[Friend]_monoField, value);
|
||||
}
|
||||
|
||||
/// Creates a new instance of the given component class and initializes it for the current entity.
|
||||
public MonoObject* CreateComponentInstance(ScriptClass componentClassType)
|
||||
{
|
||||
MonoObject* componentInstance = componentClassType.CreateInstance();
|
||||
|
||||
// TODO: We could cache the property, but this might be fine
|
||||
MonoProperty* entityProperty = Mono.mono_class_get_property_from_name(componentClassType.[Friend]_monoClass, "Entity");
|
||||
|
||||
MonoObject* exception = null;
|
||||
|
||||
Mono.mono_property_set_value(entityProperty, componentInstance, (void**)&_instance, &exception);
|
||||
|
||||
if (exception != null)
|
||||
ScriptEngine.HandleMonoException((MonoException*)exception, this);
|
||||
|
||||
return componentInstance;
|
||||
}
|
||||
}
|
||||
@@ -100,6 +100,15 @@ namespace GlitchyEngine.World
|
||||
ScriptEngine.InitializeInstance(targetEntity, targetComponent);
|
||||
}
|
||||
|
||||
// Copy values to entities.
|
||||
// We do this in a separate loop because we might reference other entities.
|
||||
// If we did it in a single loop these entities might not exist yet.
|
||||
for (let (handle, script) in target._ecsWorld.Enumerate<ScriptComponent>())
|
||||
{
|
||||
Entity entity = .(handle, this);
|
||||
ScriptEngine.CopyEditorFieldsToInstance(entity, script);
|
||||
}
|
||||
|
||||
// Copy transforms... needs special handling for the Parent<->Child relations
|
||||
for (let (sourceHandle, sourceTransform) in _ecsWorld.Enumerate<TransformComponent>())
|
||||
{
|
||||
|
||||
@@ -613,39 +613,48 @@ class SceneSerializer
|
||||
// Allocate a string on the stack, because the dictionary uses a string as key
|
||||
String fieldNameString = scope .(fieldName);
|
||||
|
||||
Result<StringView> fieldTypeName = reader.Type();
|
||||
|
||||
if (fieldTypeName case .Err)
|
||||
{
|
||||
Log.EngineLogger.Error($"Failed to read field type for field \"{fieldName}\" in script \"{component.ScriptClassName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
||||
reader.FileEntrySkip(1);
|
||||
dontRemoveComma = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
Result<ScriptFieldType> fieldType = Enum.Parse<ScriptFieldType>(fieldTypeName, true);
|
||||
|
||||
if ((fieldType case .Err))
|
||||
{
|
||||
Log.EngineLogger.Error($"Error deserializing field type (Raw string: \"{fieldTypeName}\" of field: \"{fieldName}\" in script \"{component.ScriptClassName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
||||
reader.FileEntrySkip(1);
|
||||
dontRemoveComma = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8[sizeof(Matrix)] data = .();
|
||||
|
||||
if (Deserialize.Value(reader, ValueView(fieldType.Value.GetBeefType(), &data), gBonEnv) case .Err)
|
||||
{
|
||||
Log.EngineLogger.Error($"Failed to deserialize data for field: \"{fieldName}\" in script \"{component.ScriptClassName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
||||
reader.FileEntrySkip(1);
|
||||
dontRemoveComma = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fields.ContainsKey(fieldNameString))
|
||||
{
|
||||
var field = ref fields[fieldNameString];
|
||||
|
||||
Result<StringView> fieldTypeName = reader.Type();
|
||||
|
||||
if (fieldTypeName case .Err)
|
||||
{
|
||||
Log.EngineLogger.Error($"Failed to read field type for field \"{fieldName}\" in script \"{component.ScriptClassName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
||||
reader.FileEntrySkip(1);
|
||||
dontRemoveComma = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
Result<ScriptFieldType> fieldType = Enum.Parse<ScriptFieldType>(fieldTypeName, true);
|
||||
|
||||
if ((fieldType case .Err) || (fieldType != field.Type))
|
||||
// Make sure the type we deserialized actually is correct.
|
||||
if (fieldType != field.Type)
|
||||
{
|
||||
Log.EngineLogger.Error($"Unexpected field type (\"{fieldTypeName}\" instead of \"{field.Type}\" for field: \"{fieldName}\" in script \"{component.ScriptClassName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
||||
reader.FileEntrySkip(1);
|
||||
dontRemoveComma = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
void* data = &field.[Friend]_data;
|
||||
|
||||
if (Deserialize.Value(reader, ValueView(field.Type.GetBeefType(), data), gBonEnv) case .Err)
|
||||
{
|
||||
Log.EngineLogger.Error($"Failed to deserialize data for field: \"{fieldName}\" in script \"{component.ScriptClassName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
||||
reader.FileEntrySkip(1);
|
||||
dontRemoveComma = true;
|
||||
continue;
|
||||
}
|
||||
field.SetData(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Vendored
+1
-1
Submodule GlitchyEngine/vendor/imgui updated: 827764b98c...21c9c3225a
@@ -91,6 +91,9 @@ static class Mono
|
||||
|
||||
[LinkName(.C)]
|
||||
public static extern MonoType* mono_class_get_type(MonoClass* monoClass);
|
||||
|
||||
[LinkName(.C)]
|
||||
public static extern int32 mono_class_instance_size(MonoClass* @class);
|
||||
|
||||
[LinkName(.C)]
|
||||
public static extern char8* mono_class_get_namespace(MonoClass* monoClass);
|
||||
@@ -158,6 +161,9 @@ static class Mono
|
||||
[LinkName(.C)]
|
||||
public static extern MonoType* mono_reflection_type_get_type(MonoReflectionType* reflectionType);
|
||||
|
||||
[LinkName(.C)]
|
||||
public static extern MonoReflectionType* mono_type_get_object(MonoDomain *domain, MonoType *type);
|
||||
|
||||
[LinkName(.C)]
|
||||
public static extern MonoClassField* mono_class_get_fields(MonoClass* klass, gpointer* iter);
|
||||
|
||||
@@ -178,6 +184,9 @@ static class Mono
|
||||
|
||||
[LinkName(.C)]
|
||||
public static extern void mono_field_get_value(MonoObject* object, MonoClassField* field, void* value);
|
||||
|
||||
[LinkName(.C)]
|
||||
public static extern void mono_field_static_get_value(MonoVTable* vt, MonoClassField* field, void* value);
|
||||
|
||||
/// Gets the field as object, boxes the value if it is a valuetype.
|
||||
[LinkName(.C)]
|
||||
@@ -229,6 +238,37 @@ static class Mono
|
||||
|
||||
[LinkName(.C)]
|
||||
public static extern MonoThread* mono_thread_current();
|
||||
|
||||
#region Property
|
||||
|
||||
[LinkName(.C)]
|
||||
public static extern MonoProperty* mono_class_get_property_from_name(MonoClass *klass, char8* name);
|
||||
|
||||
[LinkName(.C)]
|
||||
public static extern void mono_property_set_value(MonoProperty *prop, void *obj, void **@params, MonoObject **exc);
|
||||
|
||||
[LinkName(.C)]
|
||||
public static extern MonoObject* mono_property_get_value(MonoProperty *prop, void *obj, void** @params, MonoObject** exc);
|
||||
|
||||
#endregion
|
||||
|
||||
[LinkName(.C)]
|
||||
public static extern char8* mono_exception_get_managed_backtrace(MonoException* exc);
|
||||
|
||||
[LinkName(.C)]
|
||||
public static extern MonoClass* mono_object_get_class(MonoObject* obj);
|
||||
|
||||
|
||||
[LinkName(.C)]
|
||||
public static extern mono_bool mono_class_is_enum(MonoClass* @class);
|
||||
|
||||
|
||||
[LinkName(.C)]
|
||||
public static extern MonoVTable* mono_class_vtable(MonoDomain* domain, MonoClass* @class);
|
||||
|
||||
|
||||
[LinkName(.C)]
|
||||
public static extern MonoObject* mono_value_box(MonoDomain* domain, MonoClass* klass, gpointer value);
|
||||
}
|
||||
|
||||
struct MonoDomain;
|
||||
@@ -247,8 +287,12 @@ struct MonoObject;
|
||||
|
||||
struct MonoMethod;
|
||||
|
||||
struct MonoProperty;
|
||||
|
||||
struct MonoThread;
|
||||
|
||||
struct MonoVTable;
|
||||
|
||||
struct MonoException
|
||||
{
|
||||
void* _bla;
|
||||
|
||||
@@ -86,10 +86,10 @@ namespace Sandbox
|
||||
|
||||
ImGui.Combo("Sampler", (.)&_sampleMode, items.Ptr, (.)items.Count);
|
||||
|
||||
ImGui.SliderFloat2("Color offset and scale", *(float[2]*)&_colorOffset, -1.0f, 1.0f);
|
||||
ImGui.SliderFloat2("Alpha offset and scale", *(float[2]*)&_alphaOffset, -1.0f, 1.0f);
|
||||
ImGui.SliderFloat2("Color offset and scale", ref *(float[2]*)&_colorOffset, -1.0f, 1.0f);
|
||||
ImGui.SliderFloat2("Alpha offset and scale", ref *(float[2]*)&_alphaOffset, -1.0f, 1.0f);
|
||||
|
||||
ImGui.SliderFloat2("Position", *(float[2]*)&_position, 2 * -Math.Max(viewedTexture.Width, viewedTexture.Height) * _zoom, 2 * Math.Max(viewedTexture.Width, viewedTexture.Height) * _zoom);
|
||||
ImGui.SliderFloat2("Position", ref *(float[2]*)&_position, 2 * -Math.Max(viewedTexture.Width, viewedTexture.Height) * _zoom, 2 * Math.Max(viewedTexture.Width, viewedTexture.Height) * _zoom);
|
||||
|
||||
ImGui.BeginChild("imageChild");
|
||||
|
||||
|
||||
@@ -2,6 +2,12 @@ using System;
|
||||
|
||||
namespace GlitchyEngine.Editor;
|
||||
|
||||
// TODO: Maybe rename, definitely move into different namespace
|
||||
/* Why?
|
||||
* - this attribute also means that the Field is being serialized
|
||||
* - Editor-Namespace wont be available for distribution builds of the game
|
||||
*/
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public sealed class ShowInEditorAttribute : Attribute
|
||||
{
|
||||
public string DisplayName { get; set; } = null;
|
||||
|
||||
Reference in New Issue
Block a user