Author SHA1 Message Date
Simon Lübeß 5d8c1b111a Project user settings, load recent scenes, properly cleanup ScriptEngine when switching scenes 2023-07-31 20:09:56 +02:00
Simon Lübeß 3298053d9d Fixed Asset Drag'n'Drop 2023-07-31 20:07:12 +02:00
Simon Lübeß adccb74f44 Editor Layer cleanup 2023-07-31 18:48:36 +02:00
Simon Lübeß 97113b5df6 Start of Create Asset Context Menu
+ Asset Hierarchy: Fixed Assets in Folder-Root not being shown
2023-07-31 17:40:05 +02:00
Simon Lübeß c374d86ec7 Cleanup 2023-07-31 16:40:27 +02:00
Simon Lübeß 803fd7f8ba Fixed crash when ScriptComponent has no Instance in Play Mode 2023-07-31 16:36:02 +02:00
Simon Lübeß 11a57f5285 Fixed ComponentEditWindow showing component editor after it was deleted 2023-07-31 16:35:38 +02:00
Simon Lübeß 0d015b485e Basic project creation
+ Added TreeNode.RemoveChild
+ Added Directory.Copy
+ Path.Combine now replaces alt directory separator
+ Project: Renamed ProjectName to Name
+ Project.Load: Save settings, if file doesn't exist
2023-07-31 16:35:12 +02:00
Simon Lübeß 17e4a6a589 Updated Beef.Linq 2023-07-30 20:32:19 +02:00
Simon Lübeß c1a87ed946 Separated Assets to Resources (Engine assets) and Assets (Project specific)
+ AssetHierarchy: Exposed RootNode
+ ContentBrowserWindow: Fixed Empty Folder not being Leaf-Node
+ TreeNode: Added IsParentOf, IsChildOf and IsInSubtree.
    + Fixed InternalDeleteTreeAndChildren for null trees
