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
106 changed files with 2177 additions and 633 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,
@@ -309,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"
} }
}, },
{ {
@@ -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,8 +7,8 @@
<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>
@@ -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"}
@@ -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
+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,13 +449,46 @@ 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);
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); String directoryNameBuffer = scope String(256);
for (var directory in Directory.Enumerate(filter, .Directories)) for (var directory in Directory.Enumerate(filter, .Directories))
@@ -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);
+9 -63
View File
@@ -31,58 +31,7 @@ class AssetViewer : EditorWindow
ImGui.PushStyleVar(.CellPadding, .(0, 0)); ImGui.PushStyleVar(.CellPadding, .(0, 0));
ImGui.Columns(2); bool alt_pressed = ImGui.GetIO().KeyAlt;
if (ImGui.BeginChild("Assets"))
{
DrawAssetList();
ImGui.EndChild();
}
ImGui.NextColumn();
if (ImGui.BeginChild("Files"))
{
DrawAssetViewer();
ImGui.EndChild();
}
ImGui.Columns(1);
/*if (ImGui.BeginTable("AssetViewerTable", 2, .BordersInnerV | .Resizable | .Reorderable | .NoPadOuterX))
{
if (alt_pressed)
{
// Header anzeigen, damit sie neu angeordnet werden können
ImGui.TableSetupColumn("Assets");
ImGui.TableSetupColumn("Viewer");
ImGui.TableHeadersRow();
}
ImGui.TableNextRow();
ImGui.TableSetColumnIndex(0);
if (ImGui.BeginChild("Assets"))
{
//DrawAssetList();
ImGui.EndChild();
}
ImGui.TableNextColumn();
if (ImGui.BeginChild("Files"))
{
//DrawAssetViewer();
ImGui.EndChild();
}
ImGui.EndTable();
}*/
/*bool alt_pressed = ImGui.GetIO().KeyAlt;
if (ImGui.BeginTable("AssetViewerTable", 2, .BordersInnerV | .Resizable | .Reorderable | .NoPadOuterX)) if (ImGui.BeginTable("AssetViewerTable", 2, .BordersInnerV | .Resizable | .Reorderable | .NoPadOuterX))
{ {
@@ -93,27 +42,24 @@ class AssetViewer : EditorWindow
ImGui.TableSetupColumn("Viewer"); ImGui.TableSetupColumn("Viewer");
ImGui.TableHeadersRow(); ImGui.TableHeadersRow();
} }
ImGui.TableNextRow(); ImGui.TableNextRow();
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();
}*/ }
ImGui.PopStyleVar(1); ImGui.PopStyleVar(1);
@@ -229,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;
@@ -112,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();
} }
@@ -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("FileImage", 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(.ContentBrowserItem, 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)
@@ -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)
@@ -470,6 +470,12 @@ namespace GlitchyEditor.EditWindows
{ {
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
+1 -1
View File
@@ -36,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)
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -111,7 +111,7 @@ public class EditorLogger : Logger
String message = scope String(4096); String message = scope String(4096);
message.AppendF(format, params args); message.AppendF(format, params args);
Debug.Write($"[{timestamp:HH:mm:ss.fff}] ({_name})|{level.UpperString}: {message}"); Debug.Write($"[{timestamp:HH:mm:ss.fff}] ({_name})|{level.UpperString}: {message}\n");
if (Editor.Instance == null) if (Editor.Instance == null)
return; return;
+154
View File
@@ -0,0 +1,154 @@
using System;
using System.IO;
using Bon;
using GlitchyEngine;
namespace GlitchyEditor;
[BonTarget]
class Project
{
[BonInclude]
private String _projectName ~ delete _;
[BonIgnore]
private String _workspacePath ~ delete _;
[BonIgnore]
private String _assetsFolder ~ delete _;
[BonIgnore]
private String _scriptFolder ~ delete _;
[BonIgnore]
private ProjectUserSettings _userSettings ~ delete _;
public StringView Name => _projectName;
public StringView WorkspacePath => _workspacePath;
public StringView AssetsFolder => _assetsFolder;
public ProjectUserSettings UserSettings => _userSettings;
[AllowAppend]
private this(StringView workspacePath)
{
_workspacePath = new String(workspacePath);
_assetsFolder = new String();
PathInProject(_assetsFolder, "Assets");
InitUserSettings();
}
/// Writes the the absolute path of the give project-file into target.
/// @param target The string that will contain the full path.
/// @param relativePath The path of the file relative to the workspace folder.
public void PathInProject(String target, StringView relativePath)
{
Path.Combine(target, WorkspacePath, relativePath);
}
/// Creates a new scoped string that contains the absolute path of the give project-file
/// @param relativePath The path of the file relative to the workspace folder.
public mixin GetScopedPath(StringView relativePath)
{
String target = scope:mixin String();
PathInProject(target, relativePath);
target
}
/// Loads or creates the user specific settings for this project.
private void InitUserSettings()
{
_userSettings = new ProjectUserSettings();
String userSettingsFile = scope .();
PathInProject(userSettingsFile, ProjectUserSettings.FileName);
// It's not a problem if we couldn't find or deserialize the settings. We will simply restore the defaults.
if (Bon.DeserializeFromFile(ref _userSettings, userSettingsFile) case .Err)
{
// Log anyway, just in case...
Log.EngineLogger.Info($"Failed to deserialize project user settings file \"{userSettingsFile}\".");
_userSettings.RestoreDefaults();
}
}
public void SaveUserSettings()
{
if (_userSettings == null || !_userSettings.SettignsDirty)
return;
String userSettingsFile = scope .();
PathInProject(userSettingsFile, ProjectUserSettings.FileName);
// It's not a big problem, if we fail to serialize this file.
if (Bon.SerializeIntoFile(_userSettings, userSettingsFile) case .Err)
{
// Log anyway, just in case...
Log.EngineLogger.Error($"Failed to deserialize project user settings file \"{userSettingsFile}\".");
}
}
/// Creates a new project with the given directory and name.
public static Project CreateNew(StringView projectDirectory, StringView projectName)
{
Project project = new Project(projectDirectory);
project._projectName = new String(projectName);
String settingsFile = scope .();
project.PathInProject(settingsFile, "project.gep");
/// This is not really fatal, however the project might end up unusable
if (Bon.SerializeIntoFile(project, settingsFile) case .Err)
{
Log.EngineLogger.Warning($"Failed to save project file \"{settingsFile}\".");
delete project;
return null;
}
return project;
}
public static Result<Project> Load(StringView projectDirectory)
{
Project project = new Project(projectDirectory);
String settingsFile = scope .();
project.PathInProject(settingsFile, "project.gep");
if (File.Exists(settingsFile))
{
Result<void> result = Bon.DeserializeFromFile(ref project, settingsFile);
if (result case .Err)
Log.EngineLogger.Warning($"Failed to deserialize project file \"{settingsFile}\".");
}
else
{
Log.EngineLogger.Warning($"Project file \"{settingsFile}\" doesn't exist.");
if (project.Name.IsWhiteSpace)
{
project._projectName ??= new String();
Path.GetFileName(project.WorkspacePath, project._projectName);
/// This is not really fatal, however the project might end up unusable
if (Bon.SerializeIntoFile(project, settingsFile) case .Err)
{
Log.EngineLogger.Warning($"Failed to save project file \"{settingsFile}\".");
delete project;
return null;
}
}
}
return project;
}
}
+79
View File
@@ -0,0 +1,79 @@
using Bon;
using System;
using System.Collections;
namespace GlitchyEditor;
/// The user settings of this project
[BonTarget]
class ProjectUserSettings
{
public static StringView FileName = "project_user.bon";
/*[BonInclude]
private String _lastOpenedScene ~ delete _;*/
[BonInclude]
private List<String> _recentScenes ~ DeleteContainerAndItems!(_);
[BonIgnore]
private bool _settingsDirty;
/// Gets or sets the path of the Scene that was last open. (Relative to the workspace)
public StringView LastOpenedScene
{
get
{
if (_recentScenes == null || _recentScenes.Count == 0)
return "";
return _recentScenes[0];
}
set
{
if (_recentScenes == null)
_recentScenes = new List<String>();
// Remove duplicates
for (var entry in _recentScenes)
{
if (entry == value)
{
delete entry;
@entry.Remove();
}
}
_recentScenes.Insert(0, new String(value));
if (_recentScenes.Count > 10)
{
// We only store 10 entries, delete the rest
for (int i = 10; i < _recentScenes.Count; i++)
{
delete _recentScenes[i];
}
_recentScenes.Count = 10;
}
}
}
/// The scenes that were recently used.
public List<String> RecentScenes => _recentScenes;
public bool SettignsDirty
{
get => _settingsDirty;
set => _settingsDirty = value;
}
public void RestoreDefaults()
{
//_lastOpenedScene?.Clear();
if (_recentScenes != null)
ClearAndDeleteItems!(_recentScenes);
_settingsDirty = true;
}
}
+37
View File
@@ -1,4 +1,5 @@
using System.Collections; using System.Collections;
using System;
namespace GlitchyEngine.Collections namespace GlitchyEngine.Collections
{ {
@@ -37,6 +38,11 @@ namespace GlitchyEngine.Collections
return newChild; return newChild;
} }
public bool RemoveChild(TreeNode<T> value)
{
return Children.Remove(value);
}
public Self FindNode(T value) public Self FindNode(T value)
{ {
if (Value == value) if (Value == value)
@@ -65,6 +71,34 @@ namespace GlitchyEngine.Collections
DepthFirst DepthFirst
} }
public bool IsParentOf(TreeNode<T> wantedChild)
{
return wantedChild.IsChildOf(this);
}
public bool IsChildOf(TreeNode<T> wantedParent)
{
TreeNode<T> currentParent = Parent;
while (currentParent != null)
{
if (currentParent == wantedParent)
return true;
currentParent = currentParent.Parent;
}
return false;
}
public bool IsInSubtree(TreeNode<T> subtree)
{
if (this == subtree)
return true;
return IsChildOf(subtree);
}
public void ForEach(ElementFunc func, IterationMode iterationMode = .DepthFirst) public void ForEach(ElementFunc func, IterationMode iterationMode = .DepthFirst)
{ {
if (iterationMode == .BreadthFirst) if (iterationMode == .BreadthFirst)
@@ -123,6 +157,9 @@ namespace GlitchyEngine.Collections
private static void InternalDeleteTreeAndChildren<T>(TreeNode<T> tree) where T : class, delete private static void InternalDeleteTreeAndChildren<T>(TreeNode<T> tree) where T : class, delete
{ {
if (tree == null)
return;
for (var child in tree.Children) for (var child in tree.Children)
{ {
InternalDeleteTreeAndChildren(child); InternalDeleteTreeAndChildren(child);
@@ -0,0 +1,62 @@
namespace System.IO;
extension Directory
{
[Import("Shlwapi.lib"), CLink, CallingConvention(.Stdcall)]
private static extern System.Windows.IntBool PathIsDirectoryEmptyW(char16* pszPath);
public static bool IsEmpty(StringView fileName)
{
// TODO: This is obviously windows only
return PathIsDirectoryEmptyW(fileName.ToScopedNativeWChar!());
}
public static Result<void, Platform.BfpFileResult> Copy(StringView fromPath, StringView toPath)
{
if (fromPath.Length <= 2)
return .Err(.InvalidParameter);
if ((fromPath[0] != '/') && (fromPath[0] != '\\'))
{
if (fromPath[1] == ':')
{
if (fromPath.Length < 3)
return .Err(.InvalidParameter);
}
}
if (!Directory.Exists(fromPath))
return .Err(.NotFound);
Try!(Directory.CreateDirectory(toPath));
for (var directoryEntry in Directory.EnumerateDirectories(fromPath))
{
let dirFromPath = scope String();
directoryEntry.GetFilePath(dirFromPath);
let dirName = scope String();
directoryEntry.GetFileName(dirName);
let dirToPath = scope String();
Path.Combine(dirToPath, toPath, dirName);
Try!(Copy(dirFromPath, dirToPath));
}
for (var fileEntry in Directory.EnumerateFiles(fromPath))
{
let fileFromPath = scope String();
fileEntry.GetFilePath(fileFromPath);
let fileName = scope String();
fileEntry.GetFileName(fileName);
let fileToPath = scope String();
Path.Combine(fileToPath, toPath, fileName);
Try!(File.Copy(fileFromPath, fileToPath));
}
return .Ok;
}
}
@@ -43,5 +43,7 @@ extension Path
target.Append(Path.DirectorySeparatorChar); target.Append(Path.DirectorySeparatorChar);
target.Append(component); target.Append(component);
} }
target.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
} }
} }
@@ -3,6 +3,7 @@
using GlitchyEngine.Math; using GlitchyEngine.Math;
using GlitchyEngine.Platform.DX11; using GlitchyEngine.Platform.DX11;
using System; using System;
using GlitchyEngine.Content;
using internal GlitchyEngine.Renderer; using internal GlitchyEngine.Renderer;
using internal GlitchyEngine.Platform.DX11; using internal GlitchyEngine.Platform.DX11;
@@ -15,7 +16,7 @@ namespace GlitchyEngine.Renderer
{ {
private GraphicsContext _context ~ _?.ReleaseRef(); private GraphicsContext _context ~ _?.ReleaseRef();
private Effect _clearUintFx ~ _?.ReleaseRef(); private AssetHandle<Effect> _clearUintFx;
private BlendState _nonblendingState ~ _?.ReleaseRef(); private BlendState _nonblendingState ~ _?.ReleaseRef();
public GraphicsContext Context public GraphicsContext Context
@@ -30,7 +31,7 @@ namespace GlitchyEngine.Renderer
{ {
Debug.Profiler.ProfileFunction!(); Debug.Profiler.ProfileFunction!();
_clearUintFx = new Effect("content/Shaders/ClearUInt.hlsl"); _clearUintFx = Content.LoadAsset("Resources/Shaders/ClearUInt.hlsl", null, true);
BlendStateDescription desc =.Default; BlendStateDescription desc =.Default;
desc.RenderTarget[0].BlendEnable = false; desc.RenderTarget[0].BlendEnable = false;
_nonblendingState = new BlendState(desc); _nonblendingState = new BlendState(desc);
@@ -57,11 +57,11 @@ namespace GlitchyEngine.Renderer
Path.Combine(pathNextToParent, includer._parentFileDirectory, StringView(fileName)); Path.Combine(pathNextToParent, includer._parentFileDirectory, StringView(fileName));
Stream fileStream = Application.Get().ContentManager.GetStream(pathNextToParent); Stream fileStream = Application.Instance.ContentManager.GetStream(pathNextToParent);
if (fileStream == null) if (fileStream == null)
{ {
fileStream = Application.Get().ContentManager.GetStream(StringView(fileName)); fileStream = Application.Instance.ContentManager.GetStream(StringView(fileName));
} }
if (fileStream == null) if (fileStream == null)
+2 -2
View File
@@ -176,8 +176,8 @@ namespace GlitchyEngine.Renderer
static void InitDeferredRenderer() static void InitDeferredRenderer()
{ {
TestFullscreenEffect = Content.LoadAsset("Shaders\\simpleLight.hlsl"); TestFullscreenEffect = Content.LoadAsset("Resources/Shaders/simpleLight.hlsl");
s_tonemappingEffect = Content.LoadAsset("Shaders\\SimpleTonemapping.hlsl"); s_tonemappingEffect = Content.LoadAsset("Resources/Shaders/SimpleTonemapping.hlsl");
_gBuffer = new GBuffer(); _gBuffer = new GBuffer();
BlendStateDescription gBufferBlendDesc = .Default; BlendStateDescription gBufferBlendDesc = .Default;
+35 -68
View File
@@ -4,6 +4,7 @@ using System;
using System.Diagnostics; using System.Diagnostics;
using GlitchyEngine.Renderer.Text; using GlitchyEngine.Renderer.Text;
using GlitchyEngine.World; using GlitchyEngine.World;
using GlitchyEngine.Content;
namespace GlitchyEngine.Renderer namespace GlitchyEngine.Renderer
{ {
@@ -130,9 +131,9 @@ namespace GlitchyEngine.Renderer
private static bool s_sceneRunning; private static bool s_sceneRunning;
#endif #endif
private static Effect s_quadBatchEffect; private static AssetHandle<Effect> s_quadBatchEffect;
private static Effect s_circleBatchEffect; private static AssetHandle<Effect> s_circleBatchEffect;
private static Effect s_lineBatchEffect; private static AssetHandle<Effect> s_lineBatchEffect;
private static GeometryBinding s_quadGeometry; private static GeometryBinding s_quadGeometry;
@@ -161,9 +162,9 @@ namespace GlitchyEngine.Renderer
private static DrawOrder s_drawOrder; private static DrawOrder s_drawOrder;
/// The effect that is currently used to draw the sprites. /// The effect that is currently used to draw the sprites.
private static Effect s_currentQuadEffect; private static AssetHandle<Effect> s_currentQuadEffect;
private static Effect s_currentCircleEffect; private static AssetHandle<Effect> s_currentCircleEffect;
private static Effect s_currentLineEffect; private static AssetHandle<Effect> s_currentLineEffect;
public static uint32 MaxInstancesPerBatch public static uint32 MaxInstancesPerBatch
{ {
@@ -183,9 +184,9 @@ namespace GlitchyEngine.Renderer
{ {
Debug.Profiler.ProfileFunction!(); Debug.Profiler.ProfileFunction!();
s_quadBatchEffect = new Effect("content\\Shaders\\spritebatch.hlsl"); s_quadBatchEffect = Content.LoadAsset("Resources/Shaders/spritebatch.hlsl", null, true);
s_circleBatchEffect = new Effect("content\\Shaders\\circlebatch.hlsl"); s_circleBatchEffect = Content.LoadAsset("Resources/Shaders/circlebatch.hlsl", null, true);
s_lineBatchEffect = new Effect("content\\Shaders\\linebatch.hlsl"); s_lineBatchEffect = Content.LoadAsset("Resources/Shaders/linebatch.hlsl", null, true);
} }
private static void InitGeometry() private static void InitGeometry()
@@ -427,10 +428,6 @@ namespace GlitchyEngine.Renderer
FontRenderer.Deinit(); FontRenderer.Deinit();
s_quadBatchEffect.ReleaseRef();
s_circleBatchEffect.ReleaseRef();
s_lineBatchEffect.ReleaseRef();
s_quadGeometry.ReleaseRef(); s_quadGeometry.ReleaseRef();
s_whiteTexture.ReleaseRef(); s_whiteTexture.ReleaseRef();
@@ -449,10 +446,6 @@ namespace GlitchyEngine.Renderer
delete s_circleInstanceQueue; delete s_circleInstanceQueue;
delete s_lineInstanceQueue; delete s_lineInstanceQueue;
s_currentQuadEffect?.ReleaseRef();
s_currentCircleEffect?.ReleaseRef();
s_currentLineEffect?.ReleaseRef();
s_opaqueBlendState.ReleaseRef(); s_opaqueBlendState.ReleaseRef();
s_transparentBlendState.ReleaseRef(); s_transparentBlendState.ReleaseRef();
@@ -462,7 +455,7 @@ namespace GlitchyEngine.Renderer
} }
// TODO: remove? // TODO: remove?
public static void BeginScene(OldCamera camera, DrawOrder drawOrder = .SortByTexture, Effect effect = null, Effect circleEffect = null) public static void BeginScene(OldCamera camera, DrawOrder drawOrder = .SortByTexture, AssetHandle<Effect> effect = .Invalid, AssetHandle<Effect> circleEffect = .Invalid)
{ {
Debug.Profiler.ProfileRendererFunction!(); Debug.Profiler.ProfileRendererFunction!();
#if DEBUG #if DEBUG
@@ -470,28 +463,26 @@ namespace GlitchyEngine.Renderer
Log.EngineLogger.AssertDebug(!s_sceneRunning, "You have to call EndScene before you can make another call to BeginScene."); Log.EngineLogger.AssertDebug(!s_sceneRunning, "You have to call EndScene before you can make another call to BeginScene.");
#endif #endif
//s_textureColorEffect.Bind(Renderer._context); if(effect != .Invalid)
s_currentQuadEffect?.ReleaseRef();
if(effect != null)
{ {
s_currentQuadEffect = effect..AddRef(); s_currentQuadEffect = effect;
} }
else else
{ {
s_currentQuadEffect = s_quadBatchEffect..AddRef(); s_currentQuadEffect = s_quadBatchEffect;
} }
s_currentCircleEffect?.ReleaseRef(); if(circleEffect != .Invalid)
if(circleEffect != null)
{ {
s_currentCircleEffect = effect..AddRef(); s_currentCircleEffect = circleEffect;
} }
else else
{ {
s_currentCircleEffect = s_circleBatchEffect..AddRef(); s_currentCircleEffect = s_circleBatchEffect;
} }
s_currentLineEffect = s_lineBatchEffect;
s_currentQuadEffect.Variables["ViewProjection"].SetData(camera.ViewProjection); s_currentQuadEffect.Variables["ViewProjection"].SetData(camera.ViewProjection);
s_currentCircleEffect.Variables["ViewProjection"].SetData(camera.ViewProjection); s_currentCircleEffect.Variables["ViewProjection"].SetData(camera.ViewProjection);
@@ -502,7 +493,7 @@ namespace GlitchyEngine.Renderer
#endif #endif
} }
public static void BeginScene(Camera camera, Matrix transform, DrawOrder drawOrder = .SortByTexture, Effect effect = null, Effect circleEffect = null) public static void BeginScene(Camera camera, Matrix transform, DrawOrder drawOrder = .SortByTexture, AssetHandle<Effect> effect = .Invalid, AssetHandle<Effect> circleEffect = .Invalid)
{ {
Debug.Profiler.ProfileRendererFunction!(); Debug.Profiler.ProfileRendererFunction!();
#if DEBUG #if DEBUG
@@ -510,37 +501,25 @@ namespace GlitchyEngine.Renderer
Log.EngineLogger.AssertDebug(!s_sceneRunning, "You have to call EndScene before you can make another call to BeginScene."); Log.EngineLogger.AssertDebug(!s_sceneRunning, "You have to call EndScene before you can make another call to BeginScene.");
#endif #endif
//s_textureColorEffect.Bind(Renderer._context); if(effect != .Invalid)
s_currentQuadEffect?.ReleaseRef();
if(effect != null)
{ {
s_currentQuadEffect = effect..AddRef(); s_currentQuadEffect = effect;
} }
else else
{ {
s_currentQuadEffect = s_quadBatchEffect..AddRef(); s_currentQuadEffect = s_quadBatchEffect;
} }
s_currentCircleEffect?.ReleaseRef(); if(circleEffect != .Invalid)
if(circleEffect != null)
{ {
s_currentCircleEffect = effect..AddRef(); s_currentCircleEffect = circleEffect;
} }
else else
{ {
s_currentCircleEffect = s_circleBatchEffect..AddRef(); s_currentCircleEffect = s_circleBatchEffect;
} }
s_currentLineEffect?.ReleaseRef(); s_currentLineEffect = s_lineBatchEffect;
/*if(circleEffect != null)
{
s_currentLineEffect = effect..AddRef();
}
else
{*/
s_currentLineEffect = s_lineBatchEffect..AddRef();
//}
Matrix viewProjection = camera.Projection * Matrix.Invert(transform); Matrix viewProjection = camera.Projection * Matrix.Invert(transform);
@@ -555,7 +534,7 @@ namespace GlitchyEngine.Renderer
#endif #endif
} }
public static void BeginScene(EditorCamera camera, DrawOrder drawOrder = .SortByTexture, Effect effect = null, Effect circleEffect = null) public static void BeginScene(EditorCamera camera, DrawOrder drawOrder = .SortByTexture, AssetHandle<Effect> effect = .Invalid, AssetHandle<Effect> circleEffect = .Invalid)
{ {
Debug.Profiler.ProfileRendererFunction!(); Debug.Profiler.ProfileRendererFunction!();
#if DEBUG #if DEBUG
@@ -563,37 +542,25 @@ namespace GlitchyEngine.Renderer
Log.EngineLogger.AssertDebug(!s_sceneRunning, "You have to call EndScene before you can make another call to BeginScene."); Log.EngineLogger.AssertDebug(!s_sceneRunning, "You have to call EndScene before you can make another call to BeginScene.");
#endif #endif
//s_textureColorEffect.Bind(Renderer._context); if(effect != .Invalid)
s_currentQuadEffect?.ReleaseRef();
if(effect != null)
{ {
s_currentQuadEffect = effect..AddRef(); s_currentQuadEffect = effect;
} }
else else
{ {
s_currentQuadEffect = s_quadBatchEffect..AddRef(); s_currentQuadEffect = s_quadBatchEffect;
} }
s_currentCircleEffect?.ReleaseRef(); if(circleEffect != .Invalid)
if(circleEffect != null)
{ {
s_currentCircleEffect = effect..AddRef(); s_currentCircleEffect = circleEffect;
} }
else else
{ {
s_currentCircleEffect = s_circleBatchEffect..AddRef(); s_currentCircleEffect = s_circleBatchEffect;
} }
s_currentLineEffect?.ReleaseRef(); s_currentLineEffect = s_lineBatchEffect;
/*if(circleEffect != null)
{
s_currentLineEffect = effect..AddRef();
}
else
{*/
s_currentLineEffect = s_lineBatchEffect..AddRef();
//}
Matrix viewProjection = camera.Projection * camera.View; Matrix viewProjection = camera.Projection * camera.View;

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