2023-07-30 20:30:06 +02:00
Simon Lübeß 20dae92be7 Fixed Assets having scrollbars in content browser 2023-07-30 13:55:50 +02:00
Simon Lübeß df67f32399 Start of project system
+ added Directory.IsEmpty
2023-07-30 13:23:34 +02:00
Simon Lübeß 14a802d057 Added new line to EditorLogger 2023-07-30 13:21:33 +02:00
Simon Lübeß 12d6df3edf Fixed crash when AssetViewer has size of 0 (RTFM) 2023-07-29 18:54:45 +02:00
Simon Lübeß 2838449186 Ignore MonoDebugger.log 2023-07-28 21:15:23 +02:00
Simon Lübeß 75513bea3d Removed obsolete texture viewer 2023-07-28 21:09:33 +02:00
Simon Lübeß 16c3d7c44d Updated ImGui 2023-07-28 13:38:59 +02:00
Simon Lübeß 7ae069baf6 Fixed loading UI font 2023-07-28 12:26:15 +02:00
Simon Lübeß 00dc3faa19 Failed to show and edit script sctruct
+ SizeInBytes for MonoFields
2023-07-28 11:48:01 +02:00
Simon Lübeß f39acdadb3 Show enum fields in Edit mode 2023-07-28 00:07:10 +02:00
Simon Lübeß 1254d01545 Handle exceptions from C# Scripts + Log window + EditorLogger
+ Renamed Platform/DX11/ImGui.bf to .../Dx11ImGui.bf for clarity
+ ImGuiExtension: ImageButtonEx thata takes a TextureViewBinding
+ EditorLogger that logs to the LogWindow
+ Current logger can now be changed
+ Info, Trace, Warning and Error Icons
2023-07-27 21:58:42 +02:00
Simon Lübeß 0bc517842f Allow changing logger 2023-07-27 00:42:42 +02:00
Simon Lübeß 3e63281508 Fixed mono debugging... 2023-07-26 22:56:43 +02:00
Simon Lübeß ef486b7082 Basic entity highlighting 2023-07-25 19:37:13 +02:00
Simon Lübeß 81a61d5a90 Drag'n'drop for components
+ Added CreateInstance to ScriptClass
+ Added CreateComponentInstance to ScriptInstance
2023-07-25 16:37:41 +02:00
Simon Lübeß 37197cbdf1 Allow dragging and dropping of Entities in editor
+ New Dictionary Helpers
+ Made ImGui Payloads safer
+ Start of Component drag'n'drop
2023-07-24 23:17:00 +02:00
Simon Lübeß b53ed2d8f2 Made script deserialization more robust 2023-07-24 21:28:58 +02:00
131 changed files with 3912 additions and 1134 deletions
+1
View File
@@ -8,3 +8,4 @@ imgui.ini
GlitchyEditor/resources/scripts/ScriptCore.dll GlitchyEditor/resources/scripts/ScriptCore.dll
GlitchyEditor/resources/scripts/ScriptCore.pdb GlitchyEditor/resources/scripts/ScriptCore.pdb
GlitchyEditor/settings.bon GlitchyEditor/settings.bon
GlitchyEditor/MonoDebugger.log
+1 -1
View File
@@ -7,4 +7,4 @@ TargetType = "BeefGUIApplication"
StartupObject = "GlitchyEngine.Program" StartupObject = "GlitchyEngine.Program"
[Configs.Debug.Win64] [Configs.Debug.Win64]
DebugCommandArguments = "\"content\\Scenes\\physics2D.scene\"" DebugCommandArguments = "\"D:\\Development\\Projects\\Beef\\GlitchyEngine\\GlitchyEditor\\SandboxProject\""
+1
View File
@@ -0,0 +1 @@
project_user.bon
@@ -30,10 +30,10 @@
} }
}, },
MeshComponent = { MeshComponent = {
Mesh = "Models/sphere.glb" Mesh = "Assets/Models/sphere.glb"
}, },
MeshRendererComponent = { MeshRendererComponent = {
Material = "Textures/TestMaterial.mat" Material = "Assets/Textures/TestMaterial.mat"
} }
}, },
{ {
@@ -49,12 +49,12 @@
}, },
Rotation = { Rotation = {
X = 0.614328027, X = 0.614328027,
Y = 0.239776045, Y = 0.23977606,
Z = 0.0315669999, Z = 0.0315669999,
W = 0.751073837 W = 0.751073778
}, },
Scale = { Scale = {
X = 0.999998868, X = 0.999998808,
Y = 1, Y = 1,
Z = 1.00000095 Z = 1.00000095
}, },
@@ -70,7 +70,7 @@
Color = { Color = {
R = 1, R = 1,
G = 0.991771996, G = 0.991771996,
B = 0.74086225 B = 0.74086231
} }
} }
}, },
@@ -103,10 +103,10 @@
} }
}, },
MeshComponent = { MeshComponent = {
Mesh = "Models/plane.glb" Mesh = "Assets/Models/plane.glb"
}, },
MeshRendererComponent = { MeshRendererComponent = {
Material = "Textures/TestMaterial.mat" Material = "Assets/Textures/TestMaterial.mat"
} }
}, },
{ {
@@ -146,7 +146,7 @@
OrthographicHeight = 10, OrthographicHeight = 10,
OrthographicNearPlane = 0, OrthographicNearPlane = 0,
OrthographicFarPlane = 10, OrthographicFarPlane = 10,
AspectRatio = 2.19888878, AspectRatio = 1.87453413,
FixedAspectRatio = false FixedAspectRatio = false
} }
}, },
@@ -164,7 +164,7 @@
Rotation = { Rotation = {
X = 0.18301262, X = 0.18301262,
Y = -0.683013558, Y = -0.683013558,
Z = 0.683012128, Z = 0.683012187,
W = 0.183013007 W = 0.183013007
}, },
Scale = { Scale = {
@@ -173,13 +173,13 @@
Z = 1 Z = 1
}, },
EditorEulerRotation = { EditorEulerRotation = {
X = 1.57079446, X = 1.57079458,
Y = -2.61799312, Y = -2.61799288,
Z = 0 Z = 0
} }
}, },
MeshComponent = { MeshComponent = {
Mesh = "Models/plane.glb" Mesh = ""
}, },
MeshRendererComponent = { MeshRendererComponent = {
Material = "" Material = ""
@@ -192,32 +192,32 @@
}, },
TransformComponent = { TransformComponent = {
Position = { Position = {
X = 2.37353587, X = 2.37353563,
Y = 0.629615188, Y = 0.629615188,
Z = -1.34831977 Z = -1.34831977
}, },
Rotation = { Rotation = {
X = 0.270598024, X = 0.270598024,
Y = -0.65328145, Y = -0.65328151,
Z = 0.65328151, Z = 0.65328151,
W = 0.270598054 W = 0.270598054
}, },
Scale = { Scale = {
X = 0.999999881, X = 0.999999821,
Y = 0.999999821, Y = 0.999999762,
Z = 0.999999702 Z = 0.999999702
}, },
EditorEulerRotation = { EditorEulerRotation = {
X = 1.57079637, X = 1.57079649,
Y = -2.3561945, Y = -2.35619426,
Z = 8.94069743e-08 Z = 8.94069601e-08
} }
}, },
MeshComponent = { MeshComponent = {
Mesh = "Models/plane.glb" Mesh = "Assets/Models/plane.glb"
}, },
MeshRendererComponent = { MeshRendererComponent = {
Material = "Textures/RocketMaterial.mat" Material = "Assets/Textures/RocketMaterial.mat"
} }
} }
] ]
@@ -13,7 +13,7 @@
B = 0.32878688, B = 0.32878688,
A = 1 A = 1
}, },
Sprite = "Textures/TestMat/rustediron2_albedo.png", Sprite = "Assets/Textures/TestMat/rustediron2_albedo.png",
UvTransform = { UvTransform = {
X = 0, X = 0,
Y = 0, Y = 0,
@@ -71,8 +71,8 @@
SpriteRendererComponent = { SpriteRendererComponent = {
Color = { Color = {
R = 1, R = 1,
G = 0.941886961, G = 0.941887021,
B = 0.401484549, B = 0.401484489,
A = 1 A = 1
}, },
Sprite = "", Sprite = "",
@@ -162,7 +162,7 @@
OrthographicHeight = 10, OrthographicHeight = 10,
OrthographicNearPlane = 0, OrthographicNearPlane = 0,
OrthographicFarPlane = 10, OrthographicFarPlane = 10,
AspectRatio = 0.884925187, AspectRatio = 2.05582929,
FixedAspectRatio = false FixedAspectRatio = false
}, },
ScriptComponent = { ScriptComponent = {
@@ -195,8 +195,8 @@
}, },
TransformComponent = { TransformComponent = {
Position = { Position = {
X = -0.121203184, X = -0.121203206,
Y = 0.660160959, Y = 0.660161078,
Z = 0 Z = 0
}, },
Rotation = { Rotation = {
@@ -234,37 +234,12 @@
ScriptComponent = { ScriptComponent = {
ScriptClass = "Sandbox.MyTestEntity", ScriptClass = "Sandbox.MyTestEntity",
Fields = [ Fields = [
Bo = (Bool)false, _rigidBody = (Component)15710354273720487680,
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
},
TheEntity = (Entity)0, TheEntity = (Entity)0,
JumpForce = (Float)200, JumpForce = (Float)200,
MoveForce = (Float)148, MoveForce = (Float)148,
MyNumber = (Int)22, MyNumber = (Int)22,
MyDouble = (Double)23 Camera = (Entity)1491484622542812645
] } ] }
}, },
{ {
@@ -301,7 +276,7 @@
Color = { Color = {
R = 0.985467017, R = 0.985467017,
G = 1, G = 1,
B = 0.569978058 B = 0.569977939
} }
} }
}, },
@@ -334,10 +309,10 @@
} }
}, },
MeshComponent = { MeshComponent = {
Mesh = "Models/sphere.glb" Mesh = "Assets/Models/sphere.glb"
}, },
MeshRendererComponent = { MeshRendererComponent = {
Material = "Textures/TestMaterial.mat" Material = "Assets/Textures/TestMaterial.mat"
} }
}, },
{ {
@@ -348,8 +323,8 @@
SpriteRendererComponent = { SpriteRendererComponent = {
Color = { Color = {
R = 0.425658971, R = 0.425658971,
G = 0.855207562, G = 0.855207443,
B = 0.0558161102, B = 0.0558161177,
A = 1 A = 1
}, },
Sprite = "", Sprite = "",
@@ -363,14 +338,14 @@
TransformComponent = { TransformComponent = {
Position = { Position = {
X = 6.74610233, X = 6.74610233,
Y = -2.03225899, Y = -2.03225946,
Z = 0 Z = 0
}, },
Rotation = { Rotation = {
X = 0, X = 0,
Y = 0, Y = 0,
Z = -0.331792623, Z = -0.331792623,
W = 0.943352342 W = 0.94335258
}, },
Scale = { Scale = {
X = 5.29557419, X = 5.29557419,
@@ -409,7 +384,7 @@
}, },
SpriteRendererComponent = { SpriteRendererComponent = {
Color = { Color = {
R = 0.666116953, R = 0.666117013,
G = 0.0600316115, G = 0.0600316115,
B = 1, B = 1,
A = 1 A = 1
@@ -424,8 +399,8 @@
}, },
TransformComponent = { TransformComponent = {
Position = { Position = {
X = 15.2321301, X = 15.2321281,
Y = -1.98709249, Y = -1.98709273,
Z = 0 Z = 0
}, },
Rotation = { Rotation = {
@@ -435,7 +410,7 @@
W = 0.990847468 W = 0.990847468
}, },
Scale = { Scale = {
X = 13.9764566, X = 13.9764528,
Y = 1, Y = 1,
Z = 1 Z = 1
}, },
@@ -471,7 +446,7 @@
}, },
SpriteRendererComponent = { SpriteRendererComponent = {
Color = { Color = {
R = 0.176544324, R = 0.176544309,
G = 0.666713238, G = 0.666713238,
B = 0.687030852, B = 0.687030852,
A = 1 A = 1
@@ -487,24 +462,24 @@
TransformComponent = { TransformComponent = {
Position = { Position = {
X = -6.27842855, X = -6.27842855,
Y = 2.62550211, Y = 2.62550163,
Z = 0 Z = 0
}, },
Rotation = { Rotation = {
X = 0, X = 0,
Y = 0, Y = 0,
Z = 0.187087834, Z = 0.187087879,
W = 0.982343197 W = 0.982343197
}, },
Scale = { Scale = {
X = 0.999999523, X = 0.999999464,
Y = 6.49634314, Y = 6.49634314,
Z = 1 Z = 1
}, },
EditorEulerRotation = { EditorEulerRotation = {
X = 0, X = 0,
Y = 0, Y = 0,
Z = 0.376393586 Z = 0.376393616
} }
}, },
Rigidbody2D = { Rigidbody2D = {
@@ -522,7 +497,7 @@
}, },
Density = 1, Density = 1,
Friction = 0.5, Friction = 0.5,
Restitution = 0.899999976, Restitution = 0.899999857,
RestitutionThreshold = 0.5 RestitutionThreshold = 0.5
} }
} }
@@ -11,9 +11,9 @@ namespace Sandbox
public enum MyEnum public enum MyEnum
{ {
Yes, Yes = 1,
No, No,
Maybe Maybe = 1337
} }
public struct MyStruct public struct MyStruct
@@ -25,36 +25,38 @@ namespace Sandbox
class MyTestEntity : Entity class MyTestEntity : Entity
{ {
//[ShowInEditor] [ShowInEditor]
RigidBody2D _rigidBody; RigidBody2D _rigidBody;
public bool Bo; //public bool Bo;
public byte By; //public byte By;
public ushort Us; //public ushort Us;
public uint Ui; //public uint Ui;
public ulong Ul; //public ulong Ul;
public sbyte Sb; //public sbyte Sb;
public short Sh; //public short Sh;
public int In; //public int In;
public long Lo; //public long Lo;
public float Fl; //public float Fl;
public double Do; //public double Do;
public float2 V2; //public float2 V2;
public float3 V3; //public float3 V3;
public float4 V4; //public float4 V4;
public Entity TheEntity; public Entity TheEntity;
public float JumpForce = 2000; public float JumpForce = 2000;
[ShowInEditor] float MoveForce = 1000; [ShowInEditor] float MoveForce = 1000;
[ShowInEditor] private int MyNumber = 1337; [ShowInEditor] private int MyNumber = 1337;
[ShowInEditor] public double MyDouble = 1000.0f; //[ShowInEditor] public double MyDouble = 1000.0f;
public MyStruct AStruct; public MyStruct AStruct;
public MyEnum AEnum = MyEnum.Maybe;
public Camera Camera; public Camera Camera;
/// <summary> /// <summary>
@@ -66,8 +68,16 @@ namespace Sandbox
Log.Info($"Jump Force: {JumpForce}"); Log.Info($"Jump Force: {JumpForce}");
_rigidBody ??= GetComponent<RigidBody2D>() ?? AddComponent<RigidBody2D>(); //_rigidBody ??= GetComponent<RigidBody2D>() ?? AddComponent<RigidBody2D>();
if (_rigidBody == null)
{
Log.Error("_rigidBody was not set in editor.");
}
if (Camera == null)
{
Log.Warning("Camera wasn't set in editor. Searching...");
Camera = FindEntityWithName("Camera").As<Camera>(); Camera = FindEntityWithName("Camera").As<Camera>();
if (Camera == null) if (Camera == null)
@@ -75,6 +85,23 @@ namespace Sandbox
Log.Error("Camera not found."); 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> /// <summary>
/// Called every frame. /// Called every frame.
@@ -105,6 +132,9 @@ namespace Sandbox
force.Y += JumpForce; force.Y += JumpForce;
} }
if (Input.IsKeyPressing(Key.N))
SubVoid();
_rigidBody.ApplyForceToCenter(force); _rigidBody.ApplyForceToCenter(force);
if (Input.IsMouseButtonReleasing(MouseButton.MiddleButton)) if (Input.IsMouseButtonReleasing(MouseButton.MiddleButton))
@@ -5,11 +5,11 @@ using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden // Allgemeine Informationen über eine Assembly werden über die folgenden
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
// die einer Assembly zugeordnet sind. // die einer Assembly zugeordnet sind.
[assembly: AssemblyTitle("Sanbox")] [assembly: AssemblyTitle("SandboxProject")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Sanbox")] [assembly: AssemblyProduct("SandboxProject")]
[assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
@@ -7,15 +7,15 @@
<ProjectGuid>{7A70819C-5317-402A-8553-95C5A001E370}</ProjectGuid> <ProjectGuid>{7A70819C-5317-402A-8553-95C5A001E370}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Sandbox</RootNamespace> <RootNamespace>SandboxProject</RootNamespace>
<AssemblyName>Sandbox</AssemblyName> <AssemblyName>SandboxProject</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic> <Deterministic>true</Deterministic>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>portable</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\</OutputPath> <OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.4.33205.214 VisualStudioVersion = 17.4.33205.214
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sandbox", "Sandbox.csproj", "{7A70819C-5317-402A-8553-95C5A001E370}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SandboxProject", "SandboxProject.csproj", "{7A70819C-5317-402A-8553-95C5A001E370}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScriptCore", "..\..\..\..\ScriptCore\ScriptCore.csproj", "{6222C226-FC78-498C-80BA-5CF10AC9123C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScriptCore", "..\..\..\..\ScriptCore\ScriptCore.csproj", "{6222C226-FC78-498C-80BA-5CF10AC9123C}"
EndProject EndProject

Before

Width:  |  Height:  |  Size: 119 B

After

Width:  |  Height:  |  Size: 119 B

@@ -0,0 +1,31 @@
{
Effect = "Resources/Shaders/myEffect.hlsl",
Textures = [
"AlbedoTexture": "Assets/Textures/rocket.png",
"NormalTexture": "Assets/Textures/TestMat/rustediron2_normal.png",
"MetallicTexture": "Assets/Textures/TestMat/rustediron2_metallic.png",
"RoughnessTexture": "Assets/Textures/TestMat/rustediron2_roughness.png"
],
Variables = [
"AlbedoColor": .ColorRGBA{
Value = {
R = 1,
G = 1,
B = 1,
A = 1
}
},
"NormalScaling": .Float2{
Value = {
X = 1,
Y = 1
}
},
"MetallicFactor": .Float{
Value = 0
},
"RoughnessFactor": .Float{
Value = 1
}
]
}

Before

Width:  |  Height:  |  Size: 119 B

After

Width:  |  Height:  |  Size: 119 B

Before

Width:  |  Height:  |  Size: 10 MiB

After

Width:  |  Height:  |  Size: 10 MiB

Before

Width:  |  Height:  |  Size: 3.3 MiB

After

Width:  |  Height:  |  Size: 3.3 MiB

Before

Width:  |  Height:  |  Size: 7.4 MiB

After

Width:  |  Height:  |  Size: 7.4 MiB

Before

Width:  |  Height:  |  Size: 3.0 MiB

After

Width:  |  Height:  |  Size: 3.0 MiB

@@ -1,11 +1,11 @@
{ {
Effect = "Shaders/myEffect.hlsl", Effect = "Resources/Shaders/myEffect.hlsl",
Textures = [ Textures = [
"AlbedoTexture": "Textures/TestMat/rustediron2_albedo.png", "AlbedoTexture": "Assets/Textures/TestMat/rustediron2_albedo.png",
"NormalTexture": "Textures/TestMat/rustediron2_normal.png", "NormalTexture": "Assets/Textures/TestMat/rustediron2_normal.png",
"MetallicTexture": "Textures/TestMat/rustediron2_metallic.png", "MetallicTexture": "Assets/Textures/TestMat/rustediron2_metallic.png",
"RoughnessTexture": "Textures/TestMat/rustediron2_roughness.png", "RoughnessTexture": "Assets/Textures/TestMat/rustediron2_roughness.png",
"EmissiveTexture": "Textures/rocket.png" "EmissiveTexture": "Assets/Textures/rocket.png"
], ],
Variables = [ Variables = [
"AlbedoColor": .ColorRGBA{ "AlbedoColor": .ColorRGBA{

Before

Width:  |  Height:  |  Size: 119 B

After

Width:  |  Height:  |  Size: 119 B

Before

Width:  |  Height:  |  Size: 258 B

After

Width:  |  Height:  |  Size: 258 B

+1
View File
@@ -0,0 +1 @@
{_projectName="SandboxProject"}
Binary file not shown.
Binary file not shown.
@@ -1,31 +0,0 @@
{
Effect = "Shaders/myEffect.hlsl",
Textures = [
"AlbedoTexture": "Textures/rocket.png",
"NormalTexture": "Textures/TestMat/rustediron2_normal.png",
"MetallicTexture": "Textures/TestMat/rustediron2_metallic.png",
"RoughnessTexture": "Textures/TestMat/rustediron2_roughness.png"
],
Variables = [
"AlbedoColor": .ColorRGBA{
Value = {
R = 1,
G = 1,
B = 1,
A = 1
}
},
"NormalScaling": .Float2{
Value = {
X = 1,
Y = 1
}
},
"MetallicFactor": .Float{
Value = 0
},
"RoughnessFactor": .Float{
Value = 1
}
]
}
@@ -0,0 +1 @@
project_user.bon
@@ -0,0 +1,398 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
// die einer Assembly zugeordnet sind.
[assembly: AssemblyTitle("[ProjectName]")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("[ProjectName]")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von
// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
[assembly: ComVisible(false)]
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
[assembly: Guid("7a70819c-5317-402a-8553-95c5a001e370")]
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
//
// Hauptversion
// Nebenversion
// Buildnummer
// Revision
//
// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
// indem Sie "*" wie unten gezeigt eingeben:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{7A70819C-5317-402A-8553-95C5A001E370}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>[ProjectName]</RootNamespace>
<AssemblyName>[ProjectName]</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>portable</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>default</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>default</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="ScriptCore, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>[CoreLibPath]</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
@@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33205.214
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "[ProjectName]", "[ProjectName].csproj", "{7A70819C-5317-402A-8553-95C5A001E370}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7A70819C-5317-402A-8553-95C5A001E370}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7A70819C-5317-402A-8553-95C5A001E370}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7A70819C-5317-402A-8553-95C5A001E370}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7A70819C-5317-402A-8553-95C5A001E370}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B5D43D8D-D80B-41AA-BE40-1DC507D87148}
EndGlobalSection
EndGlobal
Binary file not shown.
@@ -9,8 +9,8 @@
AddressModeU = .Clamp, AddressModeU = .Clamp,
AddressModeV = .Clamp, AddressModeV = .Clamp,
AddressModeW = .Clamp, AddressModeW = .Clamp,
MipMinLOD = -340282346638528859811704183484516925440, MipMinLOD = -3.40282347e+38,
MipMaxLOD = 340282346638528859811704183484516925440, MipMaxLOD = 3.40282347e+38,
MaxAnisotropy = 1, MaxAnisotropy = 1,
BorderColor = { BorderColor = {
R = 1, R = 1,
Binary file not shown.
@@ -9,12 +9,21 @@
".NETStandard,Version=v2.0/": { ".NETStandard,Version=v2.0/": {
"ScriptCore/1.0.0": { "ScriptCore/1.0.0": {
"dependencies": { "dependencies": {
"Half": "1.0.0",
"NETStandard.Library": "2.0.3" "NETStandard.Library": "2.0.3"
}, },
"runtime": { "runtime": {
"ScriptCore.dll": {} "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": {}, "Microsoft.NETCore.Platforms/1.1.0": {},
"NETStandard.Library/2.0.3": { "NETStandard.Library/2.0.3": {
"dependencies": { "dependencies": {
@@ -29,6 +38,13 @@
"serviceable": false, "serviceable": false,
"sha512": "" "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": { "Microsoft.NETCore.Platforms/1.1.0": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
+243 -62
View File
@@ -12,6 +12,7 @@ public class AssetNode
{ {
public String Name ~ delete _; public String Name ~ delete _;
public String Path ~ delete _; public String Path ~ delete _;
public String Identifier ~ delete _;
public bool IsDirectory; public bool IsDirectory;
@@ -38,14 +39,43 @@ public static class AssetIdentifier
{ {
public const char8 DirectorySeparatorChar = '/'; public const char8 DirectorySeparatorChar = '/';
// TODO: Asset identifiers and paths have little to do with each other and already caused a bit of pain, we should consider not using String for both.
/// Removes or unifies potential platform specific or file-path related stuff in the given asset identifier
public static void Fixup(String assetIdentifier) public static void Fixup(String assetIdentifier)
{ {
const String DotSeperator = $".{DirectorySeparatorChar}"; int dotIndex = 0;
const String SeperatorDot = $"{DirectorySeparatorChar}.";
assetIdentifier.Replace('\\', DirectorySeparatorChar); assetIdentifier.Replace('\\', DirectorySeparatorChar);
assetIdentifier.Replace(DotSeperator, "");
assetIdentifier.Replace(SeperatorDot, ""); // Replace /./ stuff
while ((dotIndex = assetIdentifier.IndexOf('.', dotIndex)) != -1)
{
char8 lastChar = '\0';
char8 nextChar = '\0';
int nextIndex = dotIndex + 1;
if (nextIndex < assetIdentifier.Length)
nextChar = assetIdentifier[nextIndex];
int lastIndex = dotIndex - 1;
if (lastIndex < assetIdentifier.Length)
lastChar = assetIdentifier[nextIndex];
// We either need to have a slash on both sides, or we have to be at the start or end of the string
if ((lastChar == '\0' || lastChar == DirectorySeparatorChar) &&
(lastChar == '\0' || lastChar == DirectorySeparatorChar))
{
if (lastChar != '\0')
assetIdentifier.Remove(lastIndex, 2);
else
assetIdentifier.Remove(dotIndex, 2);
}
else
{
// Skip the dot
dotIndex++;
}
}
if (assetIdentifier.StartsWith(DirectorySeparatorChar)) if (assetIdentifier.StartsWith(DirectorySeparatorChar))
assetIdentifier.Remove(0, 1); assetIdentifier.Remove(0, 1);
@@ -61,32 +91,124 @@ class AssetHierarchy
bool _fileSystemDirty = false; bool _fileSystemDirty = false;
internal TreeNode<AssetNode> _assetHierarchy = null ~ DeleteTreeAndChildren!(_); internal TreeNode<AssetNode> _assetRootNode = null ~ DeleteTreeAndChildren!(_);
internal TreeNode<AssetNode> _resourcesDirectoryNode = null;
internal TreeNode<AssetNode> _assetsDirectoryNode = null;
private append Dictionary<StringView, TreeNode<AssetNode>> _pathToAssetNode = .(); private append Dictionary<StringView, TreeNode<AssetNode>> _pathToAssetNode = .();
private append Dictionary<StringView, TreeNode<AssetNode>> _identifierToAssetNode = .();
private append String _contentDirectory = .(); private append String _resourcesDirectory = .();
private append String _assetsDirectory = .();
private EditorContentManager _contentManager; private EditorContentManager _contentManager;
public StringView ContentDirectory public TreeNode<AssetNode> RootNode => _assetRootNode;
public StringView ResourcesDirectory
{ {
get => _contentDirectory; get => _resourcesDirectory;
private set private set
{ {
_contentDirectory.Clear(); _resourcesDirectory.Set(value);
_contentDirectory.Append(value); Path.Fixup(_resourcesDirectory);
Path.Fixup(_contentDirectory); }
}
public StringView AssetsDirectory
{
get => _assetsDirectory;
private set
{
_assetsDirectory.Set(value);
Path.Fixup(_assetsDirectory);
} }
} }
public this(EditorContentManager contentManager) public this(EditorContentManager contentManager)
{ {
_contentManager = contentManager; _contentManager = contentManager;
// Create a root node that will contain all Asset directory nodes.
_assetRootNode = new TreeNode<AssetNode>(new AssetNode());
_assetRootNode->Path = new String();
_assetRootNode->Name = new String();
_assetRootNode->IsDirectory = true;
Log.EngineLogger.Trace($"Created root node");
} }
public void SetContentDirectory(StringView contentDirectory) public void SetResourcesDirectory(StringView fileName)
{ {
ContentDirectory = contentDirectory; ResourcesDirectory = fileName;
_resourcesDirectoryNode?.ForEach(scope (node) => {
_pathToAssetNode.Remove(node->Path);
_identifierToAssetNode.Remove(node->Identifier);
});
_assetRootNode.RemoveChild(_resourcesDirectoryNode);
DeleteTreeAndChildren!(_resourcesDirectoryNode);
_resourcesDirectoryNode = null;
if (!Directory.Exists(ResourcesDirectory))
{
Log.EngineLogger.Error($"Resources directory \"{ResourcesDirectory}\" doesn't exist.");
return;
}
AssetNode assetNode = new AssetNode();
assetNode.Path = new String(ResourcesDirectory);
assetNode.Name = new String();
assetNode.Identifier = new String("###resources");
assetNode.IsDirectory = true;
Path.GetFileName(assetNode.Path, assetNode.Name);
_resourcesDirectoryNode = _assetRootNode.AddChild(assetNode);
_pathToAssetNode.Add(assetNode.Path, _resourcesDirectoryNode);
_identifierToAssetNode.Add(assetNode.Identifier, _resourcesDirectoryNode);
Log.EngineLogger.Trace($"Created directory node for: \"{ResourcesDirectory}\"");
_fileSystemDirty = true;
// TODO: Watch resources folder?
//SetupResourcesFileSystemWatcher();
Update();
}
public void SetAssetsDirectory(StringView fileName)
{
AssetsDirectory = fileName;
_assetsDirectoryNode?.ForEach(scope (node) => {
_pathToAssetNode.Remove(node->Path);
_identifierToAssetNode.Remove(node->Identifier);
});
_assetRootNode.RemoveChild(_assetsDirectoryNode);
DeleteTreeAndChildren!(_assetsDirectoryNode);
_assetsDirectoryNode = null;
if (!Directory.Exists(AssetsDirectory))
{
// TODO: This is not an error, if no project is loaded
Log.EngineLogger.Warning($"Assets directory \"{AssetsDirectory}\" doesn't exist.");
return;
}
AssetNode assetNode = new AssetNode();
assetNode.Path = new String(AssetsDirectory);
assetNode.Name = new String();
assetNode.Identifier = new String("###assets");
assetNode.IsDirectory = true;
Path.GetFileName(assetNode.Path, assetNode.Name);
_assetsDirectoryNode = _assetRootNode.AddChild(assetNode);
_pathToAssetNode.Add(assetNode.Path, _assetsDirectoryNode);
_identifierToAssetNode.Add(assetNode.Identifier, _assetsDirectoryNode);
Log.EngineLogger.Trace($"Created directory node for: \"{AssetsDirectory}\"");
_fileSystemDirty = true; _fileSystemDirty = true;
@@ -99,7 +221,7 @@ class AssetHierarchy
private void SetupFileSystemWatcher() private void SetupFileSystemWatcher()
{ {
delete fsw; delete fsw;
fsw = new FileSystemWatcher(_contentDirectory); fsw = new FileSystemWatcher(_assetsDirectory);
fsw.IncludeSubdirectories = true; fsw.IncludeSubdirectories = true;
fsw.OnChanged.Add(new (filename) => { fsw.OnChanged.Add(new (filename) => {
@@ -126,15 +248,7 @@ class AssetHierarchy
fsw.OnRenamed.Add(new (oldName, newName) => { fsw.OnRenamed.Add(new (oldName, newName) => {
Log.EngineLogger.Trace($"File renamed (From \"{oldName}\" to \"{newName}\")"); Log.EngineLogger.Trace($"File renamed (From \"{oldName}\" to \"{newName}\")");
//_fileSystemDirty = true;
FileRenamed(oldName, newName); FileRenamed(oldName, newName);
/*String contentFilePath = scope String();
Path.InternalCombine(contentFilePath, ContentDirectory, oldName);
//_fileSystemDirty = true;
TreeNode<AssetNode> fileNode = GetNodeFromPath(contentFilePath);
fileNode->*/
}); });
fsw.StartRaisingEvents(); fsw.StartRaisingEvents();
@@ -153,6 +267,19 @@ class AssetHierarchy
return .Err; return .Err;
} }
/// Gets the tree node for the given filePath or .Err, if the file/directory doesn't exist.
/// @param filePath the path for which to return the tree node.
/// @remarks Do not hold a reference to the TreeNode because it can become invalid when the file hierarchy changes.
public Result<TreeNode<AssetNode>> GetNodeFromIdentifier(StringView identifier)
{
if (_identifierToAssetNode.TryGetValue(identifier, let treeNode))
{
return treeNode;
}
return .Err;
}
public bool FileExists(StringView filePath) public bool FileExists(StringView filePath)
{ {
return _pathToAssetNode.ContainsKey(filePath); return _pathToAssetNode.ContainsKey(filePath);
@@ -167,33 +294,36 @@ class AssetHierarchy
} }
} }
/// Determines and set the Identfier for the given asset node.
private void DetermineIdentifier(TreeNode<AssetNode> assetNode)
{
if (assetNode->Identifier == null)
assetNode->Identifier = new String();
assetNode->Identifier.Clear();
// Get the Identifier which is simply the path relative to the asste root (either Resources- or Assets-Folder)
if (assetNode.IsInSubtree(_resourcesDirectoryNode))
{
Path.GetRelativePath(assetNode->Path, _resourcesDirectoryNode->Path, assetNode->Identifier);
assetNode->Identifier.Insert(0, "Resources/");
}
else if (assetNode.IsInSubtree(_assetsDirectoryNode))
{
Path.GetRelativePath(assetNode->Path, _assetsDirectoryNode->Path, assetNode->Identifier);
assetNode->Identifier.Insert(0, "Assets/");
}
AssetIdentifier.Fixup(assetNode->Identifier);
}
/// Rebuilds the asset file hierarchy. /// Rebuilds the asset file hierarchy.
private void UpdateFiles() private void UpdateFiles()
{ {
Log.EngineLogger.Trace($"Updating asset hierarchy"); Log.EngineLogger.Trace($"Updating asset hierarchy");
if (_assetHierarchy == null)
{
// TODO: move to init?
_assetHierarchy = new TreeNode<AssetNode>(new AssetNode());
_assetHierarchy->Path = new String(ContentDirectory);
_assetHierarchy->Name = new String("Content");
_assetHierarchy->IsDirectory = true;
Log.EngineLogger.Trace($"Created directory node for: \"{_assetHierarchy->Path}\"");
_pathToAssetNode.Add(ContentDirectory, _assetHierarchy);
}
void HandleFile(AssetNode node) void HandleFile(AssetNode node)
{ {
String identifier = scope .(node.Path.Length); node.AssetFile = new AssetFile(_contentManager, node.Identifier, node.Path, node.IsDirectory);
Path.GetRelativePath(node.Path, _contentDirectory, identifier);
AssetIdentifier.Fixup(identifier);
node.AssetFile = new AssetFile(_contentManager, identifier, node.Path, node.IsDirectory);
} }
/// Determines the files that belong to the given directory and adds them to the tree. /// Determines the files that belong to the given directory and adds them to the tree.
@@ -212,6 +342,7 @@ class AssetHierarchy
entry.GetFilePath(filepathBuffer..Clear()); entry.GetFilePath(filepathBuffer..Clear());
Path.GetExtension(filepathBuffer, .. extensionBuffer..Clear()); Path.GetExtension(filepathBuffer, .. extensionBuffer..Clear());
filepathBuffer.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
// Ignore meta files. // Ignore meta files.
if (extensionBuffer.Equals(AssetFile.ConfigFileExtension, .OrdinalIgnoreCase)) if (extensionBuffer.Equals(AssetFile.ConfigFileExtension, .OrdinalIgnoreCase))
@@ -225,13 +356,15 @@ class AssetHierarchy
assetNode.Name = new String(); assetNode.Name = new String();
Path.GetFileName(filepathBuffer, assetNode.Name); Path.GetFileName(filepathBuffer, assetNode.Name);
filepathBuffer.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
assetNode.Path = new String(filepathBuffer); assetNode.Path = new String(filepathBuffer);
assetNode.IsDirectory = false; assetNode.IsDirectory = false;
treeNode = directory.AddChild(assetNode); treeNode = directory.AddChild(assetNode);
DetermineIdentifier(treeNode);
_pathToAssetNode.Add(assetNode.Path, treeNode); _pathToAssetNode.Add(assetNode.Path, treeNode);
_identifierToAssetNode.Add(assetNode.Identifier, treeNode);
//GrabSubAssets(node); //GrabSubAssets(node);
HandleFile(treeNode.Value); HandleFile(treeNode.Value);
@@ -243,17 +376,6 @@ class AssetHierarchy
void RemoveOrphanedEntries(TreeNode<AssetNode> node) void RemoveOrphanedEntries(TreeNode<AssetNode> node)
{ {
/// Removes the node and its children from _pathToAssetNode
void RemoveSubtree(TreeNode<AssetNode> tree)
{
_pathToAssetNode.Remove(tree->Path);
for (var child in tree.Children)
{
RemoveSubtree(child);
}
}
for (TreeNode<AssetNode> child in node.Children) for (TreeNode<AssetNode> child in node.Children)
{ {
if (!Directory.Exists(child->Path) && !File.Exists(child->Path)) if (!Directory.Exists(child->Path) && !File.Exists(child->Path))
@@ -262,7 +384,10 @@ class AssetHierarchy
@child.Remove(); @child.Remove();
RemoveSubtree(child); child.ForEach(scope (node) => {
_pathToAssetNode.Remove(node->Path);
_identifierToAssetNode.Remove(node->Identifier);
});
DeleteTreeAndChildren!(child); DeleteTreeAndChildren!(child);
} }
@@ -284,11 +409,30 @@ class AssetHierarchy
AssetNode assetNode = new AssetNode(); AssetNode assetNode = new AssetNode();
assetNode.Path = new String(path); assetNode.Path = new String(path);
assetNode.Name = new String(); assetNode.Name = new String();
//assetNode.Identifier = new String();
assetNode.IsDirectory = true; assetNode.IsDirectory = true;
Path.GetFileName(assetNode.Path, assetNode.Name); Path.GetFileName(assetNode.Path, assetNode.Name);
/*// Get the Identifier which is simply the path relative to the asste root (either Resources- or Assets-Folder)
if (parentNode == _resourcesDirectoryNode || parentNode.IsChildOf(_resourcesDirectoryNode))
{
Path.GetRelativePath(assetNode.Path, _resourcesDirectoryNode->Path, assetNode.Identifier);
assetNode.Identifier.Insert(0, "Resources/");
}
else
{
Path.GetRelativePath(assetNode.Path, _assetsDirectoryNode->Path, assetNode.Identifier);
assetNode.Identifier.Insert(0, "Assets/");
}
AssetIdentifier.Fixup(assetNode.Identifier);*/
treeNode = parentNode.AddChild(assetNode); treeNode = parentNode.AddChild(assetNode);
DetermineIdentifier(treeNode);
_pathToAssetNode.Add(assetNode.Path, treeNode); _pathToAssetNode.Add(assetNode.Path, treeNode);
// No Identifiers for Directories, because we can't use directories as Assets anyways...
//_identifierToAssetNode.Add(assetNode.Identifier, treeNode);
Log.EngineLogger.Trace($"Created directory node for: \"{assetNode.Path}\""); Log.EngineLogger.Trace($"Created directory node for: \"{assetNode.Path}\"");
} }
@@ -305,15 +449,48 @@ class AssetHierarchy
AddDirectoryToTree(directoryNameBuffer, treeNode); AddDirectoryToTree(directoryNameBuffer, treeNode);
} }
AddFilesOfDirectory(treeNode);
RemoveOrphanedEntries(treeNode); RemoveOrphanedEntries(treeNode);
AddFilesOfDirectory(treeNode);
} }
String filter = scope $"{ContentDirectory}/*"; if (!AssetsDirectory.IsWhiteSpace)
{
String filter = scope $"{AssetsDirectory}/*";
String directoryNameBuffer = scope String(256); String directoryNameBuffer = scope String(256);
for (var directory in Directory.Enumerate(filter, .Directories))
{
directory.GetFilePath(directoryNameBuffer..Clear());
AddDirectoryToTree(directoryNameBuffer, _assetsDirectoryNode);
}
RemoveOrphanedEntries(_assetsDirectoryNode);
AddFilesOfDirectory(_assetsDirectoryNode);
}
if (!ResourcesDirectory.IsWhiteSpace)
{
String filter = scope $"{ResourcesDirectory}/*";
String directoryNameBuffer = scope String(256);
for (var directory in Directory.Enumerate(filter, .Directories))
{
directory.GetFilePath(directoryNameBuffer..Clear());
AddDirectoryToTree(directoryNameBuffer, _resourcesDirectoryNode);
}
RemoveOrphanedEntries(_resourcesDirectoryNode);
AddFilesOfDirectory(_resourcesDirectoryNode);
}
//*String filter = scope $"{AssetsDirectory}/*";
/*
String directoryNameBuffer = scope String(256);
for (var directory in Directory.Enumerate(filter, .Directories)) for (var directory in Directory.Enumerate(filter, .Directories))
{ {
directory.GetFilePath(directoryNameBuffer..Clear()); directory.GetFilePath(directoryNameBuffer..Clear());
@@ -321,7 +498,7 @@ class AssetHierarchy
AddDirectoryToTree(directoryNameBuffer, _assetHierarchy); AddDirectoryToTree(directoryNameBuffer, _assetHierarchy);
} }
RemoveOrphanedEntries(_assetHierarchy); RemoveOrphanedEntries(_assetHierarchy);*/
_fileSystemDirty = false; _fileSystemDirty = false;
} }
@@ -336,7 +513,7 @@ class AssetHierarchy
fileName.RemoveFromEnd(AssetFile.ConfigFileExtension.Length); fileName.RemoveFromEnd(AssetFile.ConfigFileExtension.Length);
String fileNameWithContentRoot = scope .(); String fileNameWithContentRoot = scope .();
Path.InternalCombine(fileNameWithContentRoot, _contentDirectory, fileName); Path.InternalCombine(fileNameWithContentRoot, _assetsDirectory, fileName);
var nodeResult = GetNodeFromPath(fileNameWithContentRoot); var nodeResult = GetNodeFromPath(fileNameWithContentRoot);
@@ -366,10 +543,10 @@ class AssetHierarchy
String oldFileNameWithContentRoot = scope .(); String oldFileNameWithContentRoot = scope .();
Path.InternalCombine(oldFileNameWithContentRoot, _contentDirectory, oldFilePath); Path.InternalCombine(oldFileNameWithContentRoot, _assetsDirectory, oldFilePath);
String newFileNameWithContentRoot = scope .(); String newFileNameWithContentRoot = scope .();
Path.InternalCombine(newFileNameWithContentRoot, _contentDirectory, newFilePath); Path.InternalCombine(newFileNameWithContentRoot, _assetsDirectory, newFilePath);
// Rename config file // Rename config file
{ {
@@ -397,10 +574,14 @@ class AssetHierarchy
} }
_pathToAssetNode.Remove(oldFileNameWithContentRoot); _pathToAssetNode.Remove(oldFileNameWithContentRoot);
_identifierToAssetNode.Remove(node->Identifier);
node->Path.Set(newFileNameWithContentRoot); node->Path.Set(newFileNameWithContentRoot);
_pathToAssetNode.Add(node->Path, node); _pathToAssetNode.Add(node->Path, node);
DetermineIdentifier(node);
_identifierToAssetNode.Add(node->Identifier, node);
node->Name.Clear(); node->Name.Clear();
Path.GetFileName(newFileNameWithContentRoot, node->Name); Path.GetFileName(newFileNameWithContentRoot, node->Name);
@@ -33,7 +33,7 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
if (ImGui.BeginDragDropTarget()) if (ImGui.BeginDragDropTarget())
{ {
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM"); ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.ContentBrowserItem);
if (payload != null) if (payload != null)
{ {
@@ -78,7 +78,7 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
if (ImGui.BeginDragDropTarget()) if (ImGui.BeginDragDropTarget())
{ {
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM"); ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.ContentBrowserItem);
if (payload != null) if (payload != null)
{ {
@@ -120,7 +120,7 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
value = (float3)ColorRGB.LinearToSRGB((ColorRGB)value); 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); value = (float3)ColorRGB.SRgbToLinear((ColorRGB)value);
material.SetVariable(variable.Name, value); material.SetVariable(variable.Name, value);
@@ -132,7 +132,7 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
value = (float4)ColorRGBA.LinearToSRGB((ColorRGBA)value); 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); value = (float4)ColorRGBA.SRgbToLinear((ColorRGBA)value);
material.SetVariable(variable.Name, value); material.SetVariable(variable.Name, value);
@@ -149,7 +149,7 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
value = (float3)ColorRGB.LinearToSRGB((ColorRGB)value); 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); value = (float3)ColorRGB.SRgbToLinear((ColorRGB)value);
material.SetVariable(variable.Name, value); material.SetVariable(variable.Name, value);
@@ -161,7 +161,7 @@ class MaterialAssetPropertiesEditor : AssetPropertiesEditor
value = (float4)ColorRGBA.LinearToSRGB((ColorRGBA)value); 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); value = (float4)ColorRGBA.SRgbToLinear((ColorRGBA)value);
material.SetVariable(variable.Name, value); material.SetVariable(variable.Name, value);
+3 -7
View File
@@ -47,20 +47,16 @@ class AssetViewer : EditorWindow
ImGui.TableSetColumnIndex(0); ImGui.TableSetColumnIndex(0);
if (ImGui.BeginChild("Assets")) if (ImGui.BeginChild("Assets"))
{
DrawAssetList(); DrawAssetList();
ImGui.EndChild(); ImGui.EndChild();
}
ImGui.TableNextColumn(); ImGui.TableNextColumn();
if (ImGui.BeginChild("Files")) if (ImGui.BeginChild("Files"))
{
DrawAssetViewer(); DrawAssetViewer();
ImGui.EndChild(); ImGui.EndChild();
}
ImGui.EndTable(); ImGui.EndTable();
} }
@@ -179,8 +175,8 @@ class TexturererViewerer
public this() public this()
{ {
_effect = Content.LoadAsset("Shaders\\textureViewerShader.hlsl"); _effect = Content.LoadAsset("Resources/Shaders/textureViewerShader.hlsl");
_renderTargetEffect = Content.LoadAsset("Shaders\\RenderTargetGroupViewer.hlsl"); _renderTargetEffect = Content.LoadAsset("Resources/Shaders/RenderTargetGroupViewer.hlsl");
} }
float2 _position; float2 _position;
@@ -211,7 +207,7 @@ class TexturererViewerer
float maxDimension = max(width, height); 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(); ImGui.Separator();
@@ -7,6 +7,8 @@ using GlitchyEngine.Renderer;
using GlitchyEngine; using GlitchyEngine;
using GlitchyEngine.Content; using GlitchyEngine.Content;
using GlitchyEngine.Scripting; using GlitchyEngine.Scripting;
using GlitchyEngine.Core;
using Mono;
namespace GlitchyEditor.EditWindows namespace GlitchyEditor.EditWindows
{ {
@@ -110,7 +112,8 @@ namespace GlitchyEditor.EditWindows
if (nodeOpen) if (nodeOpen)
{ {
showComponentEditor(entity, component); if (entity.TryGetComponent<TComponent>(let actualComponent))
showComponentEditor(entity, actualComponent);
ImGui.TreePop(); ImGui.TreePop();
} }
@@ -278,7 +281,7 @@ namespace GlitchyEditor.EditWindows
if (ImGui.BeginDragDropTarget()) if (ImGui.BeginDragDropTarget())
{ {
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM"); ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.ContentBrowserItem);
if (payload != null) if (payload != null)
{ {
@@ -306,7 +309,7 @@ namespace GlitchyEditor.EditWindows
if (ImGui.BeginDragDropTarget()) if (ImGui.BeginDragDropTarget())
{ {
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM"); ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.ContentBrowserItem);
if (payload != null) if (payload != null)
{ {
@@ -338,7 +341,7 @@ namespace GlitchyEditor.EditWindows
if (ImGui.BeginDragDropTarget()) if (ImGui.BeginDragDropTarget())
{ {
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM"); ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.ContentBrowserItem);
if (payload != null) if (payload != null)
{ {
@@ -512,11 +515,89 @@ namespace GlitchyEditor.EditWindows
scriptInstance.SetFieldValue<T>(scriptField, value); 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) if (scriptComponent.Instance?.IsInitialized == true)
{ {
SharpClass sharpClass = scriptComponent.Instance.ScriptClass; SharpClass sharpClass = scriptComponent.Instance.ScriptClass;
ScriptInstance scriptInstance = scriptComponent.Instance; 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) for (let (fieldName, scriptField) in sharpClass.Fields)
{ {
var monoField = scriptField.[Friend]_monoField; var monoField = scriptField.[Friend]_monoField;
@@ -592,6 +673,22 @@ namespace GlitchyEditor.EditWindows
// TODO! // TODO!
case .Struct: case .Struct:
// TODO! // 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: default:
Log.EngineLogger.Error($"Unhandled field type {scriptField.FieldType}"); Log.EngineLogger.Error($"Unhandled field type {scriptField.FieldType}");
} }
@@ -601,107 +698,111 @@ namespace GlitchyEditor.EditWindows
{ {
let scriptFields = ScriptEngine.GetScriptFieldMap(entity); let scriptFields = ScriptEngine.GetScriptFieldMap(entity);
for (var (name, field) in ref scriptFields) for (var (fieldName, field) in ref scriptFields)
{ {
switch (field.Type) switch (field.Type)
{ {
case .Bool: case .Bool:
var value = field.GetData<bool>(); var value = field.GetData<bool>();
if (ImGui.Checkbox(name.CStr(), &value)) if (ImGui.Checkbox(fieldName.CStr(), &value))
field.SetData(value); field.SetData(value);
case .SByte: case .SByte:
var value = field.GetData<int8>(); var value = field.GetData<int8>();
if (ImGui.DragScalar(name.CStr(), .S8, &value)) if (ImGui.DragScalar(fieldName.CStr(), .S8, &value))
field.SetData(value); field.SetData(value);
case .Short: case .Short:
var value = field.GetData<int16>(); var value = field.GetData<int16>();
if (ImGui.DragScalar(name.CStr(), .S16, &value)) if (ImGui.DragScalar(fieldName.CStr(), .S16, &value))
field.SetData(value); field.SetData(value);
case .Int: case .Int:
var value = field.GetData<int32>(); var value = field.GetData<int32>();
if (ImGui.DragScalar(name.CStr(), .S32, &value)) if (ImGui.DragScalar(fieldName.CStr(), .S32, &value))
field.SetData(value); field.SetData(value);
case .Int2: case .Int2:
var value = field.GetData<int2>(); var value = field.GetData<int2>();
if (ImGui.DragScalarN(name.CStr(), .S32, &value, 2)) if (ImGui.DragScalarN(fieldName.CStr(), .S32, &value, 2))
field.SetData(value); field.SetData(value);
case .Int3: case .Int3:
var value = field.GetData<int3>(); var value = field.GetData<int3>();
if (ImGui.DragScalarN(name.CStr(), .S32, &value, 3)) if (ImGui.DragScalarN(fieldName.CStr(), .S32, &value, 3))
field.SetData(value); field.SetData(value);
case .Int4: case .Int4:
var value = field.GetData<int4>(); var value = field.GetData<int4>();
if (ImGui.DragScalarN(name.CStr(), .S32, &value, 4)) if (ImGui.DragScalarN(fieldName.CStr(), .S32, &value, 4))
field.SetData(value); field.SetData(value);
case .Long: case .Long:
var value = field.GetData<int64>(); var value = field.GetData<int64>();
if (ImGui.DragScalar(name.CStr(), .S64, &value)) if (ImGui.DragScalar(fieldName.CStr(), .S64, &value))
field.SetData(value); field.SetData(value);
case .Byte: case .Byte:
var value = field.GetData<uint8>(); var value = field.GetData<uint8>();
if (ImGui.DragScalar(name.CStr(), .U8, &value)) if (ImGui.DragScalar(fieldName.CStr(), .U8, &value))
field.SetData(value); field.SetData(value);
case .UShort: case .UShort:
var value = field.GetData<uint16>(); var value = field.GetData<uint16>();
if (ImGui.DragScalar(name.CStr(), .U16, &value)) if (ImGui.DragScalar(fieldName.CStr(), .U16, &value))
field.SetData(value); field.SetData(value);
case .UInt: case .UInt:
var value = field.GetData<uint32>(); var value = field.GetData<uint32>();
if (ImGui.DragScalar(name.CStr(), .U32, &value)) if (ImGui.DragScalar(fieldName.CStr(), .U32, &value))
field.SetData(value); field.SetData(value);
case .ULong: case .ULong:
var value = field.GetData<uint64>(); var value = field.GetData<uint64>();
if (ImGui.DragScalar(name.CStr(), .U64, &value)) if (ImGui.DragScalar(fieldName.CStr(), .U64, &value))
field.SetData(value); field.SetData(value);
case .Float: case .Float:
var value = field.GetData<float>(); var value = field.GetData<float>();
if (ImGui.DragScalar(name.CStr(), .Float, &value)) if (ImGui.DragScalar(fieldName.CStr(), .Float, &value))
field.SetData(value); field.SetData(value);
case .float2: case .float2:
var value = field.GetData<float2>(); var value = field.GetData<float2>();
if (ImGui.Editfloat2(name, ref value)) if (ImGui.Editfloat2(fieldName, ref value))
field.SetData(value); field.SetData(value);
case .float3: case .float3:
var value = field.GetData<float3>(); var value = field.GetData<float3>();
if (ImGui.Editfloat3(name, ref value)) if (ImGui.Editfloat3(fieldName, ref value))
field.SetData(value); field.SetData(value);
case .float4: case .float4:
var value = field.GetData<float4>(); var value = field.GetData<float4>();
if (ImGui.Editfloat4(name, ref value)) if (ImGui.Editfloat4(fieldName, ref value))
field.SetData(value); field.SetData(value);
case .Double: case .Double:
var value = field.GetData<double>(); var value = field.GetData<double>();
if (ImGui.DragScalar(name.CStr(), .Double, &value)) if (ImGui.DragScalar(fieldName.CStr(), .Double, &value))
field.SetData(value); field.SetData(value);
case .Double2: case .Double2:
var value = field.GetData<double2>(); var value = field.GetData<double2>();
if (ImGui.DragScalarN(name.CStr(), .Double, &value, 2)) if (ImGui.DragScalarN(fieldName.CStr(), .Double, &value, 2))
field.SetData(value); field.SetData(value);
case .Double3: case .Double3:
var value = field.GetData<double3>(); var value = field.GetData<double3>();
if (ImGui.DragScalarN(name.CStr(), .Double, &value, 3)) if (ImGui.DragScalarN(fieldName.CStr(), .Double, &value, 3))
field.SetData(value); field.SetData(value);
case .Double4: case .Double4:
var value = field.GetData<double4>(); var value = field.GetData<double4>();
if (ImGui.DragScalarN(name.CStr(), .Double, &value, 4)) if (ImGui.DragScalarN(fieldName.CStr(), .Double, &value, 4))
field.SetData(value); field.SetData(value);
case .Enum: case .Enum:
// TODO! ShowEnumSelector(field, fieldName, scriptClass);
//case .String: //case .String:
// TODO! // TODO!
case .Entity: case .Entity:
// TODO! ShowEntityReceiver(field, fieldName, scriptClass);
case .Component:
ShowComponentReceiver(field, fieldName, scriptClass);
case .Struct: case .Struct:
// TODO! // TODO!
case .Class:
// We don't support editing classes
default: default:
Log.EngineLogger.Error($"Unhandled field type {field.Type}"); Log.EngineLogger.Error($"Unhandled field type {field.Type}");
} }
@@ -709,6 +810,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) private static void LabelColumn(StringView label)
{ {
ImGui.TextUnformatted(label); ImGui.TextUnformatted(label);
@@ -773,7 +1069,7 @@ namespace GlitchyEditor.EditWindows
if (ImGui.BeginDragDropTarget()) if (ImGui.BeginDragDropTarget())
{ {
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM"); ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.ContentBrowserItem);
if (payload != null) if (payload != null)
{ {
@@ -1,6 +1,7 @@
using ImGui; using ImGui;
using System; using System;
using System.IO; using System.IO;
using System.Linq;
using GlitchyEngine.Collections; using GlitchyEngine.Collections;
using System.Collections; using System.Collections;
using GlitchyEngine.Renderer; using GlitchyEngine.Renderer;
@@ -12,8 +13,35 @@ namespace GlitchyEditor.EditWindows
{ {
using internal GlitchyEditor.EditorContentManager; using internal GlitchyEditor.EditorContentManager;
class AssetCreator
{
private String _name ~ delete _;
private String _defaultFileName ~ delete _;
private CreateAssetFunc _doCreateAsset ~ delete _;
public delegate void CreateAssetFunc(StringView outputPath);
public StringView Name => _name;
public StringView DefaultFileName => _defaultFileName;
public CreateAssetFunc CreateAsset => _doCreateAsset;
public this(StringView name, StringView defaultFileName, CreateAssetFunc createAsset)
{
_name = new String(name);
_defaultFileName = new String(defaultFileName);
_doCreateAsset = createAsset;
}
}
class ContentBrowserWindow : EditorWindow class ContentBrowserWindow : EditorWindow
{ {
private append List<AssetCreator> _assetCreators = .() ~ ClearAndDeleteItems!(_);
private typealias AssetCreatorTree = TreeNode<(StringView Name, AssetCreator Creator)>;
private AssetCreatorTree _creatorTree = new AssetCreatorTree(("Create new Asset", null)) ~ delete _;
public const String s_WindowTitle = "Content Browser"; public const String s_WindowTitle = "Content Browser";
private append String _currentDirectory = .(); private append String _currentDirectory = .();
@@ -32,6 +60,28 @@ namespace GlitchyEditor.EditWindows
_manager = contentManager; _manager = contentManager;
} }
public void RegisterAssetCreator(AssetCreator assetCreator)
{
_assetCreators.Add(assetCreator);
AssetCreatorTree tree = _creatorTree;
for (StringView entryName in assetCreator.Name.Split('/'))
{
AssetCreatorTree nextNode = tree.Children.Where(scope (node) => node->Name == entryName).FirstOrDefault();
// Create new node if we didn't find it
nextNode ??= tree.AddChild((entryName, null));
tree = nextNode;
}
if (tree->Creator == null)
{
tree->Creator = assetCreator;
}
}
protected override void InternalShow() protected override void InternalShow()
{ {
_manager.Update(); _manager.Update();
@@ -39,7 +89,7 @@ namespace GlitchyEditor.EditWindows
// Make sure we are in an existing directory. // Make sure we are in an existing directory.
if (!_manager.AssetHierarchy.FileExists(_currentDirectory)) if (!_manager.AssetHierarchy.FileExists(_currentDirectory))
{ {
_currentDirectory.Set(_manager.ContentDirectory); _currentDirectory.Set(_manager.AssetDirectory);
} }
if(!ImGui.Begin(s_WindowTitle, &_open, .None)) if(!ImGui.Begin(s_WindowTitle, &_open, .None))
@@ -120,12 +170,69 @@ namespace GlitchyEditor.EditWindows
if (Path.OpenFolder(_currentDirectory) case .Err) if (Path.OpenFolder(_currentDirectory) case .Err)
Log.EngineLogger.Error("Failed to open directory in file browser."); Log.EngineLogger.Error("Failed to open directory in file browser.");
} }
ImGui.Separator();
ShowCreateContextMenu(_creatorTree);
}
/// Shows the menu for the given asset creator tree.
private void ShowCreateContextMenu(AssetCreatorTree subtree)
{
if (subtree.Children.Count == 0)
{
if (ImGui.MenuItem(subtree->Name.ToScopeCStr!()))
{
CreateAsset(subtree->Creator);
}
}
else
{
if (ImGui.BeginMenu(subtree->Name.ToScopeCStr!()))
{
for (let node in subtree.Children)
{
ShowCreateContextMenu(node);
}
ImGui.EndMenu();
}
}
}
/// Creates a new asset with the given creator
private void CreateAsset(AssetCreator creator)
{
if (!Directory.Exists(_currentDirectory))
{
Log.EngineLogger.Error($"Directory {_currentDirectory} doesn't exist.");
return;
}
String currentFile = scope String();
Path.Combine(currentFile, _currentDirectory, creator.DefaultFileName);
String fileExtension = scope String();
Path.GetExtension(currentFile, fileExtension);
StringView fileWithoutExtension = currentFile[0...^(fileExtension.Length + 1)];
int i = 0;
while (File.Exists(currentFile))
{
i++;
currentFile.Set(fileWithoutExtension);
currentFile.AppendF($"({i})");
currentFile.Append(fileExtension);
}
creator.CreateAsset(currentFile);
} }
/// Renders a sidebar that shows a tree of all directories in the asset folder. /// Renders a sidebar that shows a tree of all directories in the asset folder.
private void DrawDirectorySideBar() private void DrawDirectorySideBar()
{ {
for(var child in _manager.AssetHierarchy.[Friend]_assetHierarchy.Children) for(var child in _manager.AssetHierarchy.RootNode.Children)
{ {
ImGuiPrintEntityTree(child); ImGuiPrintEntityTree(child);
} }
@@ -142,17 +249,22 @@ namespace GlitchyEditor.EditWindows
ImGui.TreeNodeFlags flags = .OpenOnArrow | .SpanAvailWidth; ImGui.TreeNodeFlags flags = .OpenOnArrow | .SpanAvailWidth;
if(tree.Children.Count == 0) if(tree.Children.Where(scope (node) => node->IsDirectory).Count() == 0)
flags |= .Leaf; flags |= .Leaf;
if (tree->Path == _currentDirectory) if (tree->Path == _currentDirectory)
{
flags |= .Selected; flags |= .Selected;
}
// TODO: this kinda works, but the user should be able to close the directory
/*if (_manager.AssetHierarchy.GetNodeFromPath(_currentDirectory) case .Ok(let currentTreeNode))
{
if (currentTreeNode.IsInSubtree(tree))
ImGui.SetNextItemOpen(true);
}*/
bool isOpen = ImGui.TreeNodeEx(name, flags, $"{name}"); bool isOpen = ImGui.TreeNodeEx(name, flags, $"{name}");
if (ImGui.IsItemClicked(.Left)) if (!ImGui.IsItemToggledOpen() && ImGui.IsItemClicked(.Left))
{ {
_currentDirectory.Set(tree->Path); _currentDirectory.Set(tree->Path);
} }
@@ -186,7 +298,7 @@ namespace GlitchyEditor.EditWindows
if (_searchEverywhere && searchFilter.Length > 0) if (_searchEverywhere && searchFilter.Length > 0)
{ {
files = scope:: List<TreeNode<AssetNode>>(); files = scope:: List<TreeNode<AssetNode>>();
_manager.AssetHierarchy.[Friend]_assetHierarchy.ForEach(scope (node) => _manager.AssetHierarchy.[Friend]_assetRootNode.ForEach(scope (node) =>
{ {
if (node->Name.Contains(searchFilter, true)) if (node->Name.Contains(searchFilter, true))
{ {
@@ -253,10 +365,23 @@ namespace GlitchyEditor.EditWindows
} }
} }
float _zoom = 1.0f;
static readonly float2 IconBaseSize = .(100, 100);
float2 IconSize => IconBaseSize * _zoom;
/// Renders the button for the given directory item. /// Renders the button for the given directory item.
private void DrawBackButton(TreeNode<AssetNode> entry) private void DrawBackButton(TreeNode<AssetNode> entry)
{ {
ImGui.BeginChild("item", (.)DirectoryItemSize); ImGui.PushStyleVar(.WindowPadding, .(0, 0));
ImGui.PushStyleVar(.FramePadding, .(0, 0));
ImGui.PushStyleVar(.ItemSpacing, .(0, 0));
defer {ImGui.PopStyleVar(3); }
float2 DirectoryItemSize = IconSize + (float2)ImGui.GetStyle().WindowPadding * 2 + float2(0, ImGui.GetFontSize());
ImGui.BeginChild("item", (.)DirectoryItemSize, false, .NoScrollbar);
if (entry->Path == _selectedFile) if (entry->Path == _selectedFile)
{ {
@@ -270,7 +395,7 @@ namespace GlitchyEditor.EditWindows
SubTexture2D image = s_FolderTexture; SubTexture2D image = s_FolderTexture;
ImGui.ImageButton(image, (.)(DirectoryItemSize - padding)); ImGui.ImageButton("BackFolder", image, (.)IconSize);
ImGui.PopStyleColor(); ImGui.PopStyleColor();
@@ -295,7 +420,15 @@ namespace GlitchyEditor.EditWindows
/// Renders the button for the given directory item. /// Renders the button for the given directory item.
private void DrawDirectoryItem(TreeNode<AssetNode> entry) private void DrawDirectoryItem(TreeNode<AssetNode> entry)
{ {
ImGui.BeginChild("item", (.)DirectoryItemSize); ImGui.PushStyleVar(.WindowPadding, .(0, 0));
ImGui.PushStyleVar(.FramePadding, .(0, 0));
ImGui.PushStyleVar(.ItemSpacing, .(0, 0));
defer {ImGui.PopStyleVar(3); }
float2 DirectoryItemSize = IconSize + (float2)ImGui.GetStyle().WindowPadding * 2 + float2(0, ImGui.GetFontSize());
ImGui.BeginChild("item", (.)DirectoryItemSize, false, .NoScrollbar);
if (entry->Path == _selectedFile) if (entry->Path == _selectedFile)
{ {
@@ -310,21 +443,13 @@ namespace GlitchyEditor.EditWindows
// TODO: preview images // TODO: preview images
SubTexture2D image = entry->IsDirectory ? s_FolderTexture : s_FileTexture; SubTexture2D image = entry->IsDirectory ? s_FolderTexture : s_FileTexture;
ImGui.ImageButton(image, (.)(DirectoryItemSize - padding)); ImGui.ImageButton("FileImage", image, (.)IconSize);
ImGui.PopStyleColor(); ImGui.PopStyleColor();
if (ImGui.BeginDragDropSource()) if (ImGui.BeginDragDropSource())
{ {
String fullpath = scope String(entry->Path); ImGui.SetDragDropPayload(.ContentBrowserItem, entry->Identifier, (uint64)entry->Identifier.Length, .Once);
// TODO: this is dirty
if (fullpath.StartsWith(_manager.ContentDirectory, .OrdinalIgnoreCase))
fullpath.Remove(0, _manager.ContentDirectory.Length);
Path.Fixup(fullpath);
ImGui.SetDragDropPayload("CONTENT_BROWSER_ITEM", fullpath.CStr(), (.)fullpath.Length, .Once);
ImGui.EndDragDropSource(); ImGui.EndDragDropSource();
} }
@@ -350,6 +475,7 @@ namespace GlitchyEditor.EditWindows
ImGui.EndPopup(); ImGui.EndPopup();
} }
// TODO: Sub assets are probably borked now... I don't know if they ever worked, didn't test them
if (entry->SubAssets?.Count > 0) if (entry->SubAssets?.Count > 0)
{ {
// Button for revealing sub assets (e.g. Meshes in 3D-Model) // Button for revealing sub assets (e.g. Meshes in 3D-Model)
@@ -370,7 +496,7 @@ namespace GlitchyEditor.EditWindows
String fullpath = scope String(entry->Path); String fullpath = scope String(entry->Path);
fullpath.AppendF($"#{subAsset.Name}"); fullpath.AppendF($"#{subAsset.Name}");
ImGui.SetDragDropPayload("CONTENT_BROWSER_ITEM", fullpath.CStr(), (.)fullpath.Length, .Once); ImGui.SetDragDropPayload(.ContentBrowserItem, fullpath.CStr(), (.)fullpath.Length, .Once);
ImGui.EndDragDropSource(); ImGui.EndDragDropSource();
} }
@@ -382,6 +508,8 @@ namespace GlitchyEditor.EditWindows
DeleteItemPopup(entry); DeleteItemPopup(entry);
ImGui.EndChild(); ImGui.EndChild();
ImGui.AttachTooltip(entry->Name);
} }
private void DeleteItemPopup(TreeNode<AssetNode> fileOrFolder) private void DeleteItemPopup(TreeNode<AssetNode> fileOrFolder)
@@ -137,7 +137,7 @@ namespace GlitchyEditor.EditWindows
{ {
if (ImGui.BeginDragDropTarget()) if (ImGui.BeginDragDropTarget())
{ {
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM"); ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.ContentBrowserItem);
if (payload != null) if (payload != null)
{ {
@@ -21,8 +21,26 @@ namespace GlitchyEditor.EditWindows
private List<Entity> _selectedEntities = new .() ~ delete _; private List<Entity> _selectedEntities = new .() ~ delete _;
private Entity _entityToHighlight;
public List<Entity> SelectedEntities => _selectedEntities; 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) public this(Editor editor, Scene scene)
{ {
_editor = editor; _editor = editor;
@@ -322,8 +340,21 @@ namespace GlitchyEditor.EditWindows
if(inSelectedList) if(inSelectedList)
flags |= .Selected; 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}"); 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); ImGui.PushID((void*)(uint)tree.Value.Handle.[Friend]Index);
bool deleted = false; bool deleted = false;
@@ -341,9 +372,13 @@ namespace GlitchyEditor.EditWindows
if (deleted) if (deleted)
return; return;
bool isDragged = false;
if(ImGui.BeginDragDropSource()) if(ImGui.BeginDragDropSource())
{ {
ImGui.SetDragDropPayload("DND_Entity", &tree.Value, sizeof(Entity)); isDragged = true;
ImGui.SetDragDropPayload(.Entity, &tree.Value, sizeof(Entity));
ImGui.Text(name); ImGui.Text(name);
@@ -352,7 +387,7 @@ namespace GlitchyEditor.EditWindows
if(ImGui.BeginDragDropTarget()) if(ImGui.BeginDragDropTarget())
{ {
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("DND_Entity"); ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.Entity);
if(payload != null) if(payload != null)
{ {
@@ -407,6 +442,12 @@ namespace GlitchyEditor.EditWindows
} }
if (clicked || clickedRight) 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) if (inSelectedList && !clickedRight)
{ {
@@ -418,13 +459,23 @@ namespace GlitchyEditor.EditWindows
SelectEntity(tree.Value, !ImGui.GetIO().KeyCtrl && !clickedRight); SelectEntity(tree.Value, !ImGui.GetIO().KeyCtrl && !clickedRight);
inSelectedList = true; inSelectedList = true;
} }
lastClickedEntity = .();
} }
} }
private static Entity lastClickedEntity;
private void ShowEntityHierarchy() private void ShowEntityHierarchy()
{ {
StringView searchString = StringView(&_entitySearchChars); StringView searchString = StringView(&_entitySearchChars);
if (_scene == null)
{
ImGui.TextUnformatted("<No scene open>");
return;
}
if(searchString.IsWhiteSpace) if(searchString.IsWhiteSpace)
{ {
// Show entity hierarchy as tree // Show entity hierarchy as tree
@@ -464,7 +515,7 @@ namespace GlitchyEditor.EditWindows
{ {
if(ImGui.BeginDragDropTarget()) if(ImGui.BeginDragDropTarget())
{ {
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("DND_Entity"); ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.Entity);
if(payload != null) if(payload != null)
{ {
@@ -527,6 +578,10 @@ namespace GlitchyEditor.EditWindows
ImGuiPrintEntityTree(scope .(entity)); 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()) if (ImGui.BeginDragDropTarget())
{ {
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM"); ImGui.Payload* payload = ImGui.AcceptDragDropPayload(.ContentBrowserItem);
if (payload != null) if (payload != null)
{ {
+375
View File
@@ -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);
}
}
+16
View File
@@ -22,6 +22,7 @@ namespace GlitchyEditor
private ContentBrowserWindow _contentBrowserWindow ~ delete _; private ContentBrowserWindow _contentBrowserWindow ~ delete _;
private PropertiesWindow _propertiesWindow ~ delete _; private PropertiesWindow _propertiesWindow ~ delete _;
private AssetViewer _assetViewer ~ delete _; private AssetViewer _assetViewer ~ delete _;
private LogWindow _logWindow ~ delete _;
public Scene CurrentScene public Scene CurrentScene
{ {
@@ -45,6 +46,7 @@ namespace GlitchyEditor
public ContentBrowserWindow ContentBrowserWindow => _contentBrowserWindow; public ContentBrowserWindow ContentBrowserWindow => _contentBrowserWindow;
public PropertiesWindow PropertiesWindow => _propertiesWindow; public PropertiesWindow PropertiesWindow => _propertiesWindow;
public AssetViewer AssetViewer => _assetViewer; public AssetViewer AssetViewer => _assetViewer;
public LogWindow LogWindow => _logWindow;
public EditorCamera* CurrentCamera { get; set; } public EditorCamera* CurrentCamera { get; set; }
@@ -53,15 +55,27 @@ namespace GlitchyEditor
public SceneRenderer GameSceneRenderer {get; set;} public SceneRenderer GameSceneRenderer {get; set;}
public SceneRenderer EditorSceneRenderer {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 /// Creates a new editor for the given world
public this(Scene scene, EditorContentManager contentManager) 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; _scene = scene;
_contentManager = contentManager; _contentManager = contentManager;
InitWindows(); InitWindows();
} }
public ~this()
{
s_Instance = null;
}
private void InitWindows() private void InitWindows()
{ {
_sceneViewportWindow = new EditorViewportWindow(this); _sceneViewportWindow = new EditorViewportWindow(this);
@@ -71,6 +85,7 @@ namespace GlitchyEditor
_contentBrowserWindow = new ContentBrowserWindow((.)Application.Get().ContentManager); _contentBrowserWindow = new ContentBrowserWindow((.)Application.Get().ContentManager);
_propertiesWindow = new PropertiesWindow(this); _propertiesWindow = new PropertiesWindow(this);
_assetViewer = new AssetViewer((.)Application.Get().ContentManager); _assetViewer = new AssetViewer((.)Application.Get().ContentManager);
_logWindow = new LogWindow();
} }
public void Update() public void Update()
@@ -82,6 +97,7 @@ namespace GlitchyEditor
_contentBrowserWindow.Show(); _contentBrowserWindow.Show();
_propertiesWindow.Show(); _propertiesWindow.Show();
_assetViewer.Show(); _assetViewer.Show();
_logWindow.Show();
} }
} }
} }
+4 -1
View File
@@ -12,6 +12,9 @@ namespace GlitchyEditor
public this(String[] args) public this(String[] args)
{ {
PushLayer(new EditorLayer(args, _contentManager)); PushLayer(new EditorLayer(args, _contentManager));
Log.ClientLogger = new EditorLogger();
Log.EngineLogger = new EditorLogger() { IsEngineLogger = true };
} }
protected override IContentManager InitContentManager() protected override IContentManager InitContentManager()
@@ -33,7 +36,7 @@ namespace GlitchyEditor
_contentManager.SetAsDefaultAssetLoader<EffectAssetLoader>(".hlsl"); _contentManager.SetAsDefaultAssetLoader<EffectAssetLoader>(".hlsl");
_contentManager.SetAssetPropertiesEditor<EffectAssetLoader>(=> EffectAssetPropertiesEditor.Factory); _contentManager.SetAssetPropertiesEditor<EffectAssetLoader>(=> EffectAssetPropertiesEditor.Factory);
_contentManager.SetContentDirectory("./content"); _contentManager.SetResourcesDirectory("./Resources");
return _contentManager; return _contentManager;
} }
+44 -47
View File
@@ -15,11 +15,11 @@ namespace GlitchyEditor;
class EditorContentManager : IContentManager class EditorContentManager : IContentManager
{ {
private append String _contentDirectory = .(); private append String _resourcesDirectory = .();
private append String _assetsDirectory = .();
public StringView ContentDirectory => _contentDirectory; public StringView ResourcesDirectory => _resourcesDirectory;
public StringView AssetDirectory => _assetsDirectory;
//private append List<String> _identifiers = .() ~ _.ClearAndDeleteItems();
private append Dictionary<StringView, AssetHandle> _identiferToHandle = .(); // TODO: Check if all resources are unloaded private append Dictionary<StringView, AssetHandle> _identiferToHandle = .(); // TODO: Check if all resources are unloaded
@@ -64,13 +64,20 @@ class EditorContentManager : IContentManager
_identiferToHandle.Add(asset.Identifier, asset.Handle); _identiferToHandle.Add(asset.Identifier, asset.Handle);
} }
public void SetContentDirectory(StringView contentDirectory) public void SetResourcesDirectory(StringView fileName)
{ {
_contentDirectory.Clear(); _resourcesDirectory.Set(fileName);
_contentDirectory.Append(contentDirectory); Path.Fixup(_resourcesDirectory);
Path.Fixup(_contentDirectory);
_assetHierarchy.SetContentDirectory(contentDirectory); _assetHierarchy.SetResourcesDirectory(_resourcesDirectory);
}
public void SetAssetDirectory(StringView fileName)
{
_assetsDirectory.Set(fileName);
Path.Fixup(_assetsDirectory);
_assetHierarchy.SetAssetsDirectory(_assetsDirectory);
} }
public void Update() public void Update()
@@ -302,7 +309,7 @@ class EditorContentManager : IContentManager
private void GetResourceFilePath(StringView resourceName, String filePath) private void GetResourceFilePath(StringView resourceName, String filePath)
{ {
Path.Combine(filePath, _contentDirectory, resourceName); Path.Combine(filePath, _assetsDirectory, resourceName);
Path.Fixup(filePath); Path.Fixup(filePath);
} }
@@ -337,7 +344,10 @@ class EditorContentManager : IContentManager
{ {
Debug.Profiler.ProfileResourceFunction!(); Debug.Profiler.ProfileResourceFunction!();
// Todo: How strict should we be on paths? // It's valid to request no entity, but no entity is obviously invalid.
if (identifier.IsWhiteSpace)
return .Invalid;
String fixedIdentifier = scope String(identifier); String fixedIdentifier = scope String(identifier);
AssetIdentifier.Fixup(fixedIdentifier); AssetIdentifier.Fixup(fixedIdentifier);
@@ -346,30 +356,34 @@ class EditorContentManager : IContentManager
GetResourceAndSubassetName(fixedIdentifier, let resourceName, let subassetName); GetResourceAndSubassetName(fixedIdentifier, let resourceName, let subassetName);
String filePath = scope .(); Result<TreeNode<AssetNode>> resultNode = AssetHierarchy.GetNodeFromIdentifier(fixedIdentifier);
GetResourceFilePath(resourceName, filePath);
Result<TreeNode<AssetNode>> resultNode = AssetHierarchy.GetNodeFromPath(filePath);
if (resultNode case .Err) if (resultNode case .Err)
{ {
Log.EngineLogger.Error($"Could not find asset \"{filePath}\"."); Log.EngineLogger.Error($"Could not find asset \"{fixedIdentifier}\".");
return .Invalid; return .Invalid;
} }
String filePath = scope String(resultNode->Value.Path);
AssetFile file = resultNode->Value.AssetFile; AssetFile file = resultNode->Value.AssetFile;
IAssetLoader assetLoader = GetAssetLoader(file); IAssetLoader assetLoader = GetAssetLoader(file);
// TODO: what are we supposed to do if we don't find a loader? Sure not crash... // TODO: what are we supposed to do if we don't find a loader? Surely not crash...
Log.EngineLogger.AssertDebug(assetLoader != null); //Log.EngineLogger.AssertDebug(assetLoader != null);
if (assetLoader == null)
{
Log.EngineLogger.Error($"No asset loader registered for asset {identifier}.");
return .Invalid;
}
Asset loadedAsset; Asset loadedAsset;
// TODO: Support lazy loading for all asset types // TODO: Support lazy loading for all asset types
if (!(assetLoader is EditorTextureAssetLoader) || blocking) if (!(assetLoader is EditorTextureAssetLoader) || blocking)
{ {
Stream stream = GetStream(filePath); Stream stream = OpenStream(filePath, true);
loadedAsset = assetLoader.LoadAsset(stream, file.AssetConfig.Config, resourceName, subassetName, this); loadedAsset = assetLoader.LoadAsset(stream, file.AssetConfig.Config, resourceName, subassetName, this);
@@ -413,7 +427,7 @@ class EditorContentManager : IContentManager
{ {
Debug.Profiler.ProfileResourceFunction!(); Debug.Profiler.ProfileResourceFunction!();
Stream stream = GetStream(filePath); Stream stream = OpenStream(filePath, true);
Asset loadedAsset = assetLoader.LoadAsset(stream, file.AssetConfig.Config, resourceName, subassetName, this); Asset loadedAsset = assetLoader.LoadAsset(stream, file.AssetConfig.Config, resourceName, subassetName, this);
@@ -506,23 +520,13 @@ class EditorContentManager : IContentManager
return .Ok; return .Ok;
} }
private Stream OpenStream(StringView assetIdentifier, bool openOnly) private Stream OpenStream(StringView fileName, bool openOnly)
{ {
var assetIdentifier;
if (!assetIdentifier.StartsWith(_contentDirectory))
{
String filePath = scope:: String(assetIdentifier.Length + _contentDirectory.Length + 2);
Path.Combine(filePath, _contentDirectory, assetIdentifier);
assetIdentifier = filePath;
}
FileStream fs = new FileStream(); FileStream fs = new FileStream();
FileMode fileMode = openOnly ? FileMode.Open : FileMode.OpenOrCreate; FileMode fileMode = openOnly ? FileMode.Open : FileMode.OpenOrCreate;
var result = fs.Open(assetIdentifier, fileMode, openOnly ? .Read : .ReadWrite, .ReadWrite); var result = fs.Open(fileName, fileMode, openOnly ? .Read : .ReadWrite, .ReadWrite);
if (result case .Err) if (result case .Err)
return null; return null;
@@ -530,28 +534,21 @@ class EditorContentManager : IContentManager
return fs; return fs;
} }
// TODO: probably not needed /// Returns a file stream for the given assetIdentifier
public Stream GetStream(StringView assetIdentifier) public Stream GetStream(StringView assetIdentifier)
{ {
return OpenStream(assetIdentifier, true); String fixuppedIdentifier = scope .(assetIdentifier);
AssetIdentifier.Fixup(fixuppedIdentifier);
/*var assetIdentifier; var node = _assetHierarchy.GetNodeFromIdentifier(fixuppedIdentifier);
if (!assetIdentifier.StartsWith(_contentDirectory)) if (node case .Err)
{ {
String filePath = scope:: String(assetIdentifier.Length + _contentDirectory.Length + 2); Log.EngineLogger.Error($"Could not find asset node \"{assetIdentifier}\".");
Path.Combine(filePath, _contentDirectory, assetIdentifier); return null;
assetIdentifier = filePath;
} }
FileStream fs = new FileStream(); return OpenStream(node->Value.Path, true);
var result = fs.Open(assetIdentifier, .Open, .Read, .ReadWrite);
if (result case .Err)
return null;
return fs;*/
} }
public AssetHandle ManageAsset(Asset asset) public AssetHandle ManageAsset(Asset asset)
+8
View File
@@ -19,6 +19,10 @@ namespace GlitchyEditor
public SubTexture2D Simulate ~ _.ReleaseRef(); public SubTexture2D Simulate ~ _.ReleaseRef();
public SubTexture2D Pause ~ _.ReleaseRef(); public SubTexture2D Pause ~ _.ReleaseRef();
public SubTexture2D SingleStep ~ _.ReleaseRef(); public SubTexture2D SingleStep ~ _.ReleaseRef();
public SubTexture2D Error ~ _.ReleaseRef();
public SubTexture2D Warning ~ _.ReleaseRef();
public SubTexture2D Info ~ _.ReleaseRef();
public SubTexture2D Trace ~ _.ReleaseRef();
public SamplerState SamplerState public SamplerState SamplerState
{ {
@@ -41,6 +45,10 @@ namespace GlitchyEditor
Simulate = GetNextGridTexture(ref pen, iconSize); Simulate = GetNextGridTexture(ref pen, iconSize);
Pause = GetNextGridTexture(ref pen, iconSize); Pause = GetNextGridTexture(ref pen, iconSize);
SingleStep = 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) private SubTexture2D GetNextGridTexture(ref float2 pen, float2 iconSize)
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More