Compare commits
228 Commits
c73daf422b
...
master_fix
| Author | SHA1 | Date | |
|---|---|---|---|
| 824ff7050e | |||
| 042843fe42 | |||
| 8631b389c1 | |||
| e3f5af530b | |||
|
|
e257f9e4a0 | ||
|
|
056de752ed | ||
|
|
76700c0b24 | ||
|
|
9fdcff657d | ||
|
|
2b6339c05c | ||
|
|
bb91202439 | ||
|
|
f25e9f262a | ||
|
|
ee51077f49 | ||
|
|
950e958a58 | ||
|
|
5fdbed2b56 | ||
|
|
0e627577fc | ||
|
|
4846d4b024 | ||
|
|
5e5293bf7b | ||
|
|
d88477dcae | ||
|
|
bd58bd91b4 | ||
|
|
7ce0d88bdc | ||
|
|
98bb2d40d6 | ||
|
|
f4bc620bbd | ||
|
|
0313bf32c9 | ||
|
|
0c887cd29e | ||
|
|
5bd9bce634 | ||
|
|
2a53d0a462 | ||
| 82bd915274 | |||
|
|
71391cf1cc | ||
|
|
b5286af526 | ||
|
|
9f07a2a54e | ||
|
|
c39c642b60 | ||
|
|
02cff3973a | ||
|
|
a63b97d31d | ||
|
|
ca52122656 | ||
|
|
20a7fcf6a0 | ||
|
|
43665aa7eb | ||
|
|
3b9b49950c | ||
|
|
0a8752ec0a | ||
|
|
47685dc2be | ||
|
|
517ee5bb25 | ||
|
|
3ab01d3576 | ||
|
|
31b6d4d658 | ||
|
|
08f840d642 | ||
|
|
776b6259cd | ||
|
|
5c81c71116 | ||
|
|
188b635ea0 | ||
|
|
56066a3212 | ||
|
|
ed50ce9c90 | ||
|
|
a7e77f6e21 | ||
|
|
56278b17ee | ||
|
|
bd78db72b9 | ||
|
|
32bd72fecd | ||
|
|
3a798a70fa | ||
|
|
02429266b1 | ||
|
|
77aea0c69c | ||
|
|
6a3ce862cb | ||
|
|
93217da619 | ||
|
|
63def54dad | ||
|
|
00f9a28729 | ||
|
|
56beca0db4 | ||
|
|
64cd898a65 | ||
|
|
90472a4b31 | ||
|
|
a1999183f2 | ||
|
|
1e3ce48024 | ||
|
|
0007185b5f | ||
|
|
403d2cedc0 | ||
|
|
c8839b8587 | ||
|
|
cf048c9804 | ||
|
|
bea75f51bd | ||
|
|
1bf6612002 | ||
|
|
d9a18b1d31 | ||
|
|
465f30661f | ||
|
|
a62ca5452e | ||
|
|
92254eefcc | ||
|
|
2d56411e5f | ||
|
|
f8dc8ab903 | ||
|
|
2a55cda583 | ||
|
|
7c91c03adf | ||
|
|
caa902ea9b | ||
|
|
fb07071e24 | ||
|
|
a1cb7dcbe7 | ||
|
|
032f698c7b | ||
|
|
e2aaef9b88 | ||
|
|
ee0303bcfb | ||
|
|
1523c7b4ce | ||
|
|
a16a8eaded | ||
|
|
9ff9d48ffd | ||
|
|
dfb1fb91a5 | ||
|
|
8f56ab9534 | ||
|
|
c0dda45c7b | ||
|
|
3efb981f00 | ||
|
|
ed408917c6 | ||
|
|
2ca435a414 | ||
|
|
de9e282bad | ||
|
|
c437daf9be | ||
|
|
1e4f96486f | ||
|
|
e03d0f3322 | ||
|
|
5f0e1253cc | ||
|
|
7e6b040258 | ||
|
|
329ebb6482 | ||
|
|
7a9c58003d | ||
|
|
371a16e37b | ||
|
|
95629e792d | ||
|
|
e79af2fd60 | ||
|
|
4aba0153f8 | ||
|
|
f91c33e17c | ||
|
|
6c29877b20 | ||
|
|
3abde6ecfc | ||
|
|
b42168eee5 | ||
|
|
ac3b2c0ef2 | ||
|
|
f640452b7b | ||
|
|
2f670495ac | ||
|
|
2a36edf528 | ||
|
|
5e690abd76 | ||
|
|
4008e19ca9 | ||
|
|
e9070b30a0 | ||
|
|
636a1ff930 | ||
|
|
3888c4ba21 | ||
|
|
69173803bf | ||
|
|
13e31650be | ||
|
|
3563287f17 | ||
|
|
91ee9f5e05 | ||
| 49918a1067 | |||
|
|
c7997e0c2f | ||
|
|
4805dfbdba | ||
|
|
62424215c1 | ||
|
|
97ae13759e | ||
|
|
108678d94f | ||
|
|
66dbba5c16 | ||
|
|
d84cef0c18 | ||
|
|
077cefc60e | ||
|
|
35acc668c9 | ||
|
|
ebbe0f12ed | ||
|
|
6a8b76278a | ||
|
|
8ac99ef28f | ||
|
|
547cf7f600 | ||
|
|
b8b8b118c9 | ||
|
|
76247323eb | ||
|
|
0ff20c7c85 | ||
|
|
dd690e7495 | ||
|
|
ca500548a3 | ||
|
|
c0b73375b1 | ||
|
|
9c6d6a0b07 | ||
|
|
179f6014bf | ||
|
|
b580c6ec8e | ||
|
|
dd60cf0040 | ||
|
|
cc851b29fc | ||
|
|
59643b2fb9 | ||
|
|
3a5bb81d39 | ||
|
|
5ec860015d | ||
|
|
0f701ec08e | ||
|
|
387c3ea2f4 | ||
|
|
85b134b7be | ||
|
|
5d17d2509d | ||
|
|
036d4b2f4b | ||
|
|
93f12b73d8 | ||
|
|
1091bc6e2c | ||
|
|
594c0fb8e7 | ||
| 3fc1895b56 | |||
|
|
a70d7cf1f9 | ||
|
|
1f592ba1a1 | ||
|
|
a43daf025d | ||
|
|
296a2afa95 | ||
|
|
a7e879a3a4 | ||
|
|
27b160b464 | ||
|
|
7c3c4f1a63 | ||
|
|
fbae93b532 | ||
|
|
35d6e5fd21 | ||
|
|
114828adcb | ||
|
|
053e52c91f | ||
|
|
d24bd7dfd0 | ||
| 2c8c9b1637 | |||
|
|
05a8c841da | ||
|
|
c4fcaa999c | ||
|
|
70c9dd6608 | ||
|
|
802e2ac7c2 | ||
|
|
0ca60062d9 | ||
|
|
5a587a8582 | ||
|
|
22515c37b5 | ||
|
|
38a48cf1d4 | ||
|
|
cd66d00219 | ||
|
|
c944bd9bed | ||
|
|
a0689f3f00 | ||
|
|
2ee2c97f1e | ||
|
|
fd19e83a46 | ||
|
|
755702b65a | ||
|
|
72e200a7fc | ||
|
|
6353e5f4f2 | ||
|
|
b184022d15 | ||
|
|
26dce69404 | ||
| 2841ac22df | |||
|
|
516f22c3c0 | ||
|
|
5a8c4cd0a5 | ||
|
|
f53b7e3323 | ||
|
|
c1439c646e | ||
| 280035e54f | |||
| 0d140c4f39 | |||
| 32b4efc175 | |||
|
|
d1774cac28 | ||
|
|
2629511224 | ||
|
|
bcf7226946 | ||
|
|
f5c9e00beb | ||
|
|
6353514188 | ||
|
|
8467315a1e | ||
|
|
be5dbbb95f | ||
| 6b9c727a6a | |||
| 91c0ba1986 | |||
|
|
e4bb8001b2 | ||
|
|
a9fc5f720d | ||
|
|
d323b1c7e2 | ||
|
|
d93c32db9c | ||
|
|
08abdc159e | ||
|
|
708b9c6767 | ||
|
|
ed26a4c182 | ||
|
|
a239984908 | ||
|
|
fc3ea44c69 | ||
|
|
fdecad0d29 | ||
|
|
c7437ed533 | ||
|
|
dab44f5ceb | ||
|
|
c635d93b3c | ||
|
|
7377bad721 | ||
|
|
09fa3ce4be | ||
|
|
bd0daf7580 | ||
|
|
e1b3429b4c | ||
|
|
efa963be68 | ||
|
|
df28b0d977 | ||
|
|
59fb83a469 | ||
|
|
7544500be1 |
2
.github/ISSUE_TEMPLATE/1-bug.yaml
vendored
2
.github/ISSUE_TEMPLATE/1-bug.yaml
vendored
@@ -31,7 +31,7 @@ body:
|
|||||||
- '1.10'
|
- '1.10'
|
||||||
- '1.11'
|
- '1.11'
|
||||||
- master branch
|
- master branch
|
||||||
default: 2
|
default: 3
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
|
|||||||
4
.github/workflows/build_ios.yml
vendored
4
.github/workflows/build_ios.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
|||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v3
|
uses: actions/setup-dotnet@v3
|
||||||
with:
|
with:
|
||||||
dotnet-version: 8.0.x
|
dotnet-version: 9.0.x
|
||||||
- name: Setup .NET Workload
|
- name: Setup .NET Workload
|
||||||
run: |
|
run: |
|
||||||
dotnet workload install ios
|
dotnet workload install ios
|
||||||
@@ -33,4 +33,4 @@ jobs:
|
|||||||
git lfs pull
|
git lfs pull
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
./Development/Scripts/Mac/CallBuildTool.sh -build -log -dotnet=8 -arch=ARM64 -platform=iOS -configuration=Release -buildtargets=FlaxGame
|
./Development/Scripts/Mac/CallBuildTool.sh -build -log -dotnet=9 -arch=ARM64 -platform=iOS -configuration=Release -buildtargets=FlaxGame
|
||||||
|
|||||||
BIN
Content/Editor/Primitives/Cube.flax
(Stored with Git LFS)
BIN
Content/Editor/Primitives/Cube.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/ColorGrading.flax
(Stored with Git LFS)
BIN
Content/Shaders/ColorGrading.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/GI/GlobalSurfaceAtlas.flax
(Stored with Git LFS)
BIN
Content/Shaders/GI/GlobalSurfaceAtlas.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/GlobalSignDistanceField.flax
(Stored with Git LFS)
BIN
Content/Shaders/GlobalSignDistanceField.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/MotionBlur.flax
(Stored with Git LFS)
BIN
Content/Shaders/MotionBlur.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/SDF.flax
(Stored with Git LFS)
BIN
Content/Shaders/SDF.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/VolumetricFog.flax
(Stored with Git LFS)
BIN
Content/Shaders/VolumetricFog.flax
(Stored with Git LFS)
Binary file not shown.
@@ -4,7 +4,7 @@
|
|||||||
"Major": 1,
|
"Major": 1,
|
||||||
"Minor": 11,
|
"Minor": 11,
|
||||||
"Revision": 0,
|
"Revision": 0,
|
||||||
"Build": 6801
|
"Build": 6805
|
||||||
},
|
},
|
||||||
"Company": "Flax",
|
"Company": "Flax",
|
||||||
"Copyright": "Copyright (c) 2012-2025 Wojciech Figat. All rights reserved.",
|
"Copyright": "Copyright (c) 2012-2025 Wojciech Figat. All rights reserved.",
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ Follow the instructions below to compile and run the engine from source.
|
|||||||
* Fedora: `sudo dnf install dotnet-sdk-8.0`
|
* Fedora: `sudo dnf install dotnet-sdk-8.0`
|
||||||
* Arch: `sudo pacman -S dotnet-sdk-8.0 dotnet-runtime-8.0 dotnet-targeting-pack-8.0 dotnet-host`
|
* Arch: `sudo pacman -S dotnet-sdk-8.0 dotnet-runtime-8.0 dotnet-targeting-pack-8.0 dotnet-host`
|
||||||
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
|
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
|
||||||
* Ubuntu: `sudo apt install vulkan-sdk`
|
* Ubuntu: `sudo apt install vulkan-sdk` (deprecated, follow official docs)
|
||||||
* Fedora: `sudo dnf install vulkan-headers vulkan-tools vulkan-validation-layers`
|
* Fedora: `sudo dnf install vulkan-headers vulkan-tools vulkan-validation-layers`
|
||||||
* Arch: `sudo pacman -S vulkan-headers vulkan-tools vulkan-validation-layers`
|
* Arch: `sudo pacman -S vulkan-headers vulkan-tools vulkan-validation-layers`
|
||||||
* Install Git with LFS
|
* Install Git with LFS
|
||||||
@@ -60,7 +60,7 @@ Follow the instructions below to compile and run the engine from source.
|
|||||||
* Ubuntu: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev zlib1g-dev`
|
* Ubuntu: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev zlib1g-dev`
|
||||||
* Fedora: `sudo dnf install libX11-devel libXcursor-devel libXinerama-devel ghc-zlib-devel`
|
* Fedora: `sudo dnf install libX11-devel libXcursor-devel libXinerama-devel ghc-zlib-devel`
|
||||||
* Arch: `sudo pacman -S base-devel libx11 libxcursor libxinerama zlib`
|
* Arch: `sudo pacman -S base-devel libx11 libxcursor libxinerama zlib`
|
||||||
* Install Clang compiler (version 6 or later):
|
* Install Clang compiler (version 14 or later):
|
||||||
* Ubuntu: `sudo apt-get install clang lldb lld`
|
* Ubuntu: `sudo apt-get install clang lldb lld`
|
||||||
* Fedora: `sudo dnf install clang llvm lldb lld`
|
* Fedora: `sudo dnf install clang llvm lldb lld`
|
||||||
* Arch: `sudo pacman -S clang lldb lld`
|
* Arch: `sudo pacman -S clang lldb lld`
|
||||||
|
|||||||
@@ -281,6 +281,13 @@ namespace FlaxEditor.Content
|
|||||||
|
|
||||||
private void CacheData()
|
private void CacheData()
|
||||||
{
|
{
|
||||||
|
if (!_asset)
|
||||||
|
{
|
||||||
|
_parameters = Utils.GetEmptyArray<ScriptMemberInfo>();
|
||||||
|
_methods = Utils.GetEmptyArray<ScriptMemberInfo>();
|
||||||
|
_attributes = Utils.GetEmptyArray<Attribute>();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (_parameters != null)
|
if (_parameters != null)
|
||||||
return;
|
return;
|
||||||
if (_asset.WaitForLoaded())
|
if (_asset.WaitForLoaded())
|
||||||
@@ -344,13 +351,13 @@ namespace FlaxEditor.Content
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Name => Path.GetFileNameWithoutExtension(_asset.Path);
|
public string Name => _asset ? Path.GetFileNameWithoutExtension(_asset.Path) : null;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Namespace => string.Empty;
|
public string Namespace => string.Empty;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string TypeName => JsonSerializer.GetStringID(_asset.ID);
|
public string TypeName => _asset ? JsonSerializer.GetStringID(_asset.ID) : null;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool IsPublic => true;
|
public bool IsPublic => true;
|
||||||
|
|||||||
@@ -130,6 +130,11 @@ namespace FlaxEditor.Content
|
|||||||
eyeAdaptation.Mode = EyeAdaptationMode.None;
|
eyeAdaptation.Mode = EyeAdaptationMode.None;
|
||||||
eyeAdaptation.OverrideFlags |= EyeAdaptationSettingsOverride.Mode;
|
eyeAdaptation.OverrideFlags |= EyeAdaptationSettingsOverride.Mode;
|
||||||
preview.PostFxVolume.EyeAdaptation = eyeAdaptation;
|
preview.PostFxVolume.EyeAdaptation = eyeAdaptation;
|
||||||
|
|
||||||
|
var antiAliasing = preview.PostFxVolume.AntiAliasing;
|
||||||
|
antiAliasing.Mode = AntialiasingMode.FastApproximateAntialiasing;
|
||||||
|
antiAliasing.OverrideFlags |= AntiAliasingSettingsOverride.Mode;
|
||||||
|
preview.PostFxVolume.AntiAliasing = antiAliasing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,26 +15,32 @@
|
|||||||
#include "Editor/ProjectInfo.h"
|
#include "Editor/ProjectInfo.h"
|
||||||
#include "Editor/Utilities/EditorUtilities.h"
|
#include "Editor/Utilities/EditorUtilities.h"
|
||||||
|
|
||||||
GDKPlatformTools::GDKPlatformTools()
|
String GetGDK()
|
||||||
{
|
{
|
||||||
// Find GDK
|
String gdk;
|
||||||
Platform::GetEnvironmentVariable(TEXT("GameDKLatest"), _gdkPath);
|
Platform::GetEnvironmentVariable(TEXT("GameDKLatest"), gdk);
|
||||||
if (_gdkPath.IsEmpty() || !FileSystem::DirectoryExists(_gdkPath))
|
if (gdk.IsEmpty() || !FileSystem::DirectoryExists(gdk))
|
||||||
{
|
{
|
||||||
_gdkPath.Clear();
|
gdk.Clear();
|
||||||
Platform::GetEnvironmentVariable(TEXT("GRDKLatest"), _gdkPath);
|
Platform::GetEnvironmentVariable(TEXT("GRDKLatest"), gdk);
|
||||||
if (_gdkPath.IsEmpty() || !FileSystem::DirectoryExists(_gdkPath))
|
if (gdk.IsEmpty() || !FileSystem::DirectoryExists(gdk))
|
||||||
{
|
{
|
||||||
_gdkPath.Clear();
|
gdk.Clear();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_gdkPath.EndsWith(TEXT("GRDK\\")))
|
if (gdk.EndsWith(TEXT("GRDK\\")))
|
||||||
_gdkPath.Remove(_gdkPath.Length() - 6);
|
gdk.Remove(gdk.Length() - 6);
|
||||||
else if (_gdkPath.EndsWith(TEXT("GRDK")))
|
else if (gdk.EndsWith(TEXT("GRDK")))
|
||||||
_gdkPath.Remove(_gdkPath.Length() - 5);
|
gdk.Remove(gdk.Length() - 5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return gdk;
|
||||||
|
}
|
||||||
|
|
||||||
|
GDKPlatformTools::GDKPlatformTools()
|
||||||
|
{
|
||||||
|
_gdkPath = GetGDK();
|
||||||
}
|
}
|
||||||
|
|
||||||
DotNetAOTModes GDKPlatformTools::UseAOT() const
|
DotNetAOTModes GDKPlatformTools::UseAOT() const
|
||||||
@@ -121,7 +127,7 @@ bool GDKPlatformTools::OnPostProcess(CookingData& data, GDKPlatformSettings* pla
|
|||||||
validName.Add('\0');
|
validName.Add('\0');
|
||||||
|
|
||||||
sb.Append(TEXT("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"));
|
sb.Append(TEXT("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"));
|
||||||
sb.Append(TEXT("<Game configVersion=\"0\">\n"));
|
sb.Append(TEXT("<Game configVersion=\"1\">\n"));
|
||||||
sb.AppendFormat(TEXT(" <Identity Name=\"{0}\" Publisher=\"{1}\" Version=\"{2}\"/>\n"),
|
sb.AppendFormat(TEXT(" <Identity Name=\"{0}\" Publisher=\"{1}\" Version=\"{2}\"/>\n"),
|
||||||
validName.Get(),
|
validName.Get(),
|
||||||
platformSettings->PublisherName.HasChars() ? platformSettings->PublisherName : TEXT("CN=") + gameSettings->CompanyName,
|
platformSettings->PublisherName.HasChars() ? platformSettings->PublisherName : TEXT("CN=") + gameSettings->CompanyName,
|
||||||
|
|||||||
@@ -10,9 +10,10 @@
|
|||||||
#include "Engine/Serialization/JsonTools.h"
|
#include "Engine/Serialization/JsonTools.h"
|
||||||
#include "Engine/Serialization/JsonWriters.h"
|
#include "Engine/Serialization/JsonWriters.h"
|
||||||
#include "Editor/Cooker/PlatformTools.h"
|
#include "Editor/Cooker/PlatformTools.h"
|
||||||
|
#include "Engine/Engine/Globals.h"
|
||||||
#include "Editor/Editor.h"
|
#include "Editor/Editor.h"
|
||||||
#include "Editor/ProjectInfo.h"
|
#include "Editor/ProjectInfo.h"
|
||||||
#include "Engine/Engine/Globals.h"
|
#include "Editor/Utilities/EditorUtilities.h"
|
||||||
#if PLATFORM_MAC
|
#if PLATFORM_MAC
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -127,7 +128,7 @@ bool CompileScriptsStep::DeployBinaries(CookingData& data, const String& path, c
|
|||||||
const String dst = dstPath / StringUtils::GetFileName(file);
|
const String dst = dstPath / StringUtils::GetFileName(file);
|
||||||
if (dst == file)
|
if (dst == file)
|
||||||
continue;
|
continue;
|
||||||
if (FileSystem::CopyFile(dst, file))
|
if (EditorUtilities::CopyFileIfNewer(dst, file))
|
||||||
{
|
{
|
||||||
data.Error(String::Format(TEXT("Failed to copy file from {0} to {1}."), file, dst));
|
data.Error(String::Format(TEXT("Failed to copy file from {0} to {1}."), file, dst));
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -526,6 +526,7 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass
|
|||||||
#if PLATFORM_TOOLS_XBOX_SCARLETT
|
#if PLATFORM_TOOLS_XBOX_SCARLETT
|
||||||
case BuildPlatform::XboxScarlett:
|
case BuildPlatform::XboxScarlett:
|
||||||
{
|
{
|
||||||
|
options.Platform = PlatformType::XboxScarlett;
|
||||||
const char* platformDefineName = "PLATFORM_XBOX_SCARLETT";
|
const char* platformDefineName = "PLATFORM_XBOX_SCARLETT";
|
||||||
COMPILE_PROFILE(DirectX_SM6, SHADER_FILE_CHUNK_INTERNAL_D3D_SM6_CACHE);
|
COMPILE_PROFILE(DirectX_SM6, SHADER_FILE_CHUNK_INTERNAL_D3D_SM6_CACHE);
|
||||||
break;
|
break;
|
||||||
@@ -1367,7 +1368,10 @@ bool CookAssetsStep::Perform(CookingData& data)
|
|||||||
{
|
{
|
||||||
typeName = e.TypeName;
|
typeName = e.TypeName;
|
||||||
}
|
}
|
||||||
LOG(Info, "{0}: {1:>4} assets of total size {2}", typeName, e.Count, Utilities::BytesToText(e.ContentSize));
|
if (e.Count == 1)
|
||||||
|
LOG(Info, "{0}: 1 asset of total size {1}", typeName, Utilities::BytesToText(e.ContentSize));
|
||||||
|
else
|
||||||
|
LOG(Info, "{0}: {1:>4} assets of total size {2}", typeName, e.Count, Utilities::BytesToText(e.ContentSize));
|
||||||
}
|
}
|
||||||
LOG(Info, "");
|
LOG(Info, "");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ bool DeployDataStep::Perform(CookingData& data)
|
|||||||
}
|
}
|
||||||
if (version.IsEmpty())
|
if (version.IsEmpty())
|
||||||
{
|
{
|
||||||
data.Error(String::Format(TEXT("Failed to find supported .NET {} version (min {}) for the current host platform."), maxVer, minVer));
|
data.Error(String::Format(TEXT("Failed to find supported .NET {} version (min {}) for {} platform."), maxVer, minVer, platformName));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ bool PrecompileAssembliesStep::Perform(CookingData& data)
|
|||||||
data.StepProgress(infoMsg, 0);
|
data.StepProgress(infoMsg, 0);
|
||||||
|
|
||||||
// Override Newtonsoft.Json with AOT-version (one that doesn't use System.Reflection.Emit)
|
// Override Newtonsoft.Json with AOT-version (one that doesn't use System.Reflection.Emit)
|
||||||
|
// TODO: remove it since EngineModule does properly reference AOT lib now
|
||||||
EditorUtilities::CopyFileIfNewer(data.ManagedCodeOutputPath / TEXT("Newtonsoft.Json.dll"), Globals::StartupFolder / TEXT("Source/Platforms/DotNet/AOT/Newtonsoft.Json.dll"));
|
EditorUtilities::CopyFileIfNewer(data.ManagedCodeOutputPath / TEXT("Newtonsoft.Json.dll"), Globals::StartupFolder / TEXT("Source/Platforms/DotNet/AOT/Newtonsoft.Json.dll"));
|
||||||
FileSystem::DeleteFile(data.ManagedCodeOutputPath / TEXT("Newtonsoft.Json.xml"));
|
FileSystem::DeleteFile(data.ManagedCodeOutputPath / TEXT("Newtonsoft.Json.xml"));
|
||||||
FileSystem::DeleteFile(data.ManagedCodeOutputPath / TEXT("Newtonsoft.Json.pdb"));
|
FileSystem::DeleteFile(data.ManagedCodeOutputPath / TEXT("Newtonsoft.Json.pdb"));
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.GUI;
|
||||||
|
|
||||||
namespace FlaxEditor.CustomEditors.Dedicated
|
namespace FlaxEditor.CustomEditors.Dedicated
|
||||||
{
|
{
|
||||||
@@ -11,7 +12,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
[CustomEditor(typeof(EnvironmentProbe)), DefaultEditor]
|
[CustomEditor(typeof(EnvironmentProbe)), DefaultEditor]
|
||||||
public class EnvironmentProbeEditor : ActorEditor
|
public class EnvironmentProbeEditor : ActorEditor
|
||||||
{
|
{
|
||||||
private FlaxEngine.GUI.Button _bake;
|
private Button _bake;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Initialize(LayoutElementsContainer layout)
|
public override void Initialize(LayoutElementsContainer layout)
|
||||||
@@ -20,8 +21,9 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
|
|
||||||
if (Values.HasDifferentTypes == false)
|
if (Values.HasDifferentTypes == false)
|
||||||
{
|
{
|
||||||
layout.Space(10);
|
var group = layout.Group("Bake");
|
||||||
_bake = layout.Button("Bake").Button;
|
group.Panel.ItemsMargin = new Margin(Utilities.Constants.UIMargin * 2);
|
||||||
|
_bake = group.Button("Bake").Button;
|
||||||
_bake.Clicked += BakeButtonClicked;
|
_bake.Clicked += BakeButtonClicked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -914,9 +914,11 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
// Remove drop down arrows and containment lines if no objects in the group
|
// Remove drop down arrows and containment lines if no objects in the group
|
||||||
if (group.Children.Count == 0)
|
if (group.Children.Count == 0)
|
||||||
{
|
{
|
||||||
|
group.Panel.Close();
|
||||||
group.Panel.ArrowImageOpened = null;
|
group.Panel.ArrowImageOpened = null;
|
||||||
group.Panel.ArrowImageClosed = null;
|
group.Panel.ArrowImageClosed = null;
|
||||||
group.Panel.EnableContainmentLines = false;
|
group.Panel.EnableContainmentLines = false;
|
||||||
|
group.Panel.CanOpenClose = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scripts arrange bar
|
// Scripts arrange bar
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.GUI;
|
||||||
|
|
||||||
namespace FlaxEditor.CustomEditors.Dedicated
|
namespace FlaxEditor.CustomEditors.Dedicated
|
||||||
{
|
{
|
||||||
@@ -19,8 +20,9 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
if (Values.HasDifferentTypes == false)
|
if (Values.HasDifferentTypes == false)
|
||||||
{
|
{
|
||||||
// Add 'Bake' button
|
// Add 'Bake' button
|
||||||
layout.Space(10);
|
var group = layout.Group("Bake");
|
||||||
var button = layout.Button("Bake");
|
group.Panel.ItemsMargin = new Margin(Utilities.Constants.UIMargin * 2);
|
||||||
|
var button = group.Button("Bake");
|
||||||
button.Button.Clicked += BakeButtonClicked;
|
button.Button.Clicked += BakeButtonClicked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,6 +123,8 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
{
|
{
|
||||||
base.Refresh();
|
base.Refresh();
|
||||||
|
|
||||||
|
if (Picker == null)
|
||||||
|
return;
|
||||||
var differentValues = HasDifferentValues;
|
var differentValues = HasDifferentValues;
|
||||||
Picker.DifferentValues = differentValues;
|
Picker.DifferentValues = differentValues;
|
||||||
if (!differentValues)
|
if (!differentValues)
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
|
|
||||||
menu.AddButton("Copy", linkedEditor.Copy);
|
menu.AddButton("Copy", linkedEditor.Copy);
|
||||||
var b = menu.AddButton("Duplicate", () => Editor.Duplicate(Index));
|
var b = menu.AddButton("Duplicate", () => Editor.Duplicate(Index));
|
||||||
b.Enabled = linkedEditor.CanPaste && !Editor._readOnly && Editor._canResize;
|
b.Enabled = !Editor._readOnly && Editor._canResize;
|
||||||
b = menu.AddButton("Paste", linkedEditor.Paste);
|
b = menu.AddButton("Paste", linkedEditor.Paste);
|
||||||
b.Enabled = linkedEditor.CanPaste && !Editor._readOnly;
|
b.Enabled = linkedEditor.CanPaste && !Editor._readOnly;
|
||||||
|
|
||||||
@@ -407,7 +407,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
|
|
||||||
menu.AddButton("Copy", linkedEditor.Copy);
|
menu.AddButton("Copy", linkedEditor.Copy);
|
||||||
var b = menu.AddButton("Duplicate", () => Editor.Duplicate(Index));
|
var b = menu.AddButton("Duplicate", () => Editor.Duplicate(Index));
|
||||||
b.Enabled = linkedEditor.CanPaste && !Editor._readOnly && Editor._canResize;
|
b.Enabled = !Editor._readOnly && Editor._canResize;
|
||||||
var paste = menu.AddButton("Paste", linkedEditor.Paste);
|
var paste = menu.AddButton("Paste", linkedEditor.Paste);
|
||||||
paste.Enabled = linkedEditor.CanPaste && !Editor._readOnly;
|
paste.Enabled = linkedEditor.CanPaste && !Editor._readOnly;
|
||||||
|
|
||||||
@@ -650,7 +650,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
panel.Panel.Size = new Float2(0, 18);
|
panel.Panel.Size = new Float2(0, 18);
|
||||||
panel.Panel.Margin = new Margin(0, 0, Utilities.Constants.UIMargin, 0);
|
panel.Panel.Margin = new Margin(0, 0, Utilities.Constants.UIMargin, 0);
|
||||||
|
|
||||||
var removeButton = panel.Button("-", "Remove the last item");
|
var removeButton = panel.Button("-", "Remove the last item.");
|
||||||
removeButton.Button.Size = new Float2(16, 16);
|
removeButton.Button.Size = new Float2(16, 16);
|
||||||
removeButton.Button.Enabled = size > _minCount;
|
removeButton.Button.Enabled = size > _minCount;
|
||||||
removeButton.Button.AnchorPreset = AnchorPresets.TopRight;
|
removeButton.Button.AnchorPreset = AnchorPresets.TopRight;
|
||||||
@@ -661,7 +661,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
Resize(Count - 1);
|
Resize(Count - 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
var addButton = panel.Button("+", "Add a new item");
|
var addButton = panel.Button("+", "Add a new item.");
|
||||||
addButton.Button.Size = new Float2(16, 16);
|
addButton.Button.Size = new Float2(16, 16);
|
||||||
addButton.Button.Enabled = (!NotNullItems || size > 0) && size < _maxCount;
|
addButton.Button.Enabled = (!NotNullItems || size > 0) && size < _maxCount;
|
||||||
addButton.Button.AnchorPreset = AnchorPresets.TopRight;
|
addButton.Button.AnchorPreset = AnchorPresets.TopRight;
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
public event Action<TypePickerControl> TypePickerValueChanged;
|
public event Action<TypePickerControl> TypePickerValueChanged;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The custom callback for types validation. Cane be used to implement a rule for types to pick.
|
/// The custom callback for types validation. Can be used to implement a rule for types to pick.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Func<ScriptType, bool> CheckValid;
|
public Func<ScriptType, bool> CheckValid;
|
||||||
|
|
||||||
@@ -353,7 +353,13 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
}
|
}
|
||||||
if (!string.IsNullOrEmpty(typeReference.CheckMethod))
|
if (!string.IsNullOrEmpty(typeReference.CheckMethod))
|
||||||
{
|
{
|
||||||
var parentType = ParentEditor.Values[0].GetType();
|
var parentEditor = ParentEditor;
|
||||||
|
// Find actual parent editor if parent editor is collection editor
|
||||||
|
while (parentEditor.GetType().IsAssignableTo(typeof(CollectionEditor)))
|
||||||
|
parentEditor = parentEditor.ParentEditor;
|
||||||
|
|
||||||
|
var parentType = parentEditor.Values[0].GetType();
|
||||||
|
|
||||||
var method = parentType.GetMethod(typeReference.CheckMethod, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
var method = parentType.GetMethod(typeReference.CheckMethod, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
if (method != null)
|
if (method != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1390,6 +1390,7 @@ namespace FlaxEditor
|
|||||||
public void BuildAllMeshesSDF()
|
public void BuildAllMeshesSDF()
|
||||||
{
|
{
|
||||||
var models = new List<Model>();
|
var models = new List<Model>();
|
||||||
|
var forceRebuild = Input.GetKey(KeyboardKeys.F);
|
||||||
Scene.ExecuteOnGraph(node =>
|
Scene.ExecuteOnGraph(node =>
|
||||||
{
|
{
|
||||||
if (node is StaticModelNode staticModelNode && staticModelNode.Actor is StaticModel staticModel)
|
if (node is StaticModelNode staticModelNode && staticModelNode.Actor is StaticModel staticModel)
|
||||||
@@ -1399,7 +1400,7 @@ namespace FlaxEditor
|
|||||||
model != null &&
|
model != null &&
|
||||||
!models.Contains(model) &&
|
!models.Contains(model) &&
|
||||||
!model.IsVirtual &&
|
!model.IsVirtual &&
|
||||||
model.SDF.Texture == null)
|
(forceRebuild || model.SDF.Texture == null))
|
||||||
{
|
{
|
||||||
models.Add(model);
|
models.Add(model);
|
||||||
}
|
}
|
||||||
@@ -1412,7 +1413,17 @@ namespace FlaxEditor
|
|||||||
{
|
{
|
||||||
var model = models[i];
|
var model = models[i];
|
||||||
Log($"[{i}/{models.Count}] Generating SDF for {model}");
|
Log($"[{i}/{models.Count}] Generating SDF for {model}");
|
||||||
if (!model.GenerateSDF())
|
float resolutionScale = 1.0f, backfacesThreshold = 0.6f;
|
||||||
|
int lodIndex = 6;
|
||||||
|
bool useGPU = true;
|
||||||
|
var sdf = model.SDF;
|
||||||
|
if (sdf.Texture != null)
|
||||||
|
{
|
||||||
|
// Preserve options set on this model
|
||||||
|
resolutionScale = sdf.ResolutionScale;
|
||||||
|
lodIndex = sdf.LOD;
|
||||||
|
}
|
||||||
|
if (!model.GenerateSDF(resolutionScale, lodIndex, true, backfacesThreshold, useGPU))
|
||||||
model.Save();
|
model.Save();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1587,7 +1598,7 @@ namespace FlaxEditor
|
|||||||
if (dockedTo != null && dockedTo.SelectedTab != gameWin && dockedTo.SelectedTab != null)
|
if (dockedTo != null && dockedTo.SelectedTab != gameWin && dockedTo.SelectedTab != null)
|
||||||
result = dockedTo.SelectedTab.Size;
|
result = dockedTo.SelectedTab.Size;
|
||||||
else
|
else
|
||||||
result = gameWin.Viewport.Size;
|
result = gameWin.Viewport.ContentSize;
|
||||||
|
|
||||||
result *= root.DpiScale;
|
result *= root.DpiScale;
|
||||||
result = Float2.Round(result);
|
result = Float2.Round(result);
|
||||||
|
|||||||
@@ -447,8 +447,8 @@ namespace FlaxEditor.GUI.Tree
|
|||||||
// Select previous parent child
|
// Select previous parent child
|
||||||
var select = nodeParent.GetChild(myIndex - 1) as TreeNode;
|
var select = nodeParent.GetChild(myIndex - 1) as TreeNode;
|
||||||
|
|
||||||
// Select last child if is valid and expanded and has any children
|
// Get bottom most child node
|
||||||
if (select != null && select.IsExpanded && select.HasAnyVisibleChild)
|
while (select != null && select.IsExpanded && select.HasAnyVisibleChild)
|
||||||
{
|
{
|
||||||
select = select.GetChild(select.ChildrenCount - 1) as TreeNode;
|
select = select.GetChild(select.ChildrenCount - 1) as TreeNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -714,6 +714,7 @@ namespace FlaxEditor.Modules
|
|||||||
_menuToolsBuildCSGMesh = cm.AddButton("Build CSG mesh", inputOptions.BuildCSG, Editor.BuildCSG);
|
_menuToolsBuildCSGMesh = cm.AddButton("Build CSG mesh", inputOptions.BuildCSG, Editor.BuildCSG);
|
||||||
_menuToolsBuildNavMesh = cm.AddButton("Build Nav Mesh", inputOptions.BuildNav, Editor.BuildNavMesh);
|
_menuToolsBuildNavMesh = cm.AddButton("Build Nav Mesh", inputOptions.BuildNav, Editor.BuildNavMesh);
|
||||||
_menuToolsBuildAllMeshesSDF = cm.AddButton("Build all meshes SDF", inputOptions.BuildSDF, Editor.BuildAllMeshesSDF);
|
_menuToolsBuildAllMeshesSDF = cm.AddButton("Build all meshes SDF", inputOptions.BuildSDF, Editor.BuildAllMeshesSDF);
|
||||||
|
_menuToolsBuildAllMeshesSDF.LinkTooltip("Generates Sign Distance Field texture for all meshes used in loaded scenes. Use with 'F' key pressed to force rebuild SDF for meshes with existing one.");
|
||||||
cm.AddSeparator();
|
cm.AddSeparator();
|
||||||
cm.AddButton("Game Cooker", Editor.Windows.GameCookerWin.FocusOrShow);
|
cm.AddButton("Game Cooker", Editor.Windows.GameCookerWin.FocusOrShow);
|
||||||
_menuToolsCancelBuilding = cm.AddButton("Cancel building game", () => GameCooker.Cancel());
|
_menuToolsCancelBuilding = cm.AddButton("Cancel building game", () => GameCooker.Cancel());
|
||||||
|
|||||||
@@ -896,9 +896,11 @@ namespace FlaxEditor.Modules
|
|||||||
|
|
||||||
if (type.IsAssignableTo(typeof(AssetEditorWindow)))
|
if (type.IsAssignableTo(typeof(AssetEditorWindow)))
|
||||||
{
|
{
|
||||||
var ctor = type.GetConstructor(new Type[] { typeof(Editor), typeof(AssetItem) });
|
|
||||||
var assetItem = Editor.ContentDatabase.FindAsset(winData.AssetItemID);
|
var assetItem = Editor.ContentDatabase.FindAsset(winData.AssetItemID);
|
||||||
|
var assetType = assetItem.GetType();
|
||||||
|
var ctor = type.GetConstructor(new Type[] { typeof(Editor), assetType });
|
||||||
var win = (AssetEditorWindow)ctor.Invoke(new object[] { Editor.Instance, assetItem });
|
var win = (AssetEditorWindow)ctor.Invoke(new object[] { Editor.Instance, assetItem });
|
||||||
|
|
||||||
win.Show(winData.DockState, winData.DockState != DockState.Float ? winData.DockedTo : null, winData.SelectOnShow, winData.SplitterValue);
|
win.Show(winData.DockState, winData.DockState != DockState.Float ? winData.DockedTo : null, winData.SelectOnShow, winData.SplitterValue);
|
||||||
if (winData.DockState == DockState.Float)
|
if (winData.DockState == DockState.Float)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -406,6 +406,8 @@ namespace FlaxEngine.Utilities
|
|||||||
{
|
{
|
||||||
if (type == ScriptType.Null)
|
if (type == ScriptType.Null)
|
||||||
return null;
|
return null;
|
||||||
|
if (type.BaseType == null)
|
||||||
|
return type.Type;
|
||||||
while (type.Type == null)
|
while (type.Type == null)
|
||||||
type = type.BaseType;
|
type = type.BaseType;
|
||||||
return type.Type;
|
return type.Type;
|
||||||
|
|||||||
@@ -726,7 +726,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
|
|
||||||
private void OnSurfaceMouseUp(ref Float2 mouse, MouseButton buttons, ref bool handled)
|
private void OnSurfaceMouseUp(ref Float2 mouse, MouseButton buttons, ref bool handled)
|
||||||
{
|
{
|
||||||
if (handled)
|
if (handled || Surface.Context != Context)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Check click over the connection
|
// Check click over the connection
|
||||||
@@ -751,7 +751,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
|
|
||||||
private void OnSurfaceMouseDoubleClick(ref Float2 mouse, MouseButton buttons, ref bool handled)
|
private void OnSurfaceMouseDoubleClick(ref Float2 mouse, MouseButton buttons, ref bool handled)
|
||||||
{
|
{
|
||||||
if (handled)
|
if (handled || Surface.Context != Context)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Check double click over the connection
|
// Check double click over the connection
|
||||||
|
|||||||
@@ -2,11 +2,8 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.Loader;
|
|
||||||
using System.Runtime.Serialization.Formatters.Binary;
|
|
||||||
using FlaxEditor.CustomEditors;
|
using FlaxEditor.CustomEditors;
|
||||||
using FlaxEditor.CustomEditors.Editors;
|
using FlaxEditor.CustomEditors.Editors;
|
||||||
using FlaxEditor.GUI.ContextMenu;
|
using FlaxEditor.GUI.ContextMenu;
|
||||||
@@ -18,6 +15,7 @@ namespace FlaxEditor.Surface
|
|||||||
class AttributesEditor : ContextMenuBase
|
class AttributesEditor : ContextMenuBase
|
||||||
{
|
{
|
||||||
private CustomEditorPresenter _presenter;
|
private CustomEditorPresenter _presenter;
|
||||||
|
private Proxy _proxy;
|
||||||
private byte[] _oldData;
|
private byte[] _oldData;
|
||||||
|
|
||||||
private class Proxy
|
private class Proxy
|
||||||
@@ -72,11 +70,11 @@ namespace FlaxEditor.Surface
|
|||||||
/// Initializes a new instance of the <see cref="AttributesEditor"/> class.
|
/// Initializes a new instance of the <see cref="AttributesEditor"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="attributes">The attributes list to edit.</param>
|
/// <param name="attributes">The attributes list to edit.</param>
|
||||||
/// <param name="attributeType">The allowed attribute types to use.</param>
|
/// <param name="attributeTypes">The allowed attribute types to use.</param>
|
||||||
public AttributesEditor(Attribute[] attributes, IList<Type> attributeType)
|
public AttributesEditor(Attribute[] attributes, IList<Type> attributeTypes)
|
||||||
{
|
{
|
||||||
// Context menu dimensions
|
// Context menu dimensions
|
||||||
const float width = 340.0f;
|
const float width = 375.0f;
|
||||||
const float height = 370.0f;
|
const float height = 370.0f;
|
||||||
Size = new Float2(width, height);
|
Size = new Float2(width, height);
|
||||||
|
|
||||||
@@ -88,61 +86,68 @@ namespace FlaxEditor.Surface
|
|||||||
Parent = this
|
Parent = this
|
||||||
};
|
};
|
||||||
|
|
||||||
// Buttons
|
// Ok and Cancel Buttons
|
||||||
float buttonsWidth = (width - 16.0f) * 0.5f;
|
float buttonsWidth = (width - 12.0f) * 0.5f;
|
||||||
float buttonsHeight = 20.0f;
|
float buttonsHeight = 20.0f;
|
||||||
var cancelButton = new Button(4.0f, title.Bottom + 4.0f, buttonsWidth, buttonsHeight)
|
var okButton = new Button(4.0f, Bottom - 4.0f - buttonsHeight, buttonsWidth, buttonsHeight)
|
||||||
|
{
|
||||||
|
Text = "Ok",
|
||||||
|
Parent = this
|
||||||
|
};
|
||||||
|
okButton.Clicked += OnOkButtonClicked;
|
||||||
|
var cancelButton = new Button(okButton.Right + 4.0f, okButton.Y, buttonsWidth, buttonsHeight)
|
||||||
{
|
{
|
||||||
Text = "Cancel",
|
Text = "Cancel",
|
||||||
Parent = this
|
Parent = this
|
||||||
};
|
};
|
||||||
cancelButton.Clicked += Hide;
|
cancelButton.Clicked += Hide;
|
||||||
var okButton = new Button(cancelButton.Right + 4.0f, cancelButton.Y, buttonsWidth, buttonsHeight)
|
|
||||||
{
|
|
||||||
Text = "OK",
|
|
||||||
Parent = this
|
|
||||||
};
|
|
||||||
okButton.Clicked += OnOkButtonClicked;
|
|
||||||
|
|
||||||
// Actual panel
|
// Actual panel used to display attributes
|
||||||
var panel1 = new Panel(ScrollBars.Vertical)
|
var panel1 = new Panel(ScrollBars.Vertical)
|
||||||
{
|
{
|
||||||
Bounds = new Rectangle(0, okButton.Bottom + 4.0f, width, height - okButton.Bottom - 2.0f),
|
Bounds = new Rectangle(0, title.Bottom + 4.0f, width, height - buttonsHeight - title.Height - 14.0f),
|
||||||
Parent = this
|
Parent = this
|
||||||
};
|
};
|
||||||
var editor = new CustomEditorPresenter(null);
|
var editor = new CustomEditorPresenter(null);
|
||||||
editor.Panel.AnchorPreset = AnchorPresets.HorizontalStretchTop;
|
editor.Panel.AnchorPreset = AnchorPresets.HorizontalStretchTop;
|
||||||
editor.Panel.IsScrollable = true;
|
editor.Panel.IsScrollable = true;
|
||||||
editor.Panel.Parent = panel1;
|
editor.Panel.Parent = panel1;
|
||||||
editor.Panel.Tag = attributeType;
|
editor.Panel.Tag = attributeTypes;
|
||||||
_presenter = editor;
|
_presenter = editor;
|
||||||
|
|
||||||
// Cache 'previous' state to check if attributes were edited after operation
|
// Cache 'previous' state to check if attributes were edited after operation
|
||||||
_oldData = SurfaceMeta.GetAttributesData(attributes);
|
_oldData = SurfaceMeta.GetAttributesData(attributes);
|
||||||
|
|
||||||
editor.Select(new Proxy
|
_proxy = new Proxy
|
||||||
{
|
{
|
||||||
Value = attributes,
|
Value = attributes,
|
||||||
});
|
};
|
||||||
|
editor.Select(_proxy);
|
||||||
|
|
||||||
|
_presenter.Modified += OnPresenterModified;
|
||||||
|
OnPresenterModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPresenterModified()
|
||||||
|
{
|
||||||
|
if (_proxy.Value.Length == 0)
|
||||||
|
{
|
||||||
|
var label = _presenter.Label("No attributes.\nPress the \"+\" button to add a new one and then select an attribute type using the \"Type\" dropdown.", TextAlignment.Center);
|
||||||
|
label.Label.Wrapping = TextWrapping.WrapWords;
|
||||||
|
label.Control.Height = 35f;
|
||||||
|
label.Label.Margin = new Margin(10f);
|
||||||
|
label.Label.TextColor = label.Label.TextColorHighlighted = Style.Current.ForegroundGrey;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnOkButtonClicked()
|
private void OnOkButtonClicked()
|
||||||
{
|
{
|
||||||
var newValue = ((Proxy)_presenter.Selection[0]).Value;
|
var newValue = ((Proxy)_presenter.Selection[0]).Value;
|
||||||
for (int i = 0; i < newValue.Length; i++)
|
newValue = newValue.Where(v => v != null).ToArray();
|
||||||
{
|
|
||||||
if (newValue[i] == null)
|
|
||||||
{
|
|
||||||
MessageBox.Show("One of the attributes is null. Please set it to the valid object.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var newData = SurfaceMeta.GetAttributesData(newValue);
|
var newData = SurfaceMeta.GetAttributesData(newValue);
|
||||||
if (!_oldData.SequenceEqual(newData))
|
if (!_oldData.SequenceEqual(newData))
|
||||||
{
|
|
||||||
Edited?.Invoke(newValue);
|
Edited?.Invoke(newValue);
|
||||||
}
|
|
||||||
|
|
||||||
Hide();
|
Hide();
|
||||||
}
|
}
|
||||||
@@ -183,7 +188,9 @@ namespace FlaxEditor.Surface
|
|||||||
{
|
{
|
||||||
_presenter = null;
|
_presenter = null;
|
||||||
_oldData = null;
|
_oldData = null;
|
||||||
|
_proxy = null;
|
||||||
Edited = null;
|
Edited = null;
|
||||||
|
_presenter.Modified -= OnPresenterModified;
|
||||||
|
|
||||||
base.OnDestroy();
|
base.OnDestroy();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -412,7 +412,7 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
{
|
{
|
||||||
group.UnlockChildrenRecursive();
|
group.UnlockChildrenRecursive();
|
||||||
// TODO: Improve filtering to be based on boxes with the most common things instead of first box
|
// TODO: Improve filtering to be based on boxes with the most common things instead of first box
|
||||||
if (_contextSensitiveSearchEnabled && _selectedBoxes[0] != null)
|
if (_contextSensitiveSearchEnabled && _selectedBoxes.Count > 0 && _selectedBoxes[0] != null)
|
||||||
UpdateFilters();
|
UpdateFilters();
|
||||||
else
|
else
|
||||||
SortGroups();
|
SortGroups();
|
||||||
@@ -424,7 +424,7 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
OnSearchFilterChanged();
|
OnSearchFilterChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (_contextSensitiveSearchEnabled)
|
else if (_contextSensitiveSearchEnabled && _selectedBoxes.Count > 0)
|
||||||
{
|
{
|
||||||
// TODO: Filtering could be improved here as well
|
// TODO: Filtering could be improved here as well
|
||||||
group.EvaluateVisibilityWithBox(_selectedBoxes[0]);
|
group.EvaluateVisibilityWithBox(_selectedBoxes[0]);
|
||||||
@@ -462,7 +462,7 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
Parent = group
|
Parent = group
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (_contextSensitiveSearchEnabled)
|
if (_contextSensitiveSearchEnabled && _selectedBoxes.Count > 0)
|
||||||
group.EvaluateVisibilityWithBox(_selectedBoxes[0]);
|
group.EvaluateVisibilityWithBox(_selectedBoxes[0]);
|
||||||
group.SortChildren();
|
group.SortChildren();
|
||||||
if (ShowExpanded)
|
if (ShowExpanded)
|
||||||
@@ -476,7 +476,7 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
|
|
||||||
if (!isLayoutLocked)
|
if (!isLayoutLocked)
|
||||||
{
|
{
|
||||||
if (_contextSensitiveSearchEnabled && _selectedBoxes[0] != null)
|
if (_contextSensitiveSearchEnabled && _selectedBoxes.Count != 0 && _selectedBoxes[0] != null)
|
||||||
UpdateFilters();
|
UpdateFilters();
|
||||||
else
|
else
|
||||||
SortGroups();
|
SortGroups();
|
||||||
|
|||||||
@@ -214,22 +214,25 @@ namespace FlaxEditor.Surface
|
|||||||
if (!_isRenaming)
|
if (!_isRenaming)
|
||||||
Render2D.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
|
Render2D.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
|
||||||
|
|
||||||
// Close button
|
if (Surface.CanEdit)
|
||||||
Render2D.DrawSprite(style.Cross, _closeButtonRect, _closeButtonRect.Contains(_mousePosition) && Surface.CanEdit ? style.Foreground : style.ForegroundGrey);
|
|
||||||
|
|
||||||
// Color button
|
|
||||||
Render2D.DrawSprite(style.Settings, _colorButtonRect, _colorButtonRect.Contains(_mousePosition) && Surface.CanEdit ? style.Foreground : style.ForegroundGrey);
|
|
||||||
|
|
||||||
// Check if is resizing
|
|
||||||
if (_isResizing)
|
|
||||||
{
|
{
|
||||||
// Draw overlay
|
// Close button
|
||||||
Render2D.FillRectangle(_resizeButtonRect, style.Selection);
|
Render2D.DrawSprite(style.Cross, _closeButtonRect, _closeButtonRect.Contains(_mousePosition) && Surface.CanEdit ? style.Foreground : style.ForegroundGrey);
|
||||||
Render2D.DrawRectangle(_resizeButtonRect, style.SelectionBorder);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resize button
|
// Color button
|
||||||
Render2D.DrawSprite(style.Scale, _resizeButtonRect, _resizeButtonRect.Contains(_mousePosition) && Surface.CanEdit ? style.Foreground : style.ForegroundGrey);
|
Render2D.DrawSprite(style.Settings, _colorButtonRect, _colorButtonRect.Contains(_mousePosition) && Surface.CanEdit ? style.Foreground : style.ForegroundGrey);
|
||||||
|
|
||||||
|
// Check if is resizing
|
||||||
|
if (_isResizing)
|
||||||
|
{
|
||||||
|
// Draw overlay
|
||||||
|
Render2D.FillRectangle(_resizeButtonRect, style.Selection);
|
||||||
|
Render2D.DrawRectangle(_resizeButtonRect, style.SelectionBorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resize button
|
||||||
|
Render2D.DrawSprite(style.Scale, _resizeButtonRect, _resizeButtonRect.Contains(_mousePosition) && Surface.CanEdit ? style.Foreground : style.ForegroundGrey);
|
||||||
|
}
|
||||||
|
|
||||||
// Selection outline
|
// Selection outline
|
||||||
if (_isSelected)
|
if (_isSelected)
|
||||||
|
|||||||
@@ -431,27 +431,6 @@ namespace FlaxEditor.Surface
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool HasIndependentBoxes => Archetype.IndependentBoxes != null;
|
public bool HasIndependentBoxes => Archetype.IndependentBoxes != null;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether this node has dependent boxes with assigned valid types. Otherwise any box has no dependent type assigned.
|
|
||||||
/// </summary>
|
|
||||||
public bool HasDependentBoxesSetup
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (Archetype.DependentBoxes == null || Archetype.IndependentBoxes == null)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
for (int i = 0; i < Archetype.DependentBoxes.Length; i++)
|
|
||||||
{
|
|
||||||
var b = GetBox(Archetype.DependentBoxes[i]);
|
|
||||||
if (b != null && b.CurrentType == b.DefaultType)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly List<SurfaceNode> UpdateStack = new List<SurfaceNode>();
|
private static readonly List<SurfaceNode> UpdateStack = new List<SurfaceNode>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -400,7 +400,7 @@ namespace FlaxEditor.Surface
|
|||||||
return scriptType.GetGenericTypeDefinition() == typeof(Dictionary<,>);
|
return scriptType.GetGenericTypeDefinition() == typeof(Dictionary<,>);
|
||||||
}
|
}
|
||||||
var managedType = TypeUtils.GetType(scriptType);
|
var managedType = TypeUtils.GetType(scriptType);
|
||||||
return !TypeUtils.IsDelegate(managedType);
|
return managedType != null && !TypeUtils.IsDelegate(managedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool IsValidVisualScriptFunctionType(ScriptType scriptType)
|
internal static bool IsValidVisualScriptFunctionType(ScriptType scriptType)
|
||||||
@@ -408,7 +408,7 @@ namespace FlaxEditor.Surface
|
|||||||
if (scriptType.IsGenericType || scriptType.IsStatic || !scriptType.IsPublic || scriptType.HasAttribute(typeof(HideInEditorAttribute), true))
|
if (scriptType.IsGenericType || scriptType.IsStatic || !scriptType.IsPublic || scriptType.HasAttribute(typeof(HideInEditorAttribute), true))
|
||||||
return false;
|
return false;
|
||||||
var managedType = TypeUtils.GetType(scriptType);
|
var managedType = TypeUtils.GetType(scriptType);
|
||||||
return !TypeUtils.IsDelegate(managedType);
|
return managedType != null && !TypeUtils.IsDelegate(managedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string GetVisualScriptTypeDescription(ScriptType type)
|
internal static string GetVisualScriptTypeDescription(ScriptType type)
|
||||||
|
|||||||
@@ -469,7 +469,8 @@ namespace FlaxEditor.Surface
|
|||||||
bool handled = base.OnMouseDown(location, button);
|
bool handled = base.OnMouseDown(location, button);
|
||||||
if (!handled)
|
if (!handled)
|
||||||
CustomMouseDown?.Invoke(ref location, button, ref handled);
|
CustomMouseDown?.Invoke(ref location, button, ref handled);
|
||||||
if (handled)
|
var root = Root;
|
||||||
|
if (handled || root == null)
|
||||||
{
|
{
|
||||||
// Clear flags
|
// Clear flags
|
||||||
_isMovingSelection = false;
|
_isMovingSelection = false;
|
||||||
@@ -523,11 +524,11 @@ namespace FlaxEditor.Surface
|
|||||||
if (_leftMouseDown && controlUnderMouse.CanSelect(ref cLocation))
|
if (_leftMouseDown && controlUnderMouse.CanSelect(ref cLocation))
|
||||||
{
|
{
|
||||||
// Check if user is pressing control
|
// Check if user is pressing control
|
||||||
if (Root.GetKey(KeyboardKeys.Control))
|
if (root.GetKey(KeyboardKeys.Control))
|
||||||
{
|
{
|
||||||
AddToSelection(controlUnderMouse);
|
AddToSelection(controlUnderMouse);
|
||||||
}
|
}
|
||||||
else if (Root.GetKey(KeyboardKeys.Shift))
|
else if (root.GetKey(KeyboardKeys.Shift))
|
||||||
{
|
{
|
||||||
RemoveFromSelection(controlUnderMouse);
|
RemoveFromSelection(controlUnderMouse);
|
||||||
}
|
}
|
||||||
@@ -539,7 +540,7 @@ namespace FlaxEditor.Surface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start moving selected nodes
|
// Start moving selected nodes
|
||||||
if (!Root.GetKey(KeyboardKeys.Shift))
|
if (!root.GetKey(KeyboardKeys.Shift))
|
||||||
{
|
{
|
||||||
StartMouseCapture();
|
StartMouseCapture();
|
||||||
_movingSelectionViewPos = _rootControl.Location;
|
_movingSelectionViewPos = _rootControl.Location;
|
||||||
@@ -559,7 +560,7 @@ namespace FlaxEditor.Surface
|
|||||||
// Start selecting or commenting
|
// Start selecting or commenting
|
||||||
StartMouseCapture();
|
StartMouseCapture();
|
||||||
|
|
||||||
if (!Root.GetKey(KeyboardKeys.Control) && !Root.GetKey(KeyboardKeys.Shift))
|
if (!root.GetKey(KeyboardKeys.Control) && !root.GetKey(KeyboardKeys.Shift))
|
||||||
{
|
{
|
||||||
ClearSelection();
|
ClearSelection();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,19 +178,31 @@ namespace FlaxEditor.Surface
|
|||||||
|
|
||||||
// Update boxes types for nodes that dependant box types based on incoming connections
|
// Update boxes types for nodes that dependant box types based on incoming connections
|
||||||
{
|
{
|
||||||
bool keepUpdating = false;
|
bool keepUpdating = true;
|
||||||
int updateLimit = 100;
|
int updatesMin = 2, updatesMax = 100;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
keepUpdating = false;
|
||||||
for (int i = 0; i < RootControl.Children.Count; i++)
|
for (int i = 0; i < RootControl.Children.Count; i++)
|
||||||
{
|
{
|
||||||
if (RootControl.Children[i] is SurfaceNode node && !node.HasDependentBoxesSetup)
|
if (RootControl.Children[i] is SurfaceNode node)
|
||||||
{
|
{
|
||||||
node.UpdateBoxesTypes();
|
node.UpdateBoxesTypes();
|
||||||
keepUpdating = true;
|
var arch = node.Archetype;
|
||||||
|
if (arch.DependentBoxes != null && arch.IndependentBoxes != null)
|
||||||
|
{
|
||||||
|
foreach (var boxId in arch.DependentBoxes)
|
||||||
|
{
|
||||||
|
var b = node.GetBox(boxId);
|
||||||
|
if (b != null && b.CurrentType == b.DefaultType)
|
||||||
|
{
|
||||||
|
keepUpdating = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (keepUpdating && updateLimit-- > 0);
|
} while ((keepUpdating && --updatesMax > 0) || --updatesMin > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Loaded?.Invoke(this);
|
Loaded?.Invoke(this);
|
||||||
|
|||||||
@@ -74,11 +74,6 @@ struct TextureDataResult
|
|||||||
PixelFormat Format;
|
PixelFormat Format;
|
||||||
Int2 Mip0Size;
|
Int2 Mip0Size;
|
||||||
BytesContainer* Mip0DataPtr;
|
BytesContainer* Mip0DataPtr;
|
||||||
|
|
||||||
TextureDataResult()
|
|
||||||
: Lock(FlaxStorage::LockData::Invalid)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool GetTextureDataForSampling(Texture* texture, TextureDataResult& data, bool hdr = false)
|
bool GetTextureDataForSampling(Texture* texture, TextureDataResult& data, bool hdr = false)
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ namespace FlaxEditor.Viewport
|
|||||||
private PrefabUIEditorRoot _uiRoot;
|
private PrefabUIEditorRoot _uiRoot;
|
||||||
private bool _showUI = false;
|
private bool _showUI = false;
|
||||||
|
|
||||||
private int _defaultScaleActiveIndex = 0;
|
private int _defaultScaleActiveIndex = -1;
|
||||||
private int _customScaleActiveIndex = -1;
|
private int _customScaleActiveIndex = -1;
|
||||||
private ContextMenuButton _uiModeButton;
|
private ContextMenuButton _uiModeButton;
|
||||||
private ContextMenuChildMenu _uiViewOptions;
|
private ContextMenuChildMenu _uiViewOptions;
|
||||||
@@ -257,16 +257,23 @@ namespace FlaxEditor.Viewport
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void SaveActiveUIScalingOption()
|
public void SaveActiveUIScalingOption()
|
||||||
{
|
{
|
||||||
var defaultKey = $"{Prefab.ID}:DefaultViewportScalingIndex";
|
if (!Prefab)
|
||||||
|
return;
|
||||||
|
var id = Prefab.ID;
|
||||||
|
var defaultKey = $"{id}:DefaultViewportScalingIndex";
|
||||||
Editor.Instance.ProjectCache.SetCustomData(defaultKey, _defaultScaleActiveIndex.ToString());
|
Editor.Instance.ProjectCache.SetCustomData(defaultKey, _defaultScaleActiveIndex.ToString());
|
||||||
var customKey = $"{Prefab.ID}:CustomViewportScalingIndex";
|
var customKey = $"{id}:CustomViewportScalingIndex";
|
||||||
Editor.Instance.ProjectCache.SetCustomData(customKey, _customScaleActiveIndex.ToString());
|
Editor.Instance.ProjectCache.SetCustomData(customKey, _customScaleActiveIndex.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadCustomUIScalingOption()
|
private void LoadCustomUIScalingOption()
|
||||||
{
|
{
|
||||||
|
if (!Prefab)
|
||||||
|
return;
|
||||||
|
var id = Prefab.ID;
|
||||||
Prefab.WaitForLoaded();
|
Prefab.WaitForLoaded();
|
||||||
var defaultKey = $"{Prefab.ID}:DefaultViewportScalingIndex";
|
|
||||||
|
var defaultKey = $"{id}:DefaultViewportScalingIndex";
|
||||||
if (Editor.Instance.ProjectCache.TryGetCustomData(defaultKey, out string defaultData))
|
if (Editor.Instance.ProjectCache.TryGetCustomData(defaultKey, out string defaultData))
|
||||||
{
|
{
|
||||||
if (int.TryParse(defaultData, out var index))
|
if (int.TryParse(defaultData, out var index))
|
||||||
@@ -286,7 +293,7 @@ namespace FlaxEditor.Viewport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var customKey = $"{Prefab.ID}:CustomViewportScalingIndex";
|
var customKey = $"{id}:CustomViewportScalingIndex";
|
||||||
if (Editor.Instance.ProjectCache.TryGetCustomData(customKey, out string data))
|
if (Editor.Instance.ProjectCache.TryGetCustomData(customKey, out string data))
|
||||||
{
|
{
|
||||||
if (int.TryParse(data, out var index))
|
if (int.TryParse(data, out var index))
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ namespace FlaxEditor.Windows
|
|||||||
}
|
}
|
||||||
|
|
||||||
private string _cacheFolder;
|
private string _cacheFolder;
|
||||||
private Guid _assetId;
|
private AssetItem _item;
|
||||||
private Surface _surface;
|
private Surface _surface;
|
||||||
private Label _loadingLabel;
|
private Label _loadingLabel;
|
||||||
private CancellationTokenSource _token;
|
private CancellationTokenSource _token;
|
||||||
@@ -163,13 +163,13 @@ namespace FlaxEditor.Windows
|
|||||||
public AssetReferencesGraphWindow(Editor editor, AssetItem assetItem)
|
public AssetReferencesGraphWindow(Editor editor, AssetItem assetItem)
|
||||||
: base(editor, false, ScrollBars.None)
|
: base(editor, false, ScrollBars.None)
|
||||||
{
|
{
|
||||||
Title = assetItem.ShortName + " References";
|
_item = assetItem;
|
||||||
|
Title = _item.ShortName + " References";
|
||||||
|
|
||||||
_tempFolder = StringUtils.NormalizePath(Path.GetDirectoryName(Globals.TemporaryFolder));
|
_tempFolder = StringUtils.NormalizePath(Path.GetDirectoryName(Globals.TemporaryFolder));
|
||||||
_cacheFolder = Path.Combine(Globals.ProjectCacheFolder, "References");
|
_cacheFolder = Path.Combine(Globals.ProjectCacheFolder, "References");
|
||||||
if (!Directory.Exists(_cacheFolder))
|
if (!Directory.Exists(_cacheFolder))
|
||||||
Directory.CreateDirectory(_cacheFolder);
|
Directory.CreateDirectory(_cacheFolder);
|
||||||
_assetId = assetItem.ID;
|
|
||||||
_surface = new Surface(this)
|
_surface = new Surface(this)
|
||||||
{
|
{
|
||||||
AnchorPreset = AnchorPresets.StretchAll,
|
AnchorPreset = AnchorPresets.StretchAll,
|
||||||
@@ -194,6 +194,7 @@ namespace FlaxEditor.Windows
|
|||||||
_nodesAssets.Add(assetId);
|
_nodesAssets.Add(assetId);
|
||||||
var node = new AssetNode((uint)_nodes.Count + 1, _surface.Context, GraphNodes[0], GraphGroups[0], assetId);
|
var node = new AssetNode((uint)_nodes.Count + 1, _surface.Context, GraphNodes[0], GraphGroups[0], assetId);
|
||||||
_nodes.Add(node);
|
_nodes.Add(node);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,8 +393,7 @@ namespace FlaxEditor.Windows
|
|||||||
_nodesAssets = new HashSet<Guid>();
|
_nodesAssets = new HashSet<Guid>();
|
||||||
var searchLevel = 4; // TODO: make it as an option (somewhere in window UI)
|
var searchLevel = 4; // TODO: make it as an option (somewhere in window UI)
|
||||||
// TODO: add option to filter assets by type (eg. show only textures as leaf nodes)
|
// TODO: add option to filter assets by type (eg. show only textures as leaf nodes)
|
||||||
var assetNode = SpawnNode(_assetId);
|
var assetNode = SpawnNode(_item.ID);
|
||||||
// TODO: add some outline or tint color to the main node
|
|
||||||
BuildGraph(assetNode, searchLevel, false);
|
BuildGraph(assetNode, searchLevel, false);
|
||||||
ArrangeGraph(assetNode, false);
|
ArrangeGraph(assetNode, false);
|
||||||
BuildGraph(assetNode, searchLevel, true);
|
BuildGraph(assetNode, searchLevel, true);
|
||||||
@@ -402,6 +402,10 @@ namespace FlaxEditor.Windows
|
|||||||
return;
|
return;
|
||||||
_progress = 100.0f;
|
_progress = 100.0f;
|
||||||
|
|
||||||
|
var commentRect = assetNode.EditorBounds;
|
||||||
|
commentRect.Expand(80f);
|
||||||
|
_surface.Context.CreateComment(ref commentRect, _item.ShortName, Color.Green);
|
||||||
|
|
||||||
// Update UI
|
// Update UI
|
||||||
FlaxEngine.Scripting.InvokeOnUpdate(() =>
|
FlaxEngine.Scripting.InvokeOnUpdate(() =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ using FlaxEditor.Surface;
|
|||||||
using FlaxEditor.Viewport.Previews;
|
using FlaxEditor.Viewport.Previews;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
using FlaxEngine.Utilities;
|
|
||||||
|
|
||||||
namespace FlaxEditor.Windows.Assets
|
namespace FlaxEditor.Windows.Assets
|
||||||
{
|
{
|
||||||
@@ -430,7 +429,7 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
for (var i = 0; i < parameters.Length; i++)
|
for (var i = 0; i < parameters.Length; i++)
|
||||||
{
|
{
|
||||||
var p = parameters[i];
|
var p = parameters[i];
|
||||||
if (p.IsOverride)
|
if (p.IsOverride && p.IsPublic)
|
||||||
{
|
{
|
||||||
p.IsOverride = false;
|
p.IsOverride = false;
|
||||||
actions.Add(new EditParamOverrideAction
|
actions.Add(new EditParamOverrideAction
|
||||||
|
|||||||
@@ -90,25 +90,15 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
|
|
||||||
var gpu = group.Checkbox("Bake on GPU", "If checked, SDF generation will be calculated using GPU on Compute Shader, otherwise CPU will use Job System. GPU generation is fast but result in artifacts in various meshes (eg. foliage).");
|
var gpu = group.Checkbox("Bake on GPU", "If checked, SDF generation will be calculated using GPU on Compute Shader, otherwise CPU will use Job System. GPU generation is fast but result in artifacts in various meshes (eg. foliage).");
|
||||||
gpu.CheckBox.Checked = sdfOptions.GPU;
|
gpu.CheckBox.Checked = sdfOptions.GPU;
|
||||||
|
gpu.CheckBox.StateChanged += c => { Window._sdfOptions.GPU = c.Checked; };
|
||||||
|
|
||||||
var backfacesThresholdProp = group.AddPropertyItem("Backfaces Threshold", "Custom threshold (in range 0-1) for adjusting mesh internals detection based on the percentage of test rays hit triangle backfaces. Use lower value for more dense mesh.");
|
var backfacesThresholdProp = group.AddPropertyItem("Backfaces Threshold", "Custom threshold (in range 0-1) for adjusting mesh internals detection based on the percentage of test rays hit triangle backfaces. Use lower value for more dense mesh.");
|
||||||
var backfacesThreshold = backfacesThresholdProp.FloatValue();
|
var backfacesThreshold = backfacesThresholdProp.FloatValue();
|
||||||
var backfacesThresholdLabel = backfacesThresholdProp.Labels.Last();
|
|
||||||
backfacesThreshold.ValueBox.MinValue = 0.001f;
|
backfacesThreshold.ValueBox.MinValue = 0.001f;
|
||||||
backfacesThreshold.ValueBox.MaxValue = 1.0f;
|
backfacesThreshold.ValueBox.MaxValue = 1.0f;
|
||||||
backfacesThreshold.ValueBox.Value = sdfOptions.BackfacesThreshold;
|
backfacesThreshold.ValueBox.Value = sdfOptions.BackfacesThreshold;
|
||||||
backfacesThreshold.ValueBox.BoxValueChanged += b => { Window._sdfOptions.BackfacesThreshold = b.Value; };
|
backfacesThreshold.ValueBox.BoxValueChanged += b => { Window._sdfOptions.BackfacesThreshold = b.Value; };
|
||||||
|
|
||||||
// Toggle Backfaces Threshold visibility (CPU-only option)
|
|
||||||
gpu.CheckBox.StateChanged += c =>
|
|
||||||
{
|
|
||||||
Window._sdfOptions.GPU = c.Checked;
|
|
||||||
backfacesThresholdLabel.Visible = !c.Checked;
|
|
||||||
backfacesThreshold.ValueBox.Visible = !c.Checked;
|
|
||||||
};
|
|
||||||
backfacesThresholdLabel.Visible = !gpu.CheckBox.Checked;
|
|
||||||
backfacesThreshold.ValueBox.Visible = !gpu.CheckBox.Checked;
|
|
||||||
|
|
||||||
var lodIndex = group.IntegerValue("LOD Index", "Index of the model Level of Detail to use for SDF data building. By default uses the lowest quality LOD for fast building.");
|
var lodIndex = group.IntegerValue("LOD Index", "Index of the model Level of Detail to use for SDF data building. By default uses the lowest quality LOD for fast building.");
|
||||||
lodIndex.IntValue.MinValue = 0;
|
lodIndex.IntValue.MinValue = 0;
|
||||||
lodIndex.IntValue.MaxValue = Asset.LODsCount - 1;
|
lodIndex.IntValue.MaxValue = Asset.LODsCount - 1;
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ namespace FlaxEditor.Windows
|
|||||||
{
|
{
|
||||||
Title = "Content";
|
Title = "Content";
|
||||||
Icon = editor.Icons.Folder32;
|
Icon = editor.Icons.Folder32;
|
||||||
|
var style = Style.Current;
|
||||||
|
|
||||||
FlaxEditor.Utilities.Utils.SetupCommonInputActions(this);
|
FlaxEditor.Utilities.Utils.SetupCommonInputActions(this);
|
||||||
|
|
||||||
@@ -164,6 +165,8 @@ namespace FlaxEditor.Windows
|
|||||||
_navigationBar = new NavigationBar
|
_navigationBar = new NavigationBar
|
||||||
{
|
{
|
||||||
Parent = _toolStrip,
|
Parent = _toolStrip,
|
||||||
|
ScrollbarTrackColor = style.Background,
|
||||||
|
ScrollbarThumbColor = style.ForegroundGrey,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Split panel
|
// Split panel
|
||||||
@@ -179,7 +182,7 @@ namespace FlaxEditor.Windows
|
|||||||
var headerPanel = new ContainerControl
|
var headerPanel = new ContainerControl
|
||||||
{
|
{
|
||||||
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
||||||
BackgroundColor = Style.Current.Background,
|
BackgroundColor = style.Background,
|
||||||
IsScrollable = false,
|
IsScrollable = false,
|
||||||
Offsets = new Margin(0, 0, 0, 18 + 6),
|
Offsets = new Margin(0, 0, 0, 18 + 6),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,17 +10,117 @@ using FlaxEditor.Modules;
|
|||||||
using FlaxEditor.Options;
|
using FlaxEditor.Options;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
using FlaxEngine.Json;
|
|
||||||
|
|
||||||
namespace FlaxEditor.Windows
|
namespace FlaxEditor.Windows
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Render output control with content scaling support.
|
||||||
|
/// </summary>
|
||||||
|
public class ScaledRenderOutputControl : RenderOutputControl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Custom scale.
|
||||||
|
/// </summary>
|
||||||
|
public float ContentScale = 1.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Actual bounds size for content (incl. scale).
|
||||||
|
/// </summary>
|
||||||
|
public Float2 ContentSize => Size / ContentScale;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ScaledRenderOutputControl(SceneRenderTask task)
|
||||||
|
: base(task)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void Draw()
|
||||||
|
{
|
||||||
|
DrawSelf();
|
||||||
|
|
||||||
|
// Draw children with scale
|
||||||
|
var scaling = new Float3(ContentScale, ContentScale, 1);
|
||||||
|
Matrix3x3.Scaling(ref scaling, out Matrix3x3 scale);
|
||||||
|
Render2D.PushTransform(scale);
|
||||||
|
if (ClipChildren)
|
||||||
|
{
|
||||||
|
GetDesireClientArea(out var clientArea);
|
||||||
|
Render2D.PushClip(ref clientArea);
|
||||||
|
DrawChildren();
|
||||||
|
Render2D.PopClip();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
Render2D.PopTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void GetDesireClientArea(out Rectangle rect)
|
||||||
|
{
|
||||||
|
// Scale the area for the client controls
|
||||||
|
rect = new Rectangle(Float2.Zero, Size / ContentScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool IntersectsContent(ref Float2 locationParent, out Float2 location)
|
||||||
|
{
|
||||||
|
// Skip local PointFromParent but use base code
|
||||||
|
location = base.PointFromParent(ref locationParent);
|
||||||
|
return ContainsPoint(ref location);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool IntersectsChildContent(Control child, Float2 location, out Float2 childSpaceLocation)
|
||||||
|
{
|
||||||
|
location /= ContentScale;
|
||||||
|
return base.IntersectsChildContent(child, location, out childSpaceLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool ContainsPoint(ref Float2 location, bool precise = false)
|
||||||
|
{
|
||||||
|
if (precise) // Ignore as utility-only element
|
||||||
|
return false;
|
||||||
|
return base.ContainsPoint(ref location, precise);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool RayCast(ref Float2 location, out Control hit)
|
||||||
|
{
|
||||||
|
var p = location / ContentScale;
|
||||||
|
if (RayCastChildren(ref p, out hit))
|
||||||
|
return true;
|
||||||
|
return base.RayCast(ref location, out hit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Float2 PointToParent(ref Float2 location)
|
||||||
|
{
|
||||||
|
var result = base.PointToParent(ref location);
|
||||||
|
result *= ContentScale;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Float2 PointFromParent(ref Float2 location)
|
||||||
|
{
|
||||||
|
var result = base.PointFromParent(ref location);
|
||||||
|
result /= ContentScale;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides in-editor play mode simulation.
|
/// Provides in-editor play mode simulation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Windows.EditorWindow" />
|
/// <seealso cref="FlaxEditor.Windows.EditorWindow" />
|
||||||
public class GameWindow : EditorWindow
|
public class GameWindow : EditorWindow
|
||||||
{
|
{
|
||||||
private readonly RenderOutputControl _viewport;
|
private readonly ScaledRenderOutputControl _viewport;
|
||||||
private readonly GameRoot _guiRoot;
|
private readonly GameRoot _guiRoot;
|
||||||
private bool _showGUI = true, _editGUI = true;
|
private bool _showGUI = true, _editGUI = true;
|
||||||
private bool _showDebugDraw = false;
|
private bool _showDebugDraw = false;
|
||||||
@@ -77,7 +177,7 @@ namespace FlaxEditor.Windows
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the viewport.
|
/// Gets the viewport.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public RenderOutputControl Viewport => _viewport;
|
public ScaledRenderOutputControl Viewport => _viewport;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether show game GUI in the view or keep it hidden.
|
/// Gets or sets a value indicating whether show game GUI in the view or keep it hidden.
|
||||||
@@ -295,7 +395,7 @@ namespace FlaxEditor.Windows
|
|||||||
var task = MainRenderTask.Instance;
|
var task = MainRenderTask.Instance;
|
||||||
|
|
||||||
// Setup viewport
|
// Setup viewport
|
||||||
_viewport = new RenderOutputControl(task)
|
_viewport = new ScaledRenderOutputControl(task)
|
||||||
{
|
{
|
||||||
AnchorPreset = AnchorPresets.StretchAll,
|
AnchorPreset = AnchorPresets.StretchAll,
|
||||||
Offsets = Margin.Zero,
|
Offsets = Margin.Zero,
|
||||||
@@ -396,11 +496,8 @@ namespace FlaxEditor.Windows
|
|||||||
{
|
{
|
||||||
if (v == null)
|
if (v == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (v.Size.Y <= 0 || v.Size.X <= 0)
|
if (v.Size.Y <= 0 || v.Size.X <= 0)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(v.Label, "Free Aspect", StringComparison.Ordinal) && v.Size == new Int2(1, 1))
|
if (string.Equals(v.Label, "Free Aspect", StringComparison.Ordinal) && v.Size == new Int2(1, 1))
|
||||||
{
|
{
|
||||||
@@ -448,15 +545,7 @@ namespace FlaxEditor.Windows
|
|||||||
|
|
||||||
private void ResizeViewport()
|
private void ResizeViewport()
|
||||||
{
|
{
|
||||||
if (!_freeAspect)
|
_windowAspectRatio = _freeAspect ? 1 : Width / Height;
|
||||||
{
|
|
||||||
_windowAspectRatio = Width / Height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_windowAspectRatio = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var scaleWidth = _viewportAspectRatio / _windowAspectRatio;
|
var scaleWidth = _viewportAspectRatio / _windowAspectRatio;
|
||||||
var scaleHeight = _windowAspectRatio / _viewportAspectRatio;
|
var scaleHeight = _windowAspectRatio / _viewportAspectRatio;
|
||||||
|
|
||||||
@@ -468,6 +557,24 @@ namespace FlaxEditor.Windows
|
|||||||
{
|
{
|
||||||
_viewport.Bounds = new Rectangle(Width * (1 - scaleWidth) / 2, 0, Width * scaleWidth, Height);
|
_viewport.Bounds = new Rectangle(Width * (1 - scaleWidth) / 2, 0, Width * scaleWidth, Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_viewport.KeepAspectRatio)
|
||||||
|
{
|
||||||
|
var resolution = _viewport.CustomResolution.HasValue ? (Float2)_viewport.CustomResolution.Value : Size;
|
||||||
|
if (scaleHeight < 1)
|
||||||
|
{
|
||||||
|
_viewport.ContentScale = _viewport.Width / resolution.X;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_viewport.ContentScale = _viewport.Height / resolution.Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_viewport.ContentScale = 1;
|
||||||
|
}
|
||||||
|
|
||||||
_viewport.SyncBackbufferSize();
|
_viewport.SyncBackbufferSize();
|
||||||
PerformLayout();
|
PerformLayout();
|
||||||
}
|
}
|
||||||
@@ -885,12 +992,12 @@ namespace FlaxEditor.Windows
|
|||||||
// Restore cursor visibility (could be hidden by the game)
|
// Restore cursor visibility (could be hidden by the game)
|
||||||
if (!_cursorVisible)
|
if (!_cursorVisible)
|
||||||
Screen.CursorVisible = true;
|
Screen.CursorVisible = true;
|
||||||
}
|
|
||||||
|
|
||||||
if (Editor.IsPlayMode && IsDocked && IsSelected && RootWindow.FocusedControl == null)
|
if (Editor.IsPlayMode && IsDocked && IsSelected && RootWindow.FocusedControl == null)
|
||||||
{
|
{
|
||||||
// Game UI cleared focus so regain it to maintain UI navigation just like game window does
|
// Game UI cleared focus so regain it to maintain UI navigation just like game window does
|
||||||
FlaxEngine.Scripting.InvokeOnUpdate(Focus);
|
FlaxEngine.Scripting.InvokeOnUpdate(Focus);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -907,6 +1014,7 @@ namespace FlaxEditor.Windows
|
|||||||
return child.OnNavigate(direction, Float2.Zero, this, visited);
|
return child.OnNavigate(direction, Float2.Zero, this, visited);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -957,7 +1065,7 @@ namespace FlaxEditor.Windows
|
|||||||
else
|
else
|
||||||
_defaultScaleActiveIndex = 0;
|
_defaultScaleActiveIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_customScaleActiveIndex != -1)
|
if (_customScaleActiveIndex != -1)
|
||||||
{
|
{
|
||||||
var options = Editor.UI.CustomViewportScaleOptions;
|
var options = Editor.UI.CustomViewportScaleOptions;
|
||||||
|
|||||||
@@ -296,13 +296,15 @@ namespace FlaxEditor.Windows.Profiler
|
|||||||
var resources = _resources.Get(_memoryUsageChart.SelectedSampleIndex);
|
var resources = _resources.Get(_memoryUsageChart.SelectedSampleIndex);
|
||||||
if (resources == null || resources.Length == 0)
|
if (resources == null || resources.Length == 0)
|
||||||
return;
|
return;
|
||||||
var resourcesOrdered = resources.OrderByDescending(x => x.MemoryUsage);
|
var resourcesOrdered = resources.OrderByDescending(x => x?.MemoryUsage ?? 0);
|
||||||
|
|
||||||
// Add rows
|
// Add rows
|
||||||
var rowColor2 = Style.Current.Background * 1.4f;
|
var rowColor2 = Style.Current.Background * 1.4f;
|
||||||
int rowIndex = 0;
|
int rowIndex = 0;
|
||||||
foreach (var e in resourcesOrdered)
|
foreach (var e in resourcesOrdered)
|
||||||
{
|
{
|
||||||
|
if (e == null)
|
||||||
|
continue;
|
||||||
ClickableRow row;
|
ClickableRow row;
|
||||||
if (_tableRowsCache.Count != 0)
|
if (_tableRowsCache.Count != 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -319,22 +319,22 @@ namespace FlaxEditor.Windows
|
|||||||
{
|
{
|
||||||
if (assetItem.IsOfType<SceneAsset>())
|
if (assetItem.IsOfType<SceneAsset>())
|
||||||
return true;
|
return true;
|
||||||
return assetItem.OnEditorDrag(this);
|
return assetItem.OnEditorDrag(this) && Level.IsAnySceneLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ValidateDragActorType(ScriptType actorType)
|
private static bool ValidateDragActorType(ScriptType actorType)
|
||||||
{
|
{
|
||||||
return Editor.Instance.CodeEditing.Actors.Get().Contains(actorType);
|
return Editor.Instance.CodeEditing.Actors.Get().Contains(actorType) && Level.IsAnySceneLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ValidateDragControlType(ScriptType controlType)
|
private static bool ValidateDragControlType(ScriptType controlType)
|
||||||
{
|
{
|
||||||
return Editor.Instance.CodeEditing.Controls.Get().Contains(controlType);
|
return Editor.Instance.CodeEditing.Controls.Get().Contains(controlType) && Level.IsAnySceneLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ValidateDragScriptItem(ScriptItem script)
|
private static bool ValidateDragScriptItem(ScriptItem script)
|
||||||
{
|
{
|
||||||
return Editor.Instance.CodeEditing.Actors.Get(script) != ScriptType.Null;
|
return Editor.Instance.CodeEditing.Actors.Get(script) != ScriptType.Null && Level.IsAnySceneLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -490,6 +490,7 @@ namespace FlaxEditor.Windows
|
|||||||
if (result == DragDropEffect.None)
|
if (result == DragDropEffect.None)
|
||||||
{
|
{
|
||||||
_isDropping = true;
|
_isDropping = true;
|
||||||
|
|
||||||
// Drag assets
|
// Drag assets
|
||||||
if (_dragAssets != null && _dragAssets.HasValidDrag)
|
if (_dragAssets != null && _dragAssets.HasValidDrag)
|
||||||
{
|
{
|
||||||
@@ -504,7 +505,7 @@ namespace FlaxEditor.Windows
|
|||||||
}
|
}
|
||||||
var actor = item.OnEditorDrop(this);
|
var actor = item.OnEditorDrop(this);
|
||||||
actor.Name = item.ShortName;
|
actor.Name = item.ShortName;
|
||||||
Level.SpawnActor(actor);
|
Editor.SceneEditing.Spawn(actor);
|
||||||
var graphNode = Editor.Scene.GetActorNode(actor.ID);
|
var graphNode = Editor.Scene.GetActorNode(actor.ID);
|
||||||
if (graphNode != null)
|
if (graphNode != null)
|
||||||
graphNodes.Add(graphNode);
|
graphNodes.Add(graphNode);
|
||||||
@@ -527,7 +528,7 @@ namespace FlaxEditor.Windows
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
actor.Name = item.Name;
|
actor.Name = item.Name;
|
||||||
Level.SpawnActor(actor);
|
Editor.SceneEditing.Spawn(actor);
|
||||||
Editor.Scene.MarkSceneEdited(actor.Scene);
|
Editor.Scene.MarkSceneEdited(actor.Scene);
|
||||||
}
|
}
|
||||||
result = DragDropEffect.Move;
|
result = DragDropEffect.Move;
|
||||||
@@ -549,7 +550,7 @@ namespace FlaxEditor.Windows
|
|||||||
Control = control,
|
Control = control,
|
||||||
Name = item.Name,
|
Name = item.Name,
|
||||||
};
|
};
|
||||||
Level.SpawnActor(uiControl);
|
Editor.SceneEditing.Spawn(uiControl);
|
||||||
Editor.Scene.MarkSceneEdited(uiControl.Scene);
|
Editor.Scene.MarkSceneEdited(uiControl.Scene);
|
||||||
}
|
}
|
||||||
result = DragDropEffect.Move;
|
result = DragDropEffect.Move;
|
||||||
@@ -571,7 +572,7 @@ namespace FlaxEditor.Windows
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
actor.Name = actorType.Name;
|
actor.Name = actorType.Name;
|
||||||
Level.SpawnActor(actor);
|
Editor.SceneEditing.Spawn(actor);
|
||||||
var graphNode = Editor.Scene.GetActorNode(actor.ID);
|
var graphNode = Editor.Scene.GetActorNode(actor.ID);
|
||||||
if (graphNode != null)
|
if (graphNode != null)
|
||||||
graphNodes.Add(graphNode);
|
graphNodes.Add(graphNode);
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ const Char* SplashScreenQuotes[] =
|
|||||||
TEXT("Good Luck Have Fun"),
|
TEXT("Good Luck Have Fun"),
|
||||||
TEXT("GG Well Played"),
|
TEXT("GG Well Played"),
|
||||||
TEXT("Now with documentation."),
|
TEXT("Now with documentation."),
|
||||||
|
TEXT("We do this not because it is easy,\nbut because we thought it would be easy"),
|
||||||
};
|
};
|
||||||
|
|
||||||
SplashScreen::~SplashScreen()
|
SplashScreen::~SplashScreen()
|
||||||
|
|||||||
@@ -246,11 +246,19 @@ void AnimGraphExecutor::ProcessAnimEvents(AnimGraphNode* node, bool loop, float
|
|||||||
const float duration = k.Value.Duration > 1 ? k.Value.Duration : 0.0f;
|
const float duration = k.Value.Duration > 1 ? k.Value.Duration : 0.0f;
|
||||||
#define ADD_OUTGOING_EVENT(type) context.Data->OutgoingEvents.Add({ k.Value.Instance, (AnimatedModel*)context.Data->Object, anim, eventTime, eventDeltaTime, AnimGraphInstanceData::OutgoingEvent::type })
|
#define ADD_OUTGOING_EVENT(type) context.Data->OutgoingEvents.Add({ k.Value.Instance, (AnimatedModel*)context.Data->Object, anim, eventTime, eventDeltaTime, AnimGraphInstanceData::OutgoingEvent::type })
|
||||||
if ((k.Time <= eventTimeMax && eventTimeMin <= k.Time + duration
|
if ((k.Time <= eventTimeMax && eventTimeMin <= k.Time + duration
|
||||||
&& (Math::FloorToInt(animPos) != 0 && Math::CeilToInt(animPrevPos) != Math::CeilToInt(anim->GetDuration()) && Math::FloorToInt(animPrevPos) != 0 && Math::CeilToInt(animPos) != Math::CeilToInt(anim->GetDuration())))
|
&& (Math::FloorToInt(animPos) != 0 && Math::CeilToInt(animPrevPos) != Math::CeilToInt(anim->GetDuration())
|
||||||
|
&& Math::FloorToInt(animPrevPos) != 0 && Math::CeilToInt(animPos) != Math::CeilToInt(anim->GetDuration())))
|
||||||
// Handle the edge case of an event on 0 or on max animation duration during looping
|
// Handle the edge case of an event on 0 or on max animation duration during looping
|
||||||
|| (loop && duration == 0.0f && Math::CeilToInt(animPos) == Math::CeilToInt(anim->GetDuration()) && k.Time == anim->GetDuration())
|
|| (!loop && duration == 0.0f && Math::CeilToInt(animPos) == Math::CeilToInt(anim->GetDuration()) && Math::CeilToInt(animPrevPos) == Math::CeilToInt(anim->GetDuration()) - 1 && Math::NearEqual(k.Time, anim->GetDuration()))
|
||||||
|| (loop && Math::FloorToInt(animPos) == 0 && Math::CeilToInt(animPrevPos) == Math::CeilToInt(anim->GetDuration()) && k.Time == 0.0f)
|
|| (loop && Math::FloorToInt(animPos) == 0 && Math::CeilToInt(animPrevPos) == Math::CeilToInt(anim->GetDuration()) && k.Time == 0.0f)
|
||||||
|| (loop && Math::FloorToInt(animPrevPos) == 0 && Math::CeilToInt(animPos) == Math::CeilToInt(anim->GetDuration()) && k.Time == 0.0f)
|
|| (loop && Math::FloorToInt(animPrevPos) == 0 && Math::CeilToInt(animPos) == Math::CeilToInt(anim->GetDuration()) && k.Time == 0.0f)
|
||||||
|
|| (loop && Math::FloorToInt(animPos) == 0 && Math::CeilToInt(animPrevPos) == Math::CeilToInt(anim->GetDuration()) && Math::NearEqual(k.Time, anim->GetDuration()))
|
||||||
|
|| (loop && Math::FloorToInt(animPrevPos) == 0 && Math::CeilToInt(animPos) == Math::CeilToInt(anim->GetDuration()) && Math::NearEqual(k.Time, anim->GetDuration()))
|
||||||
|
|| (Math::FloorToInt(animPos) == 1 && Math::FloorToInt(animPrevPos) == 0 && k.Time == 1.0f)
|
||||||
|
|| (Math::FloorToInt(animPos) == 0 && Math::FloorToInt(animPrevPos) == 1 && k.Time == 1.0f)
|
||||||
|
|| (Math::CeilToInt(animPos) == Math::CeilToInt(anim->GetDuration()) && Math::CeilToInt(animPrevPos) == Math::CeilToInt(anim->GetDuration()) - 1 && Math::NearEqual(k.Time, anim->GetDuration() - 1.0f))
|
||||||
|
|| (Math::CeilToInt(animPos) == Math::CeilToInt(anim->GetDuration()) - 1 && Math::CeilToInt(animPrevPos) == Math::CeilToInt(anim->GetDuration()) && Math::NearEqual(k.Time, anim->GetDuration() - 1.0f))
|
||||||
|
|| (Math::FloorToInt(animPos) == 0 && Math::FloorToInt(animPrevPos) == 0 && k.Time == 0.0f)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
int32 stateIndex = -1;
|
int32 stateIndex = -1;
|
||||||
@@ -2433,10 +2441,14 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
|||||||
{
|
{
|
||||||
if (bucket.LoopsLeft == 0)
|
if (bucket.LoopsLeft == 0)
|
||||||
{
|
{
|
||||||
// End playing animation
|
// End playing animation and reset bucket params
|
||||||
value = tryGetValue(node->GetBox(1), Value::Null);
|
value = tryGetValue(node->GetBox(1), Value::Null);
|
||||||
bucket.Index = -1;
|
bucket.Index = -1;
|
||||||
slot.Animation = nullptr;
|
slot.Animation = nullptr;
|
||||||
|
bucket.TimePosition = 0.0f;
|
||||||
|
bucket.BlendInPosition = 0.0f;
|
||||||
|
bucket.BlendOutPosition = 0.0f;
|
||||||
|
bucket.LoopsDone = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2545,9 +2557,15 @@ void AnimGraphExecutor::ProcessGroupFunction(Box* boxBase, Node* node, Value& va
|
|||||||
// Function Input
|
// Function Input
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
|
// Skip when graph is too small (eg. preview) and fallback with default value from the function graph
|
||||||
|
if (context.GraphStack.Count() < 2)
|
||||||
|
{
|
||||||
|
value = tryGetValue(node->TryGetBox(1), Value::Zero);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Find the function call
|
// Find the function call
|
||||||
AnimGraphNode* functionCallNode = nullptr;
|
AnimGraphNode* functionCallNode = nullptr;
|
||||||
ASSERT(context.GraphStack.Count() >= 2);
|
|
||||||
Graph* graph;
|
Graph* graph;
|
||||||
for (int32 i = context.CallStack.Count() - 1; i >= 0; i--)
|
for (int32 i = context.CallStack.Count() - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -666,7 +666,7 @@ void Asset::onLoaded()
|
|||||||
{
|
{
|
||||||
onLoaded_MainThread();
|
onLoaded_MainThread();
|
||||||
}
|
}
|
||||||
else if (OnLoaded.IsBinded())
|
else if (OnLoaded.IsBinded() || _references.HasItems())
|
||||||
{
|
{
|
||||||
Function<void()> action;
|
Function<void()> action;
|
||||||
action.Bind<Asset, &Asset::onLoaded>(this);
|
action.Bind<Asset, &Asset::onLoaded>(this);
|
||||||
|
|||||||
@@ -218,10 +218,14 @@ Asset::LoadResult MaterialInstance::load()
|
|||||||
Guid baseMaterialId;
|
Guid baseMaterialId;
|
||||||
headerStream.Read(baseMaterialId);
|
headerStream.Read(baseMaterialId);
|
||||||
auto baseMaterial = Content::LoadAsync<MaterialBase>(baseMaterialId);
|
auto baseMaterial = Content::LoadAsync<MaterialBase>(baseMaterialId);
|
||||||
|
if (baseMaterial)
|
||||||
|
baseMaterial->AddReference();
|
||||||
|
|
||||||
// Load parameters
|
// Load parameters
|
||||||
if (Params.Load(&headerStream))
|
if (Params.Load(&headerStream))
|
||||||
{
|
{
|
||||||
|
if (baseMaterial)
|
||||||
|
baseMaterial->RemoveReference();
|
||||||
LOG(Warning, "Cannot load material parameters.");
|
LOG(Warning, "Cannot load material parameters.");
|
||||||
return LoadResult::CannotLoadData;
|
return LoadResult::CannotLoadData;
|
||||||
}
|
}
|
||||||
@@ -239,6 +243,8 @@ Asset::LoadResult MaterialInstance::load()
|
|||||||
ParamsChanged();
|
ParamsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (baseMaterial)
|
||||||
|
baseMaterial->RemoveReference();
|
||||||
return LoadResult::Ok;
|
return LoadResult::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -262,6 +262,7 @@ bool Model::GenerateSDF(float resolutionScale, int32 lodIndex, bool cacheData, f
|
|||||||
LOG(Warning, "Cannot generate SDF for virtual models on a main thread.");
|
LOG(Warning, "Cannot generate SDF for virtual models on a main thread.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
auto chunkLocks = Storage ? Storage->Lock() : FlaxStorage::LockData();
|
||||||
lodIndex = Math::Clamp(lodIndex, HighestResidentLODIndex(), LODs.Count() - 1);
|
lodIndex = Math::Clamp(lodIndex, HighestResidentLODIndex(), LODs.Count() - 1);
|
||||||
|
|
||||||
// Generate SDF
|
// Generate SDF
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ public:
|
|||||||
model->GetLODData(_lodIndex, data);
|
model->GetLODData(_lodIndex, data);
|
||||||
if (data.IsInvalid())
|
if (data.IsInvalid())
|
||||||
{
|
{
|
||||||
LOG(Warning, "Missing data chunk");
|
LOG(Warning, "Missing data chunk with LOD{} for model '{}'", _lodIndex, model->ToString());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
MemoryReadStream stream(data.Get(), data.Length());
|
MemoryReadStream stream(data.Get(), data.Length());
|
||||||
@@ -234,6 +234,7 @@ bool ModelBase::Save(bool withMeshDataFromGpu, const StringView& path)
|
|||||||
LOG(Error, "To save virtual model asset you need to specify 'withMeshDataFromGpu' (it has no other storage container to get data).");
|
LOG(Error, "To save virtual model asset you need to specify 'withMeshDataFromGpu' (it has no other storage container to get data).");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
auto chunkLocks = Storage ? Storage->Lock() : FlaxStorage::LockData();
|
||||||
ScopeLock lock(Locker);
|
ScopeLock lock(Locker);
|
||||||
|
|
||||||
// Use a temporary chunks for data storage for virtual assets
|
// Use a temporary chunks for data storage for virtual assets
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public:
|
|||||||
/// <param name="id">The asset id.</param>
|
/// <param name="id">The asset id.</param>
|
||||||
/// <returns>Loaded asset of null.</returns>
|
/// <returns>Loaded asset of null.</returns>
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T* LoadAsync(const Guid& id)
|
T* Load(const Guid& id)
|
||||||
{
|
{
|
||||||
for (auto& e : *this)
|
for (auto& e : *this)
|
||||||
{
|
{
|
||||||
@@ -26,8 +26,10 @@ public:
|
|||||||
return (T*)e.Get();
|
return (T*)e.Get();
|
||||||
}
|
}
|
||||||
auto asset = (T*)::LoadAsset(id, T::TypeInitializer);
|
auto asset = (T*)::LoadAsset(id, T::TypeInitializer);
|
||||||
if (asset)
|
if (asset && !asset->WaitForLoaded())
|
||||||
Add(asset);
|
Add(asset);
|
||||||
|
else
|
||||||
|
asset = nullptr;
|
||||||
return asset;
|
return asset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "Engine/Profiler/ProfilerCPU.h"
|
#include "Engine/Profiler/ProfilerCPU.h"
|
||||||
#include "Engine/Profiler/ProfilerMemory.h"
|
#include "Engine/Profiler/ProfilerMemory.h"
|
||||||
#include "Engine/Scripting/ManagedCLR/MClass.h"
|
#include "Engine/Scripting/ManagedCLR/MClass.h"
|
||||||
|
#include "Engine/Scripting/Internal/InternalCalls.h"
|
||||||
#include "Engine/Scripting/Scripting.h"
|
#include "Engine/Scripting/Scripting.h"
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
#include "Editor/Editor.h"
|
#include "Editor/Editor.h"
|
||||||
@@ -346,17 +347,21 @@ int32 LoadingThread::Run()
|
|||||||
ContentLoadTask* task;
|
ContentLoadTask* task;
|
||||||
ThisLoadThread = this;
|
ThisLoadThread = this;
|
||||||
|
|
||||||
|
MONO_THREAD_INFO_TYPE* monoThreadInfo = nullptr;
|
||||||
while (Platform::AtomicRead(&_exitFlag) == 0)
|
while (Platform::AtomicRead(&_exitFlag) == 0)
|
||||||
{
|
{
|
||||||
if (LoadTasks.try_dequeue(task))
|
if (LoadTasks.try_dequeue(task))
|
||||||
{
|
{
|
||||||
Run(task);
|
Run(task);
|
||||||
|
MONO_THREAD_INFO_GET(monoThreadInfo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
MONO_ENTER_GC_SAFE_WITH_INFO(monoThreadInfo);
|
||||||
LoadTasksMutex.Lock();
|
LoadTasksMutex.Lock();
|
||||||
LoadTasksSignal.Wait(LoadTasksMutex);
|
LoadTasksSignal.Wait(LoadTasksMutex);
|
||||||
LoadTasksMutex.Unlock();
|
LoadTasksMutex.Unlock();
|
||||||
|
MONO_EXIT_GC_SAFE_WITH_INFO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -700,6 +705,7 @@ Asset* Content::GetAsset(const StringView& outputPath)
|
|||||||
{
|
{
|
||||||
if (outputPath.IsEmpty())
|
if (outputPath.IsEmpty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
PROFILE_CPU();
|
||||||
ScopeLock lock(AssetsLocker);
|
ScopeLock lock(AssetsLocker);
|
||||||
for (auto i = Assets.Begin(); i.IsNotEnd(); ++i)
|
for (auto i = Assets.Begin(); i.IsNotEnd(); ++i)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -87,6 +87,10 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
double LastAccessTime = 0.0;
|
double LastAccessTime = 0.0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flag set to indicate that chunk is during loading (atomic access to sync multiple reading threads).
|
||||||
|
/// </summary>
|
||||||
|
int64 IsLoading = 0;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The chunk data.
|
/// The chunk data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -146,7 +150,7 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
FORCE_INLINE bool IsLoaded() const
|
FORCE_INLINE bool IsLoaded() const
|
||||||
{
|
{
|
||||||
return Data.IsValid();
|
return Data.IsValid() && Platform::AtomicRead(&IsLoading) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -154,7 +158,7 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
FORCE_INLINE bool IsMissing() const
|
FORCE_INLINE bool IsMissing() const
|
||||||
{
|
{
|
||||||
return Data.IsInvalid();
|
return !IsLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "FlaxPackage.h"
|
#include "FlaxPackage.h"
|
||||||
#include "ContentStorageManager.h"
|
#include "ContentStorageManager.h"
|
||||||
#include "Engine/Core/Log.h"
|
#include "Engine/Core/Log.h"
|
||||||
|
#include "Engine/Core/ScopeExit.h"
|
||||||
#include "Engine/Core/Types/TimeSpan.h"
|
#include "Engine/Core/Types/TimeSpan.h"
|
||||||
#include "Engine/Platform/File.h"
|
#include "Engine/Platform/File.h"
|
||||||
#include "Engine/Profiler/ProfilerCPU.h"
|
#include "Engine/Profiler/ProfilerCPU.h"
|
||||||
@@ -74,8 +75,6 @@ FlaxChunk* FlaxChunk::Clone() const
|
|||||||
|
|
||||||
const int32 FlaxStorage::MagicCode = 1180124739;
|
const int32 FlaxStorage::MagicCode = 1180124739;
|
||||||
|
|
||||||
FlaxStorage::LockData FlaxStorage::LockData::Invalid(nullptr);
|
|
||||||
|
|
||||||
struct Header
|
struct Header
|
||||||
{
|
{
|
||||||
int32 MagicCode;
|
int32 MagicCode;
|
||||||
@@ -246,6 +245,7 @@ FlaxStorage::~FlaxStorage()
|
|||||||
ASSERT(IsDisposed());
|
ASSERT(IsDisposed());
|
||||||
CHECK(_chunksLock == 0);
|
CHECK(_chunksLock == 0);
|
||||||
CHECK(_refCount == 0);
|
CHECK(_refCount == 0);
|
||||||
|
CHECK(_isUnloadingData == 0);
|
||||||
ASSERT(_chunks.IsEmpty());
|
ASSERT(_chunks.IsEmpty());
|
||||||
|
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
@@ -261,6 +261,22 @@ FlaxStorage::~FlaxStorage()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FlaxStorage::LockChunks()
|
||||||
|
{
|
||||||
|
RETRY:
|
||||||
|
Platform::InterlockedIncrement(&_chunksLock);
|
||||||
|
if (Platform::AtomicRead(&_isUnloadingData) != 0)
|
||||||
|
{
|
||||||
|
// Someone else is closing file handles or freeing chunks so wait for it to finish and retry
|
||||||
|
Platform::InterlockedDecrement(&_chunksLock);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Platform::Sleep(1);
|
||||||
|
} while (Platform::AtomicRead(&_isUnloadingData) != 0);
|
||||||
|
goto RETRY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FlaxStorage::LockData FlaxStorage::LockSafe()
|
FlaxStorage::LockData FlaxStorage::LockSafe()
|
||||||
{
|
{
|
||||||
auto lock = LockData(this);
|
auto lock = LockData(this);
|
||||||
@@ -689,7 +705,6 @@ bool FlaxStorage::LoadAssetHeader(const Guid& id, AssetInitData& data)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load header
|
|
||||||
return LoadAssetHeader(e, data);
|
return LoadAssetHeader(e, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -699,7 +714,10 @@ bool FlaxStorage::LoadAssetChunk(FlaxChunk* chunk)
|
|||||||
ASSERT(IsLoaded());
|
ASSERT(IsLoaded());
|
||||||
ASSERT(chunk != nullptr && _chunks.Contains(chunk));
|
ASSERT(chunk != nullptr && _chunks.Contains(chunk));
|
||||||
|
|
||||||
// Check if already loaded
|
// Protect against loading the same chunk from multiple threads at once
|
||||||
|
while (Platform::InterlockedCompareExchange(&chunk->IsLoading, 1, 0) != 0)
|
||||||
|
Platform::Sleep(1);
|
||||||
|
SCOPE_EXIT{ Platform::AtomicStore(&chunk->IsLoading, 0); };
|
||||||
if (chunk->IsLoaded())
|
if (chunk->IsLoaded())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -776,12 +794,10 @@ bool FlaxStorage::LoadAssetChunk(FlaxChunk* chunk)
|
|||||||
// Raw data
|
// Raw data
|
||||||
chunk->Data.Read(stream, size);
|
chunk->Data.Read(stream, size);
|
||||||
}
|
}
|
||||||
ASSERT(chunk->IsLoaded());
|
|
||||||
chunk->RegisterUsage();
|
chunk->RegisterUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
UnlockChunks();
|
UnlockChunks();
|
||||||
|
|
||||||
return failed;
|
return failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1420,10 +1436,12 @@ FileReadStream* FlaxStorage::OpenFile()
|
|||||||
|
|
||||||
bool FlaxStorage::CloseFileHandles()
|
bool FlaxStorage::CloseFileHandles()
|
||||||
{
|
{
|
||||||
|
// Guard the whole process so if new thread wants to lock the chunks will need to wait for this to end
|
||||||
|
Platform::InterlockedIncrement(&_isUnloadingData);
|
||||||
|
SCOPE_EXIT{ Platform::InterlockedDecrement(&_isUnloadingData); };
|
||||||
|
|
||||||
if (Platform::AtomicRead(&_chunksLock) == 0 && Platform::AtomicRead(&_files) == 0)
|
if (Platform::AtomicRead(&_chunksLock) == 0 && Platform::AtomicRead(&_files) == 0)
|
||||||
{
|
return false; // Early out when no files are opened
|
||||||
return false;
|
|
||||||
}
|
|
||||||
PROFILE_CPU();
|
PROFILE_CPU();
|
||||||
PROFILE_MEM(ContentFiles);
|
PROFILE_MEM(ContentFiles);
|
||||||
|
|
||||||
@@ -1496,9 +1514,21 @@ void FlaxStorage::Tick(double time)
|
|||||||
{
|
{
|
||||||
auto chunk = _chunks.Get()[i];
|
auto chunk = _chunks.Get()[i];
|
||||||
const bool wasUsed = (time - chunk->LastAccessTime) < unusedDataChunksLifetime;
|
const bool wasUsed = (time - chunk->LastAccessTime) < unusedDataChunksLifetime;
|
||||||
if (!wasUsed && chunk->IsLoaded() && EnumHasNoneFlags(chunk->Flags, FlaxChunkFlags::KeepInMemory))
|
if (!wasUsed &&
|
||||||
|
chunk->IsLoaded() &&
|
||||||
|
EnumHasNoneFlags(chunk->Flags, FlaxChunkFlags::KeepInMemory) &&
|
||||||
|
Platform::AtomicRead(&chunk->IsLoading) == 0)
|
||||||
{
|
{
|
||||||
|
// Guard the unloading so if other thread wants to lock the chunks will need to wait for this to end
|
||||||
|
Platform::InterlockedIncrement(&_isUnloadingData);
|
||||||
|
if (Platform::AtomicRead(&_chunksLock) != 0 || Platform::AtomicRead(&chunk->IsLoading) != 0)
|
||||||
|
{
|
||||||
|
// Someone started loading so skip ticking
|
||||||
|
Platform::InterlockedDecrement(&_isUnloadingData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
chunk->Unload();
|
chunk->Unload();
|
||||||
|
Platform::InterlockedDecrement(&_isUnloadingData);
|
||||||
}
|
}
|
||||||
wasAnyUsed |= wasUsed;
|
wasAnyUsed |= wasUsed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ protected:
|
|||||||
int64 _refCount = 0;
|
int64 _refCount = 0;
|
||||||
int64 _chunksLock = 0;
|
int64 _chunksLock = 0;
|
||||||
int64 _files = 0;
|
int64 _files = 0;
|
||||||
|
int64 _isUnloadingData = 0;
|
||||||
double _lastRefLostTime;
|
double _lastRefLostTime;
|
||||||
CriticalSection _loadLocker;
|
CriticalSection _loadLocker;
|
||||||
|
|
||||||
@@ -129,10 +130,7 @@ public:
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Locks the storage chunks data to prevent disposing them. Also ensures that file handles won't be closed while chunks are locked.
|
/// Locks the storage chunks data to prevent disposing them. Also ensures that file handles won't be closed while chunks are locked.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
FORCE_INLINE void LockChunks()
|
void LockChunks();
|
||||||
{
|
|
||||||
Platform::InterlockedIncrement(&_chunksLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unlocks the storage chunks data.
|
/// Unlocks the storage chunks data.
|
||||||
@@ -148,7 +146,6 @@ public:
|
|||||||
struct LockData
|
struct LockData
|
||||||
{
|
{
|
||||||
friend FlaxStorage;
|
friend FlaxStorage;
|
||||||
static LockData Invalid;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FlaxStorage* _storage;
|
FlaxStorage* _storage;
|
||||||
@@ -161,6 +158,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
LockData()
|
||||||
|
: _storage(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
LockData(const LockData& other)
|
LockData(const LockData& other)
|
||||||
: _storage(other._storage)
|
: _storage(other._storage)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -658,7 +658,10 @@ public:
|
|||||||
--_count;
|
--_count;
|
||||||
T* data = _allocation.Get();
|
T* data = _allocation.Get();
|
||||||
if (index < _count)
|
if (index < _count)
|
||||||
Memory::MoveAssignItems(data + index, data + (index + 1), _count - index);
|
{
|
||||||
|
for (int32 i = index; i < _count; i++)
|
||||||
|
data[i] = MoveTemp(data[i + 1]);
|
||||||
|
}
|
||||||
Memory::DestructItems(data + _count, 1);
|
Memory::DestructItems(data + _count, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -409,27 +409,36 @@ protected:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Rebuild entire table completely
|
// Rebuild entire table completely
|
||||||
|
const int32 elementsCount = _elementsCount;
|
||||||
|
const int32 oldSize = _size;
|
||||||
AllocationData oldAllocation;
|
AllocationData oldAllocation;
|
||||||
AllocationUtils::MoveToEmpty<BucketType, AllocationType>(oldAllocation, _allocation, _size, _size);
|
AllocationUtils::MoveToEmpty<BucketType, AllocationType>(oldAllocation, _allocation, oldSize, oldSize);
|
||||||
_allocation.Allocate(_size);
|
_allocation.Allocate(_size);
|
||||||
BucketType* data = _allocation.Get();
|
BucketType* data = _allocation.Get();
|
||||||
for (int32 i = 0; i < _size; ++i)
|
for (int32 i = 0; i < oldSize; ++i)
|
||||||
data[i]._state = HashSetBucketState::Empty;
|
data[i]._state = HashSetBucketState::Empty;
|
||||||
BucketType* oldData = oldAllocation.Get();
|
BucketType* oldData = oldAllocation.Get();
|
||||||
FindPositionResult pos;
|
FindPositionResult pos;
|
||||||
for (int32 i = 0; i < _size; ++i)
|
for (int32 i = 0; i < oldSize; ++i)
|
||||||
{
|
{
|
||||||
BucketType& oldBucket = oldData[i];
|
BucketType& oldBucket = oldData[i];
|
||||||
if (oldBucket.IsOccupied())
|
if (oldBucket.IsOccupied())
|
||||||
{
|
{
|
||||||
FindPosition(oldBucket.GetKey(), pos);
|
FindPosition(oldBucket.GetKey(), pos);
|
||||||
ASSERT(pos.FreeSlotIndex != -1);
|
if (pos.FreeSlotIndex == -1)
|
||||||
|
{
|
||||||
|
// Grow and retry to handle pathological cases (eg. heavy collisions)
|
||||||
|
EnsureCapacity(_size + 1, true);
|
||||||
|
FindPosition(oldBucket.GetKey(), pos);
|
||||||
|
ASSERT(pos.FreeSlotIndex != -1);
|
||||||
|
}
|
||||||
BucketType& bucket = _allocation.Get()[pos.FreeSlotIndex];
|
BucketType& bucket = _allocation.Get()[pos.FreeSlotIndex];
|
||||||
bucket = MoveTemp(oldBucket);
|
bucket = MoveTemp(oldBucket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int32 i = 0; i < _size; ++i)
|
for (int32 i = 0; i < oldSize; ++i)
|
||||||
oldData[i].Free();
|
oldData[i].Free();
|
||||||
|
_elementsCount = elementsCount;
|
||||||
}
|
}
|
||||||
_deletedCount = 0;
|
_deletedCount = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
|
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
|
|
||||||
#define DLLEXPORT __attribute__ ((__visibility__ ("default")))
|
#define DLLEXPORT __attribute__((__visibility__("default")))
|
||||||
#define DLLIMPORT
|
#define DLLIMPORT
|
||||||
|
#define USED __attribute__((used))
|
||||||
#define THREADLOCAL __thread
|
#define THREADLOCAL __thread
|
||||||
#define STDCALL __attribute__((stdcall))
|
#define STDCALL __attribute__((stdcall))
|
||||||
#define CDECL __attribute__((cdecl))
|
#define CDECL __attribute__((cdecl))
|
||||||
@@ -19,7 +20,7 @@
|
|||||||
#define PACK_BEGIN()
|
#define PACK_BEGIN()
|
||||||
#define PACK_END() __attribute__((__packed__))
|
#define PACK_END() __attribute__((__packed__))
|
||||||
#define ALIGN_BEGIN(_align)
|
#define ALIGN_BEGIN(_align)
|
||||||
#define ALIGN_END(_align) __attribute__( (aligned(_align) ) )
|
#define ALIGN_END(_align) __attribute__((aligned(_align)))
|
||||||
#define OFFSET_OF(X, Y) __builtin_offsetof(X, Y)
|
#define OFFSET_OF(X, Y) __builtin_offsetof(X, Y)
|
||||||
#define PRAGMA_DISABLE_DEPRECATION_WARNINGS \
|
#define PRAGMA_DISABLE_DEPRECATION_WARNINGS \
|
||||||
_Pragma("clang diagnostic push") \
|
_Pragma("clang diagnostic push") \
|
||||||
@@ -37,8 +38,9 @@
|
|||||||
|
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
|
|
||||||
#define DLLEXPORT __attribute__ ((__visibility__ ("default")))
|
#define DLLEXPORT __attribute__((__visibility__("default")))
|
||||||
#define DLLIMPORT
|
#define DLLIMPORT
|
||||||
|
#define USED __attribute__((used))
|
||||||
#define THREADLOCAL __thread
|
#define THREADLOCAL __thread
|
||||||
#define STDCALL __attribute__((stdcall))
|
#define STDCALL __attribute__((stdcall))
|
||||||
#define CDECL __attribute__((cdecl))
|
#define CDECL __attribute__((cdecl))
|
||||||
@@ -52,7 +54,7 @@
|
|||||||
#define PACK_BEGIN()
|
#define PACK_BEGIN()
|
||||||
#define PACK_END() __attribute__((__packed__))
|
#define PACK_END() __attribute__((__packed__))
|
||||||
#define ALIGN_BEGIN(_align)
|
#define ALIGN_BEGIN(_align)
|
||||||
#define ALIGN_END(_align) __attribute__( (aligned(_align) ) )
|
#define ALIGN_END(_align) __attribute__((aligned(_align)))
|
||||||
#define OFFSET_OF(X, Y) __builtin_offsetof(X, Y)
|
#define OFFSET_OF(X, Y) __builtin_offsetof(X, Y)
|
||||||
#define PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
#define PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
||||||
#define PRAGMA_ENABLE_DEPRECATION_WARNINGS
|
#define PRAGMA_ENABLE_DEPRECATION_WARNINGS
|
||||||
@@ -67,6 +69,7 @@
|
|||||||
|
|
||||||
#define DLLEXPORT __declspec(dllexport)
|
#define DLLEXPORT __declspec(dllexport)
|
||||||
#define DLLIMPORT __declspec(dllimport)
|
#define DLLIMPORT __declspec(dllimport)
|
||||||
|
#define USED
|
||||||
#define THREADLOCAL __declspec(thread)
|
#define THREADLOCAL __declspec(thread)
|
||||||
#define STDCALL __stdcall
|
#define STDCALL __stdcall
|
||||||
#define CDECL __cdecl
|
#define CDECL __cdecl
|
||||||
|
|||||||
@@ -620,14 +620,9 @@ bool Collision::RayIntersectsTriangle(const Ray& ray, const Vector3& a, const Ve
|
|||||||
Real rayDistance = edge2.X * distanceCrossEdge1.X + edge2.Y * distanceCrossEdge1.Y + edge2.Z * distanceCrossEdge1.Z;
|
Real rayDistance = edge2.X * distanceCrossEdge1.X + edge2.Y * distanceCrossEdge1.Y + edge2.Z * distanceCrossEdge1.Z;
|
||||||
rayDistance *= inverseDeterminant;
|
rayDistance *= inverseDeterminant;
|
||||||
|
|
||||||
// Check if the triangle is behind the ray origin
|
// Check if the triangle is in front the ray origin
|
||||||
if (rayDistance < 0.0f)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
distance = rayDistance;
|
distance = rayDistance;
|
||||||
return true;
|
return rayDistance >= 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CollisionsHelper::RayIntersectsTriangle(const Ray& ray, const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3, Real& distance, Vector3& normal)
|
bool CollisionsHelper::RayIntersectsTriangle(const Ray& ray, const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3, Real& distance, Vector3& normal)
|
||||||
|
|||||||
@@ -12,11 +12,6 @@ String Ray::ToString() const
|
|||||||
return String::Format(TEXT("{}"), *this);
|
return String::Format(TEXT("{}"), *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 Ray::GetPoint(Real distance) const
|
|
||||||
{
|
|
||||||
return Position + Direction * distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ray Ray::GetPickRay(float x, float y, const Viewport& viewport, const Matrix& vp)
|
Ray Ray::GetPickRay(float x, float y, const Viewport& viewport, const Matrix& vp)
|
||||||
{
|
{
|
||||||
Vector3 nearPoint(x, y, 0.0f);
|
Vector3 nearPoint(x, y, 0.0f);
|
||||||
|
|||||||
@@ -79,7 +79,10 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="distance">The distance from ray origin.</param>
|
/// <param name="distance">The distance from ray origin.</param>
|
||||||
/// <returns>The calculated point.</returns>
|
/// <returns>The calculated point.</returns>
|
||||||
Vector3 GetPoint(Real distance) const;
|
FORCE_INLINE Vector3 GetPoint(Real distance) const
|
||||||
|
{
|
||||||
|
return Position + Direction * distance;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines if there is an intersection between ray and a point.
|
/// Determines if there is an intersection between ray and a point.
|
||||||
|
|||||||
@@ -18,9 +18,7 @@ namespace AllocationUtils
|
|||||||
capacity |= capacity >> 8;
|
capacity |= capacity >> 8;
|
||||||
capacity |= capacity >> 16;
|
capacity |= capacity >> 16;
|
||||||
uint64 capacity64 = (uint64)(capacity + 1) * 2;
|
uint64 capacity64 = (uint64)(capacity + 1) * 2;
|
||||||
if (capacity64 > MAX_int32)
|
return capacity64 >= MAX_int32 ? MAX_int32 : (int32)capacity64 / 2;
|
||||||
capacity64 = MAX_int32;
|
|
||||||
return (int32)capacity64;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aligns the input value to the next power of 2 to be used as bigger memory allocation block.
|
// Aligns the input value to the next power of 2 to be used as bigger memory allocation block.
|
||||||
@@ -208,7 +206,7 @@ public:
|
|||||||
typedef typename FallbackAllocation::template Data<T> FallbackData;
|
typedef typename FallbackAllocation::template Data<T> FallbackData;
|
||||||
|
|
||||||
bool _useFallback = false;
|
bool _useFallback = false;
|
||||||
byte _data[Capacity * sizeof(T)];
|
alignas(sizeof(void*)) byte _data[Capacity * sizeof(T)];
|
||||||
FallbackData _fallback;
|
FallbackData _fallback;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -215,6 +215,11 @@ public:
|
|||||||
return String(_data.Get(), _data.Count());
|
return String(_data.Get(), _data.Count());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringAnsi ToStringAnsi() const
|
||||||
|
{
|
||||||
|
return StringAnsi(_data.Get(), _data.Count());
|
||||||
|
}
|
||||||
|
|
||||||
StringView ToStringView() const;
|
StringView ToStringView() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -79,10 +79,11 @@ namespace FlaxEngine.Interop
|
|||||||
NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), NativeLibraryImportResolver);
|
NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), NativeLibraryImportResolver);
|
||||||
|
|
||||||
// Change default culture to match with Mono runtime default culture
|
// Change default culture to match with Mono runtime default culture
|
||||||
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
|
var culture = CultureInfo.InvariantCulture;
|
||||||
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture;
|
CultureInfo.DefaultThreadCurrentCulture = culture;
|
||||||
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
|
CultureInfo.DefaultThreadCurrentUICulture = culture;
|
||||||
System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
|
System.Threading.Thread.CurrentThread.CurrentCulture = culture;
|
||||||
|
System.Threading.Thread.CurrentThread.CurrentUICulture = culture;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,6 +426,8 @@ namespace FlaxEngine.Interop
|
|||||||
var fieldOffsetPtr = (IntPtr*)field.FieldHandle.Value; // Pointer to MonoClassField
|
var fieldOffsetPtr = (IntPtr*)field.FieldHandle.Value; // Pointer to MonoClassField
|
||||||
fieldOffsetPtr += 3; // Skip three pointers (type, name, parent_and_flags)
|
fieldOffsetPtr += 3; // Skip three pointers (type, name, parent_and_flags)
|
||||||
return *(int*)fieldOffsetPtr - IntPtr.Size * 2; // Load the value of a pointer (4 bytes, int32), then subtracting 16 bytes from it (2 pointers for vtable and threadsync)
|
return *(int*)fieldOffsetPtr - IntPtr.Size * 2; // Load the value of a pointer (4 bytes, int32), then subtracting 16 bytes from it (2 pointers for vtable and threadsync)
|
||||||
|
#else
|
||||||
|
throw new NotImplementedException();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ void GPUContext::FrameBegin()
|
|||||||
|
|
||||||
void GPUContext::FrameEnd()
|
void GPUContext::FrameEnd()
|
||||||
{
|
{
|
||||||
ClearState();
|
ResetState();
|
||||||
FlushState();
|
FlushState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ public:
|
|||||||
/// [Deprecated in v1.10]
|
/// [Deprecated in v1.10]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns><c>true</c> if depth buffer is binded; otherwise, <c>false</c>.</returns>
|
/// <returns><c>true</c> if depth buffer is binded; otherwise, <c>false</c>.</returns>
|
||||||
DEPRECATED("IsDepthBufferBinded has been deprecated and will be removed in ")
|
DEPRECATED("IsDepthBufferBinded has been deprecated and will be removed in future")
|
||||||
virtual bool IsDepthBufferBinded() = 0;
|
virtual bool IsDepthBufferBinded() = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -617,8 +617,17 @@ public:
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clears the context state.
|
/// Clears the context state.
|
||||||
|
/// [Deprecated in v1.12]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FUNCTION() virtual void ClearState() = 0;
|
API_FUNCTION() DEPRECATED("Use ResetState instead") void ClearState()
|
||||||
|
{
|
||||||
|
ResetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resets the context state.
|
||||||
|
/// </summary>
|
||||||
|
API_FUNCTION() virtual void ResetState() = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Flushes the internal cached context state with a command buffer.
|
/// Flushes the internal cached context state with a command buffer.
|
||||||
|
|||||||
@@ -201,6 +201,7 @@ bool DeferredMaterialShader::Load()
|
|||||||
psDesc.DepthWriteEnable = true;
|
psDesc.DepthWriteEnable = true;
|
||||||
psDesc.DepthEnable = true;
|
psDesc.DepthEnable = true;
|
||||||
psDesc.DepthFunc = ComparisonFunc::Less;
|
psDesc.DepthFunc = ComparisonFunc::Less;
|
||||||
|
psDesc.BlendMode.RenderTargetWriteMask = BlendingMode::ColorWrite::None;
|
||||||
psDesc.HS = nullptr;
|
psDesc.HS = nullptr;
|
||||||
psDesc.DS = nullptr;
|
psDesc.DS = nullptr;
|
||||||
GPUShaderProgramVS* instancedDepthPassVS;
|
GPUShaderProgramVS* instancedDepthPassVS;
|
||||||
|
|||||||
@@ -195,5 +195,10 @@ bool ForwardMaterialShader::Load()
|
|||||||
psDesc.VS = _shader->GetVS("VS_Skinned");
|
psDesc.VS = _shader->GetVS("VS_Skinned");
|
||||||
_cache.DepthSkinned.Init(psDesc);
|
_cache.DepthSkinned.Init(psDesc);
|
||||||
|
|
||||||
|
#if PLATFORM_PS5
|
||||||
|
// Fix shader binding issues on forward shading materials on PS5
|
||||||
|
_drawModes = DrawPass::None;
|
||||||
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,5 +264,10 @@ bool ParticleMaterialShader::Load()
|
|||||||
// Lazy initialization
|
// Lazy initialization
|
||||||
_cacheVolumetricFog.Desc.PS = nullptr;
|
_cacheVolumetricFog.Desc.PS = nullptr;
|
||||||
|
|
||||||
|
#if PLATFORM_PS5
|
||||||
|
// Fix shader binding issues on forward shading materials on PS5
|
||||||
|
_drawModes = DrawPass::None;
|
||||||
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,7 +113,8 @@ GPUTexture* RenderBuffers::RequestHalfResDepth(GPUContext* context)
|
|||||||
|
|
||||||
PixelFormat RenderBuffers::GetOutputFormat() const
|
PixelFormat RenderBuffers::GetOutputFormat() const
|
||||||
{
|
{
|
||||||
return _useAlpha ? PixelFormat::R16G16B16A16_Float : PixelFormat::R11G11B10_Float;
|
// TODO: fix incorrect alpha leaking into reflections on PS5 with R11G11B10_Float
|
||||||
|
return _useAlpha || PLATFORM_PS5 ? PixelFormat::R16G16B16A16_Float : PixelFormat::R11G11B10_Float;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenderBuffers::GetUseAlpha() const
|
bool RenderBuffers::GetUseAlpha() const
|
||||||
|
|||||||
@@ -450,7 +450,7 @@ public:
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The high-level renderer context. Used to collect the draw calls for the scene rendering. Can be used to perform a custom rendering.
|
/// The high-level renderer context. Used to collect the draw calls for the scene rendering. Can be used to perform a custom rendering.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_STRUCT(NoDefault) struct RenderContext
|
API_STRUCT(NoDefault) struct FLAXENGINE_API RenderContext
|
||||||
{
|
{
|
||||||
DECLARE_SCRIPTING_TYPE_MINIMAL(RenderContext);
|
DECLARE_SCRIPTING_TYPE_MINIMAL(RenderContext);
|
||||||
|
|
||||||
@@ -491,7 +491,7 @@ API_STRUCT(NoDefault) struct RenderContext
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The high-level renderer context batch that encapsulates multiple rendering requests within a single task (eg. optimize main view scene rendering and shadow projections at once).
|
/// The high-level renderer context batch that encapsulates multiple rendering requests within a single task (eg. optimize main view scene rendering and shadow projections at once).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_STRUCT(NoDefault) struct RenderContextBatch
|
API_STRUCT(NoDefault) struct FLAXENGINE_API RenderContextBatch
|
||||||
{
|
{
|
||||||
DECLARE_SCRIPTING_TYPE_MINIMAL(RenderContextBatch);
|
DECLARE_SCRIPTING_TYPE_MINIMAL(RenderContextBatch);
|
||||||
|
|
||||||
|
|||||||
@@ -216,20 +216,21 @@ GPUVertexLayout* GPUVertexLayout::Get(const Span<GPUVertexLayout*>& layouts)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUVertexLayout* GPUVertexLayout::Merge(GPUVertexLayout* base, GPUVertexLayout* reference, bool removeUnused, bool addMissing, int32 missingSlotOverride)
|
GPUVertexLayout* GPUVertexLayout::Merge(GPUVertexLayout* base, GPUVertexLayout* reference, bool removeUnused, bool addMissing, int32 missingSlotOverride, bool referenceOrder)
|
||||||
{
|
{
|
||||||
GPUVertexLayout* result = base ? base : reference;
|
GPUVertexLayout* result = base ? base : reference;
|
||||||
if (base && reference && base != reference)
|
if (base && reference && base != reference)
|
||||||
{
|
{
|
||||||
bool elementsModified = false;
|
bool elementsModified = false;
|
||||||
Elements newElements = base->GetElements();
|
Elements newElements = base->GetElements();
|
||||||
|
const Elements& refElements = reference->GetElements();
|
||||||
if (removeUnused)
|
if (removeUnused)
|
||||||
{
|
{
|
||||||
for (int32 i = newElements.Count() - 1; i >= 0; i--)
|
for (int32 i = newElements.Count() - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
bool missing = true;
|
bool missing = true;
|
||||||
const VertexElement& e = newElements.Get()[i];
|
const VertexElement& e = newElements.Get()[i];
|
||||||
for (const VertexElement& ee : reference->GetElements())
|
for (const VertexElement& ee : refElements)
|
||||||
{
|
{
|
||||||
if (ee.Type == e.Type)
|
if (ee.Type == e.Type)
|
||||||
{
|
{
|
||||||
@@ -247,7 +248,7 @@ GPUVertexLayout* GPUVertexLayout::Merge(GPUVertexLayout* base, GPUVertexLayout*
|
|||||||
}
|
}
|
||||||
if (addMissing)
|
if (addMissing)
|
||||||
{
|
{
|
||||||
for (const VertexElement& e : reference->GetElements())
|
for (const VertexElement& e : refElements)
|
||||||
{
|
{
|
||||||
bool missing = true;
|
bool missing = true;
|
||||||
for (const VertexElement& ee : base->GetElements())
|
for (const VertexElement& ee : base->GetElements())
|
||||||
@@ -282,6 +283,32 @@ GPUVertexLayout* GPUVertexLayout::Merge(GPUVertexLayout* base, GPUVertexLayout*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (referenceOrder)
|
||||||
|
{
|
||||||
|
for (int32 i = 0, j = 0; i < newElements.Count() && j < refElements.Count(); j++)
|
||||||
|
{
|
||||||
|
if (newElements[i].Type == refElements[j].Type)
|
||||||
|
{
|
||||||
|
// Elements match so move forward
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find reference element in a new list
|
||||||
|
for (int32 k = i + 1; k < newElements.Count(); k++)
|
||||||
|
{
|
||||||
|
if (newElements[k].Type == refElements[j].Type)
|
||||||
|
{
|
||||||
|
// Move matching element to the reference position
|
||||||
|
VertexElement e = newElements[k];
|
||||||
|
newElements.RemoveAt(k);
|
||||||
|
newElements.Insert(i, e);
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (elementsModified)
|
if (elementsModified)
|
||||||
result = Get(newElements, true);
|
result = Get(newElements, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,8 +84,9 @@ public:
|
|||||||
/// <param name="removeUnused">True to remove elements from base layout that don't exist in a reference layout.</param>
|
/// <param name="removeUnused">True to remove elements from base layout that don't exist in a reference layout.</param>
|
||||||
/// <param name="addMissing">True to add missing elements to base layout that exist in a reference layout.</param>
|
/// <param name="addMissing">True to add missing elements to base layout that exist in a reference layout.</param>
|
||||||
/// <param name="missingSlotOverride">Allows to override the input slot for missing elements. Use value -1 to inherit slot from the reference layout.</param>
|
/// <param name="missingSlotOverride">Allows to override the input slot for missing elements. Use value -1 to inherit slot from the reference layout.</param>
|
||||||
|
/// <param name="referenceOrder">True to reorder result elements to match the reference layout. For example, if input vertex buffer layout is different than vertex shader then it can match those.</param>
|
||||||
/// <returns>Vertex layout object. Doesn't need to be cleared as it's cached for an application lifetime.</returns>
|
/// <returns>Vertex layout object. Doesn't need to be cleared as it's cached for an application lifetime.</returns>
|
||||||
static GPUVertexLayout* Merge(GPUVertexLayout* base, GPUVertexLayout* reference, bool removeUnused = false, bool addMissing = true, int32 missingSlotOverride = -1);
|
static GPUVertexLayout* Merge(GPUVertexLayout* base, GPUVertexLayout* reference, bool removeUnused = false, bool addMissing = true, int32 missingSlotOverride = -1, bool referenceOrder = false);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// [GPUResource]
|
// [GPUResource]
|
||||||
|
|||||||
@@ -338,10 +338,10 @@ public:
|
|||||||
StreamTextureMipTask(StreamingTexture* texture, int32 mipIndex, Task* rootTask)
|
StreamTextureMipTask(StreamingTexture* texture, int32 mipIndex, Task* rootTask)
|
||||||
: GPUUploadTextureMipTask(texture->GetTexture(), mipIndex, Span<byte>(nullptr, 0), 0, 0, false)
|
: GPUUploadTextureMipTask(texture->GetTexture(), mipIndex, Span<byte>(nullptr, 0), 0, 0, false)
|
||||||
, _streamingTexture(texture)
|
, _streamingTexture(texture)
|
||||||
, _rootTask(rootTask ? rootTask : this)
|
, _rootTask(rootTask)
|
||||||
, _dataLock(_streamingTexture->GetOwner()->LockData())
|
, _dataLock(_streamingTexture->GetOwner()->LockData())
|
||||||
{
|
{
|
||||||
_streamingTexture->_streamingTasks.Add(_rootTask);
|
_streamingTexture->_streamingTasks.Add(this);
|
||||||
_texture.Released.Bind<StreamTextureMipTask, &StreamTextureMipTask::OnResourceReleased2>(this);
|
_texture.Released.Bind<StreamTextureMipTask, &StreamTextureMipTask::OnResourceReleased2>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,7 +357,7 @@ private:
|
|||||||
if (_streamingTexture)
|
if (_streamingTexture)
|
||||||
{
|
{
|
||||||
ScopeLock lock(_streamingTexture->GetOwner()->GetOwnerLocker());
|
ScopeLock lock(_streamingTexture->GetOwner()->GetOwnerLocker());
|
||||||
_streamingTexture->_streamingTasks.Remove(_rootTask);
|
_streamingTexture->_streamingTasks.Remove(this);
|
||||||
_streamingTexture = nullptr;
|
_streamingTexture = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -422,6 +422,15 @@ protected:
|
|||||||
|
|
||||||
GPUUploadTextureMipTask::OnFail();
|
GPUUploadTextureMipTask::OnFail();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnCancel() override
|
||||||
|
{
|
||||||
|
GPUUploadTextureMipTask::OnCancel();
|
||||||
|
|
||||||
|
// Cancel the root task too (eg. mip loading from asset)
|
||||||
|
if (_rootTask != nullptr)
|
||||||
|
_rootTask->Cancel();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Task* StreamingTexture::CreateStreamingTask(int32 residency)
|
Task* StreamingTexture::CreateStreamingTask(int32 residency)
|
||||||
|
|||||||
@@ -771,7 +771,7 @@ Task* TextureBase::RequestMipDataAsync(int32 mipIndex)
|
|||||||
|
|
||||||
FlaxStorage::LockData TextureBase::LockData()
|
FlaxStorage::LockData TextureBase::LockData()
|
||||||
{
|
{
|
||||||
return _parent->Storage ? _parent->Storage->Lock() : FlaxStorage::LockData::Invalid;
|
return _parent->Storage ? _parent->Storage->Lock() : FlaxStorage::LockData();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBase::GetMipData(int32 mipIndex, BytesContainer& data) const
|
void TextureBase::GetMipData(int32 mipIndex, BytesContainer& data) const
|
||||||
|
|||||||
@@ -724,7 +724,7 @@ void GPUContextDX11::SetState(GPUPipelineState* state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPUContextDX11::ClearState()
|
void GPUContextDX11::ResetState()
|
||||||
{
|
{
|
||||||
if (!_context)
|
if (!_context)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ public:
|
|||||||
void SetScissor(const Rectangle& scissorRect) override;
|
void SetScissor(const Rectangle& scissorRect) override;
|
||||||
GPUPipelineState* GetState() const override;
|
GPUPipelineState* GetState() const override;
|
||||||
void SetState(GPUPipelineState* state) override;
|
void SetState(GPUPipelineState* state) override;
|
||||||
void ClearState() override;
|
void ResetState() override;
|
||||||
void FlushState() override;
|
void FlushState() override;
|
||||||
void Flush() override;
|
void Flush() override;
|
||||||
void UpdateBuffer(GPUBuffer* buffer, const void* data, uint32 size, uint32 offset) override;
|
void UpdateBuffer(GPUBuffer* buffer, const void* data, uint32 size, uint32 offset) override;
|
||||||
|
|||||||
@@ -92,9 +92,8 @@ float GPUTimerQueryDX11::GetResult()
|
|||||||
{
|
{
|
||||||
if (!_finalized)
|
if (!_finalized)
|
||||||
{
|
{
|
||||||
#if BUILD_DEBUG
|
if (!HasResult())
|
||||||
ASSERT(HasResult());
|
return 0;
|
||||||
#endif
|
|
||||||
|
|
||||||
UINT64 timeStart, timeEnd;
|
UINT64 timeStart, timeEnd;
|
||||||
auto context = _device->GetIM();
|
auto context = _device->GetIM();
|
||||||
|
|||||||
@@ -143,6 +143,8 @@ void CommandQueueDX12::WaitForFence(uint64 fenceValue)
|
|||||||
|
|
||||||
void CommandQueueDX12::WaitForGPU()
|
void CommandQueueDX12::WaitForGPU()
|
||||||
{
|
{
|
||||||
|
PROFILE_CPU();
|
||||||
|
ZoneColor(TracyWaitZoneColor);
|
||||||
const uint64 value = _fence.Signal(this);
|
const uint64 value = _fence.Signal(this);
|
||||||
_fence.WaitCPU(value);
|
_fence.WaitCPU(value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ bool GPUBufferDX12::OnInit()
|
|||||||
// Create resource
|
// Create resource
|
||||||
ID3D12Resource* resource;
|
ID3D12Resource* resource;
|
||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS
|
||||||
D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_CREATE_NOT_ZEROED;
|
D3D12_HEAP_FLAGS heapFlags = EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::VertexBuffer | GPUBufferFlags::IndexBuffer) || _desc.InitData ? D3D12_HEAP_FLAG_CREATE_NOT_ZEROED : D3D12_HEAP_FLAG_NONE;
|
||||||
#else
|
#else
|
||||||
D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_NONE;
|
D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_NONE;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "GPUVertexLayoutDX12.h"
|
#include "GPUVertexLayoutDX12.h"
|
||||||
#include "CommandQueueDX12.h"
|
#include "CommandQueueDX12.h"
|
||||||
#include "DescriptorHeapDX12.h"
|
#include "DescriptorHeapDX12.h"
|
||||||
|
#include "RootSignatureDX12.h"
|
||||||
#include "Engine/Graphics/RenderTask.h"
|
#include "Engine/Graphics/RenderTask.h"
|
||||||
#include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h"
|
#include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h"
|
||||||
#include "Engine/Debug/Exceptions/NotImplementedException.h"
|
#include "Engine/Debug/Exceptions/NotImplementedException.h"
|
||||||
@@ -307,6 +308,7 @@ void GPUContextDX12::Reset()
|
|||||||
_device->DummyVB = _device->CreateBuffer(TEXT("DummyVertexBuffer"));
|
_device->DummyVB = _device->CreateBuffer(TEXT("DummyVertexBuffer"));
|
||||||
auto* layout = GPUVertexLayout::Get({ { VertexElement::Types::Attribute3, 0, 0, 0, PixelFormat::R32G32B32A32_Float } });
|
auto* layout = GPUVertexLayout::Get({ { VertexElement::Types::Attribute3, 0, 0, 0, PixelFormat::R32G32B32A32_Float } });
|
||||||
_device->DummyVB->Init(GPUBufferDescription::Vertex(layout, sizeof(Color), 1, &Color::Transparent));
|
_device->DummyVB->Init(GPUBufferDescription::Vertex(layout, sizeof(Color), 1, &Color::Transparent));
|
||||||
|
SetResourceState(_device->DummyVB, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, 0);
|
||||||
}
|
}
|
||||||
((GPUBufferDX12*)_device->DummyVB)->GetVBView(dummyVBView);
|
((GPUBufferDX12*)_device->DummyVB)->GetVBView(dummyVBView);
|
||||||
_commandList->IASetVertexBuffers(GPU_MAX_VB_BINDED, 1, &dummyVBView);
|
_commandList->IASetVertexBuffers(GPU_MAX_VB_BINDED, 1, &dummyVBView);
|
||||||
@@ -491,7 +493,7 @@ void GPUContextDX12::flushUAVs()
|
|||||||
ASSERT(uaCount <= GPU_MAX_UA_BINDED);
|
ASSERT(uaCount <= GPU_MAX_UA_BINDED);
|
||||||
|
|
||||||
// Fill table with source descriptors
|
// Fill table with source descriptors
|
||||||
DxShaderHeader& header = _currentCompute ? ((GPUShaderProgramCSDX12*)_currentCompute)->Header : _currentState->Header;
|
DxShaderHeader& header = _isCompute ? ((GPUShaderProgramCSDX12*)_currentCompute)->Header : _currentState->Header;
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE srcDescriptorRangeStarts[GPU_MAX_UA_BINDED];
|
D3D12_CPU_DESCRIPTOR_HANDLE srcDescriptorRangeStarts[GPU_MAX_UA_BINDED];
|
||||||
for (uint32 i = 0; i < uaCount; i++)
|
for (uint32 i = 0; i < uaCount; i++)
|
||||||
{
|
{
|
||||||
@@ -628,7 +630,9 @@ void GPUContextDX12::flushPS()
|
|||||||
LOG(Error, "Missing Vertex Layout (not assigned to GPUBuffer). Vertex Shader won't read valid data resulting incorrect visuals.");
|
LOG(Error, "Missing Vertex Layout (not assigned to GPUBuffer). Vertex Shader won't read valid data resulting incorrect visuals.");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
_commandList->SetPipelineState(_currentState->GetState(_rtDepth, _rtCount, _rtHandles, _vertexLayout));
|
ID3D12PipelineState* pso = _currentState->GetState(_rtDepth, _rtCount, _rtHandles, _vertexLayout);
|
||||||
|
ASSERT(pso);
|
||||||
|
_commandList->SetPipelineState(pso);
|
||||||
if (_primitiveTopology != _currentState->PrimitiveTopology)
|
if (_primitiveTopology != _currentState->PrimitiveTopology)
|
||||||
{
|
{
|
||||||
_primitiveTopology = _currentState->PrimitiveTopology;
|
_primitiveTopology = _currentState->PrimitiveTopology;
|
||||||
@@ -1300,7 +1304,7 @@ void GPUContextDX12::SetState(GPUPipelineState* state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPUContextDX12::ClearState()
|
void GPUContextDX12::ResetState()
|
||||||
{
|
{
|
||||||
if (!_commandList)
|
if (!_commandList)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ public:
|
|||||||
void SetScissor(const Rectangle& scissorRect) override;
|
void SetScissor(const Rectangle& scissorRect) override;
|
||||||
GPUPipelineState* GetState() const override;
|
GPUPipelineState* GetState() const override;
|
||||||
void SetState(GPUPipelineState* state) override;
|
void SetState(GPUPipelineState* state) override;
|
||||||
void ClearState() override;
|
void ResetState() override;
|
||||||
void FlushState() override;
|
void FlushState() override;
|
||||||
void Flush() override;
|
void Flush() override;
|
||||||
void UpdateBuffer(GPUBuffer* buffer, const void* data, uint32 size, uint32 offset) override;
|
void UpdateBuffer(GPUBuffer* buffer, const void* data, uint32 size, uint32 offset) override;
|
||||||
|
|||||||
@@ -12,6 +12,9 @@
|
|||||||
#include "GPUSamplerDX12.h"
|
#include "GPUSamplerDX12.h"
|
||||||
#include "GPUVertexLayoutDX12.h"
|
#include "GPUVertexLayoutDX12.h"
|
||||||
#include "GPUSwapChainDX12.h"
|
#include "GPUSwapChainDX12.h"
|
||||||
|
#include "RootSignatureDX12.h"
|
||||||
|
#include "UploadBufferDX12.h"
|
||||||
|
#include "CommandQueueDX12.h"
|
||||||
#include "Engine/Engine/Engine.h"
|
#include "Engine/Engine/Engine.h"
|
||||||
#include "Engine/Engine/CommandLine.h"
|
#include "Engine/Engine/CommandLine.h"
|
||||||
#include "Engine/Graphics/RenderTask.h"
|
#include "Engine/Graphics/RenderTask.h"
|
||||||
@@ -21,20 +24,23 @@
|
|||||||
#include "Engine/Profiler/ProfilerMemory.h"
|
#include "Engine/Profiler/ProfilerMemory.h"
|
||||||
#include "Engine/Core/Log.h"
|
#include "Engine/Core/Log.h"
|
||||||
#include "Engine/Core/Config/PlatformSettings.h"
|
#include "Engine/Core/Config/PlatformSettings.h"
|
||||||
#include "UploadBufferDX12.h"
|
#include "Engine/Core/Types/StringBuilder.h"
|
||||||
#include "CommandQueueDX12.h"
|
|
||||||
#include "Engine/Core/Utilities.h"
|
#include "Engine/Core/Utilities.h"
|
||||||
#include "Engine/Threading/Threading.h"
|
#include "Engine/Threading/Threading.h"
|
||||||
#include "CommandSignatureDX12.h"
|
#include "CommandSignatureDX12.h"
|
||||||
|
|
||||||
static bool CheckDX12Support(IDXGIAdapter* adapter)
|
static bool CheckDX12Support(IDXGIAdapter* adapter)
|
||||||
{
|
{
|
||||||
|
#if PLATFORM_XBOX_SCARLETT || PLATFORM_XBOX_ONE
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
// Try to create device
|
// Try to create device
|
||||||
if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
|
if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUVertexLayoutDX12::GPUVertexLayoutDX12(GPUDeviceDX12* device, const Elements& elements, bool explicitOffsets)
|
GPUVertexLayoutDX12::GPUVertexLayoutDX12(GPUDeviceDX12* device, const Elements& elements, bool explicitOffsets)
|
||||||
@@ -55,6 +61,310 @@ GPUVertexLayoutDX12::GPUVertexLayoutDX12(GPUDeviceDX12* device, const Elements&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RootSignatureDX12::RootSignatureDX12()
|
||||||
|
{
|
||||||
|
// Clear structures
|
||||||
|
Platform::MemoryClear(this, sizeof(*this));
|
||||||
|
|
||||||
|
// Descriptor tables
|
||||||
|
{
|
||||||
|
// SRVs
|
||||||
|
D3D12_DESCRIPTOR_RANGE& range = _ranges[0];
|
||||||
|
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
||||||
|
range.NumDescriptors = GPU_MAX_SR_BINDED;
|
||||||
|
range.BaseShaderRegister = 0;
|
||||||
|
range.RegisterSpace = 0;
|
||||||
|
range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// UAVs
|
||||||
|
D3D12_DESCRIPTOR_RANGE& range = _ranges[1];
|
||||||
|
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
|
||||||
|
range.NumDescriptors = GPU_MAX_UA_BINDED;
|
||||||
|
range.BaseShaderRegister = 0;
|
||||||
|
range.RegisterSpace = 0;
|
||||||
|
range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Samplers
|
||||||
|
D3D12_DESCRIPTOR_RANGE& range = _ranges[2];
|
||||||
|
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
|
||||||
|
range.NumDescriptors = GPU_MAX_SAMPLER_BINDED - GPU_STATIC_SAMPLERS_COUNT;
|
||||||
|
range.BaseShaderRegister = GPU_STATIC_SAMPLERS_COUNT;
|
||||||
|
range.RegisterSpace = 0;
|
||||||
|
range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Root parameters
|
||||||
|
for (int32 i = 0; i < GPU_MAX_CB_BINDED; i++)
|
||||||
|
{
|
||||||
|
// CBs
|
||||||
|
D3D12_ROOT_PARAMETER& param = _parameters[DX12_ROOT_SIGNATURE_CB + i];
|
||||||
|
param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
|
||||||
|
param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||||
|
param.Descriptor.ShaderRegister = i;
|
||||||
|
param.Descriptor.RegisterSpace = 0;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// SRVs
|
||||||
|
D3D12_ROOT_PARAMETER& param = _parameters[DX12_ROOT_SIGNATURE_SR];
|
||||||
|
param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||||
|
param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||||
|
param.DescriptorTable.NumDescriptorRanges = 1;
|
||||||
|
param.DescriptorTable.pDescriptorRanges = &_ranges[0];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// UAVs
|
||||||
|
D3D12_ROOT_PARAMETER& param = _parameters[DX12_ROOT_SIGNATURE_UA];
|
||||||
|
param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||||
|
param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||||
|
param.DescriptorTable.NumDescriptorRanges = 1;
|
||||||
|
param.DescriptorTable.pDescriptorRanges = &_ranges[1];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Samplers
|
||||||
|
D3D12_ROOT_PARAMETER& param = _parameters[DX12_ROOT_SIGNATURE_SAMPLER];
|
||||||
|
param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||||
|
param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||||
|
param.DescriptorTable.NumDescriptorRanges = 1;
|
||||||
|
param.DescriptorTable.pDescriptorRanges = &_ranges[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static samplers
|
||||||
|
static_assert(GPU_STATIC_SAMPLERS_COUNT == ARRAY_COUNT(_staticSamplers), "Update static samplers setup.");
|
||||||
|
// Linear Clamp
|
||||||
|
InitSampler(0, D3D12_FILTER_MIN_MAG_MIP_LINEAR, D3D12_TEXTURE_ADDRESS_MODE_CLAMP);
|
||||||
|
// Point Clamp
|
||||||
|
InitSampler(1, D3D12_FILTER_MIN_MAG_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_CLAMP);
|
||||||
|
// Linear Wrap
|
||||||
|
InitSampler(2, D3D12_FILTER_MIN_MAG_MIP_LINEAR, D3D12_TEXTURE_ADDRESS_MODE_WRAP);
|
||||||
|
// Point Wrap
|
||||||
|
InitSampler(3, D3D12_FILTER_MIN_MAG_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_WRAP);
|
||||||
|
// Shadow
|
||||||
|
InitSampler(4, D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_CLAMP, D3D12_COMPARISON_FUNC_LESS_EQUAL);
|
||||||
|
// Shadow PCF
|
||||||
|
InitSampler(5, D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR, D3D12_TEXTURE_ADDRESS_MODE_CLAMP, D3D12_COMPARISON_FUNC_LESS_EQUAL);
|
||||||
|
|
||||||
|
// Init
|
||||||
|
_desc.NumParameters = ARRAY_COUNT(_parameters);
|
||||||
|
_desc.pParameters = _parameters;
|
||||||
|
_desc.NumStaticSamplers = ARRAY_COUNT(_staticSamplers);
|
||||||
|
_desc.pStaticSamplers = _staticSamplers;
|
||||||
|
_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RootSignatureDX12::InitSampler(int32 i, D3D12_FILTER filter, D3D12_TEXTURE_ADDRESS_MODE address, D3D12_COMPARISON_FUNC comparisonFunc)
|
||||||
|
{
|
||||||
|
auto& sampler = _staticSamplers[i];
|
||||||
|
sampler.Filter = filter;
|
||||||
|
sampler.AddressU = address;
|
||||||
|
sampler.AddressV = address;
|
||||||
|
sampler.AddressW = address;
|
||||||
|
sampler.MipLODBias = 0.0f;
|
||||||
|
sampler.MaxAnisotropy = 1;
|
||||||
|
sampler.ComparisonFunc = comparisonFunc;
|
||||||
|
sampler.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;
|
||||||
|
sampler.MinLOD = 0;
|
||||||
|
sampler.MaxLOD = D3D12_FLOAT32_MAX;
|
||||||
|
sampler.ShaderRegister = i;
|
||||||
|
sampler.RegisterSpace = 0;
|
||||||
|
sampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComPtr<ID3DBlob> RootSignatureDX12::Serialize() const
|
||||||
|
{
|
||||||
|
ComPtr<ID3DBlob> signature;
|
||||||
|
ComPtr<ID3DBlob> error;
|
||||||
|
VALIDATE_DIRECTX_CALL(D3D12SerializeRootSignature(&_desc, D3D_ROOT_SIGNATURE_VERSION_1_0, &signature, &error));
|
||||||
|
if (error.Get())
|
||||||
|
{
|
||||||
|
LOG(Error, "D3D12SerializeRootSignature failed with error: {}", String((const char*)error->GetBufferPointer()));
|
||||||
|
}
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if USE_EDITOR
|
||||||
|
|
||||||
|
const Char* GetRootSignatureShaderVisibility(D3D12_SHADER_VISIBILITY visibility)
|
||||||
|
{
|
||||||
|
switch (visibility)
|
||||||
|
{
|
||||||
|
case D3D12_SHADER_VISIBILITY_VERTEX:
|
||||||
|
return TEXT(", visibility=SHADER_VISIBILITY_VERTEX");
|
||||||
|
case D3D12_SHADER_VISIBILITY_HULL:
|
||||||
|
return TEXT(", visibility=SHADER_VISIBILITY_HULL");
|
||||||
|
case D3D12_SHADER_VISIBILITY_DOMAIN:
|
||||||
|
return TEXT(", visibility=SHADER_VISIBILITY_DOMAIN");
|
||||||
|
case D3D12_SHADER_VISIBILITY_GEOMETRY:
|
||||||
|
return TEXT(", visibility=SHADER_VISIBILITY_GEOMETRY");
|
||||||
|
case D3D12_SHADER_VISIBILITY_PIXEL:
|
||||||
|
return TEXT(", visibility=SHADER_VISIBILITY_PIXEL");
|
||||||
|
case D3D12_SHADER_VISIBILITY_AMPLIFICATION:
|
||||||
|
return TEXT(", visibility=SHADER_VISIBILITY_AMPLIFICATION");
|
||||||
|
case D3D12_SHADER_VISIBILITY_MESH:
|
||||||
|
return TEXT(", visibility=SHADER_VISIBILITY_MESH");
|
||||||
|
case D3D12_SHADER_VISIBILITY_ALL:
|
||||||
|
default:
|
||||||
|
return TEXT(""); // Default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Char* GetRootSignatureSamplerFilter(D3D12_FILTER filter)
|
||||||
|
{
|
||||||
|
switch (filter)
|
||||||
|
{
|
||||||
|
case D3D12_FILTER_MIN_MAG_MIP_POINT:
|
||||||
|
return TEXT("FILTER_MIN_MAG_MIP_POINT");
|
||||||
|
case D3D12_FILTER_MIN_MAG_MIP_LINEAR:
|
||||||
|
return TEXT("FILTER_MIN_MAG_MIP_LINEAR");
|
||||||
|
case D3D12_FILTER_ANISOTROPIC:
|
||||||
|
return TEXT("FILTER_ANISOTROPIC");
|
||||||
|
case D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT:
|
||||||
|
return TEXT("FILTER_COMPARISON_MIN_MAG_MIP_POINT");
|
||||||
|
case D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR:
|
||||||
|
return TEXT("FILTER_COMPARISON_MIN_MAG_MIP_LINEAR");
|
||||||
|
default:
|
||||||
|
CRASH; // Not implemented
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Char* GetRootSignatureSamplerAddress(D3D12_TEXTURE_ADDRESS_MODE address)
|
||||||
|
{
|
||||||
|
switch (address)
|
||||||
|
{
|
||||||
|
case D3D12_TEXTURE_ADDRESS_MODE_WRAP:
|
||||||
|
return TEXT("TEXTURE_ADDRESS_WRAP");
|
||||||
|
case D3D12_TEXTURE_ADDRESS_MODE_MIRROR:
|
||||||
|
return TEXT("TEXTURE_ADDRESS_MIRROR");
|
||||||
|
case D3D12_TEXTURE_ADDRESS_MODE_CLAMP:
|
||||||
|
return TEXT("TEXTURE_ADDRESS_CLAMP");
|
||||||
|
case D3D12_TEXTURE_ADDRESS_MODE_BORDER:
|
||||||
|
return TEXT("TEXTURE_ADDRESS_BORDER");
|
||||||
|
case D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE:
|
||||||
|
return TEXT("TEXTURE_ADDRESS_MIRROR_ONCE");
|
||||||
|
default:
|
||||||
|
return TEXT("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Char* GetRootSignatureSamplerComparisonFunc(D3D12_COMPARISON_FUNC func)
|
||||||
|
{
|
||||||
|
switch (func)
|
||||||
|
{
|
||||||
|
case D3D12_COMPARISON_FUNC_NEVER:
|
||||||
|
return TEXT("COMPARISON_NEVER");
|
||||||
|
case D3D12_COMPARISON_FUNC_LESS:
|
||||||
|
return TEXT("COMPARISON_LESS");
|
||||||
|
case D3D12_COMPARISON_FUNC_EQUAL:
|
||||||
|
return TEXT("COMPARISON_EQUAL");
|
||||||
|
case D3D12_COMPARISON_FUNC_LESS_EQUAL:
|
||||||
|
return TEXT("COMPARISON_LESS_EQUAL");
|
||||||
|
case D3D12_COMPARISON_FUNC_GREATER:
|
||||||
|
return TEXT("COMPARISON_GREATER");
|
||||||
|
case D3D12_COMPARISON_FUNC_NOT_EQUAL:
|
||||||
|
return TEXT("COMPARISON_NOT_EQUAL");
|
||||||
|
case D3D12_COMPARISON_FUNC_GREATER_EQUAL:
|
||||||
|
return TEXT("COMPARISON_GREATER_EQUAL");
|
||||||
|
case D3D12_COMPARISON_FUNC_ALWAYS:
|
||||||
|
default:
|
||||||
|
return TEXT("COMPARISON_ALWAYS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RootSignatureDX12::ToString(StringBuilder& sb, bool singleLine) const
|
||||||
|
{
|
||||||
|
// Flags
|
||||||
|
sb.Append(TEXT("RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT)"));
|
||||||
|
|
||||||
|
// Parameters
|
||||||
|
const Char newLine = singleLine ? ' ' : '\n';
|
||||||
|
for (const D3D12_ROOT_PARAMETER& param : _parameters)
|
||||||
|
{
|
||||||
|
const Char* visibility = GetRootSignatureShaderVisibility(param.ShaderVisibility);
|
||||||
|
switch (param.ParameterType)
|
||||||
|
{
|
||||||
|
case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:
|
||||||
|
sb.AppendFormat(TEXT(",{}DescriptorTable("), newLine);
|
||||||
|
for (uint32 rangeIndex = 0; rangeIndex < param.DescriptorTable.NumDescriptorRanges; rangeIndex++)
|
||||||
|
{
|
||||||
|
if (rangeIndex)
|
||||||
|
sb.Append(TEXT(", "));
|
||||||
|
const D3D12_DESCRIPTOR_RANGE& range = param.DescriptorTable.pDescriptorRanges[rangeIndex];
|
||||||
|
switch (range.RangeType)
|
||||||
|
{
|
||||||
|
case D3D12_DESCRIPTOR_RANGE_TYPE_SRV:
|
||||||
|
sb.AppendFormat(TEXT("SRV(t{}"), range.BaseShaderRegister);
|
||||||
|
break;
|
||||||
|
case D3D12_DESCRIPTOR_RANGE_TYPE_UAV:
|
||||||
|
sb.AppendFormat(TEXT("UAV(u{}"), range.BaseShaderRegister);
|
||||||
|
break;
|
||||||
|
case D3D12_DESCRIPTOR_RANGE_TYPE_CBV:
|
||||||
|
sb.AppendFormat(TEXT("CBV(b{}"), range.BaseShaderRegister);
|
||||||
|
break;
|
||||||
|
case D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER:
|
||||||
|
sb.AppendFormat(TEXT("Sampler(s{}"), range.BaseShaderRegister);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (range.NumDescriptors != 1)
|
||||||
|
{
|
||||||
|
if (range.NumDescriptors == UINT_MAX)
|
||||||
|
sb.Append(TEXT(", numDescriptors=unbounded"));
|
||||||
|
else
|
||||||
|
sb.AppendFormat(TEXT(", numDescriptors={}"), range.NumDescriptors);
|
||||||
|
}
|
||||||
|
if (range.OffsetInDescriptorsFromTableStart != D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)
|
||||||
|
sb.AppendFormat(TEXT(", offset={}"), range.OffsetInDescriptorsFromTableStart);
|
||||||
|
sb.Append(')');
|
||||||
|
}
|
||||||
|
sb.AppendFormat(TEXT("{})"), visibility);
|
||||||
|
break;
|
||||||
|
case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:
|
||||||
|
sb.AppendFormat(TEXT(",{}RootConstants(num32BitConstants={}, b{}{})"), newLine, param.Constants.Num32BitValues, param.Constants.ShaderRegister, visibility);
|
||||||
|
break;
|
||||||
|
case D3D12_ROOT_PARAMETER_TYPE_CBV:
|
||||||
|
sb.AppendFormat(TEXT(",{}CBV(b{}{})"), newLine, param.Descriptor.ShaderRegister, visibility);
|
||||||
|
break;
|
||||||
|
case D3D12_ROOT_PARAMETER_TYPE_SRV:
|
||||||
|
sb.AppendFormat(TEXT(",{}SRV(t{}{})"), newLine, param.Descriptor.ShaderRegister, visibility);
|
||||||
|
break;
|
||||||
|
case D3D12_ROOT_PARAMETER_TYPE_UAV:
|
||||||
|
sb.AppendFormat(TEXT(",{}UAV(u{}{})"), newLine, param.Descriptor.ShaderRegister, visibility);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static Samplers
|
||||||
|
for (const D3D12_STATIC_SAMPLER_DESC& sampler : _staticSamplers)
|
||||||
|
{
|
||||||
|
const Char* visibility = GetRootSignatureShaderVisibility(sampler.ShaderVisibility);
|
||||||
|
sb.AppendFormat(TEXT(",{}StaticSampler(s{}"), newLine, sampler.ShaderRegister);
|
||||||
|
sb.AppendFormat(TEXT(", filter={}"), GetRootSignatureSamplerFilter(sampler.Filter));
|
||||||
|
sb.AppendFormat(TEXT(", addressU={}"), GetRootSignatureSamplerAddress(sampler.AddressU));
|
||||||
|
sb.AppendFormat(TEXT(", addressV={}"), GetRootSignatureSamplerAddress(sampler.AddressV));
|
||||||
|
sb.AppendFormat(TEXT(", addressW={}"), GetRootSignatureSamplerAddress(sampler.AddressW));
|
||||||
|
sb.AppendFormat(TEXT(", comparisonFunc={}"), GetRootSignatureSamplerComparisonFunc(sampler.ComparisonFunc));
|
||||||
|
sb.AppendFormat(TEXT(", maxAnisotropy={}"), sampler.MaxAnisotropy);
|
||||||
|
sb.Append(TEXT(", borderColor=STATIC_BORDER_COLOR_OPAQUE_BLACK"));
|
||||||
|
sb.AppendFormat(TEXT("{})"), visibility);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String RootSignatureDX12::ToString() const
|
||||||
|
{
|
||||||
|
StringBuilder sb;
|
||||||
|
ToString(sb);
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
StringAnsi RootSignatureDX12::ToStringAnsi() const
|
||||||
|
{
|
||||||
|
StringBuilder sb;
|
||||||
|
ToString(sb);
|
||||||
|
return sb.ToStringAnsi();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
GPUDevice* GPUDeviceDX12::Create()
|
GPUDevice* GPUDeviceDX12::Create()
|
||||||
{
|
{
|
||||||
#if PLATFORM_XBOX_SCARLETT || PLATFORM_XBOX_ONE
|
#if PLATFORM_XBOX_SCARLETT || PLATFORM_XBOX_ONE
|
||||||
@@ -318,6 +628,7 @@ bool GPUDeviceDX12::Init()
|
|||||||
VALIDATE_DIRECTX_CALL(dxgiAdapter->EnumOutputs(0, dxgiOutput.GetAddressOf()));
|
VALIDATE_DIRECTX_CALL(dxgiAdapter->EnumOutputs(0, dxgiOutput.GetAddressOf()));
|
||||||
DXGI_FORMAT backbufferFormat = RenderToolsDX::ToDxgiFormat(GPU_BACK_BUFFER_PIXEL_FORMAT);
|
DXGI_FORMAT backbufferFormat = RenderToolsDX::ToDxgiFormat(GPU_BACK_BUFFER_PIXEL_FORMAT);
|
||||||
UINT modesCount = 0;
|
UINT modesCount = 0;
|
||||||
|
#ifdef _GAMING_XBOX_SCARLETT
|
||||||
VALIDATE_DIRECTX_CALL(dxgiOutput->GetDisplayModeList(backbufferFormat, 0, &modesCount, NULL));
|
VALIDATE_DIRECTX_CALL(dxgiOutput->GetDisplayModeList(backbufferFormat, 0, &modesCount, NULL));
|
||||||
Array<DXGIXBOX_MODE_DESC> modes;
|
Array<DXGIXBOX_MODE_DESC> modes;
|
||||||
modes.Resize((int32)modesCount);
|
modes.Resize((int32)modesCount);
|
||||||
@@ -332,6 +643,11 @@ bool GPUDeviceDX12::Init()
|
|||||||
videoOutput.RefreshRate = Math::Max(videoOutput.RefreshRate, mode.RefreshRate.Numerator / (float)mode.RefreshRate.Denominator);
|
videoOutput.RefreshRate = Math::Max(videoOutput.RefreshRate, mode.RefreshRate.Numerator / (float)mode.RefreshRate.Denominator);
|
||||||
}
|
}
|
||||||
modes.Resize(0);
|
modes.Resize(0);
|
||||||
|
#else
|
||||||
|
videoOutput.Width = 1920;
|
||||||
|
videoOutput.Height = 1080;
|
||||||
|
videoOutput.RefreshRate = 60;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if PLATFORM_GDK
|
#if PLATFORM_GDK
|
||||||
GDKPlatform::Suspended.Bind<GPUDeviceDX12, &GPUDeviceDX12::OnSuspended>(this);
|
GDKPlatform::Suspended.Bind<GPUDeviceDX12, &GPUDeviceDX12::OnSuspended>(this);
|
||||||
@@ -561,170 +877,10 @@ bool GPUDeviceDX12::Init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create root signature
|
// Create root signature
|
||||||
// TODO: maybe create set of different root signatures? for UAVs, for compute, for simple drawing, for post fx?
|
|
||||||
{
|
{
|
||||||
// Descriptor tables
|
RootSignatureDX12 signature;
|
||||||
D3D12_DESCRIPTOR_RANGE r[3]; // SRV+UAV+Sampler
|
ComPtr<ID3DBlob> signatureBlob = signature.Serialize();
|
||||||
{
|
VALIDATE_DIRECTX_CALL(_device->CreateRootSignature(0, signatureBlob->GetBufferPointer(), signatureBlob->GetBufferSize(), IID_PPV_ARGS(&_rootSignature)));
|
||||||
D3D12_DESCRIPTOR_RANGE& range = r[0];
|
|
||||||
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
|
||||||
range.NumDescriptors = GPU_MAX_SR_BINDED;
|
|
||||||
range.BaseShaderRegister = 0;
|
|
||||||
range.RegisterSpace = 0;
|
|
||||||
range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
D3D12_DESCRIPTOR_RANGE& range = r[1];
|
|
||||||
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
|
|
||||||
range.NumDescriptors = GPU_MAX_UA_BINDED;
|
|
||||||
range.BaseShaderRegister = 0;
|
|
||||||
range.RegisterSpace = 0;
|
|
||||||
range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
D3D12_DESCRIPTOR_RANGE& range = r[2];
|
|
||||||
range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
|
|
||||||
range.NumDescriptors = GPU_MAX_SAMPLER_BINDED - GPU_STATIC_SAMPLERS_COUNT;
|
|
||||||
range.BaseShaderRegister = GPU_STATIC_SAMPLERS_COUNT;
|
|
||||||
range.RegisterSpace = 0;
|
|
||||||
range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Root parameters
|
|
||||||
D3D12_ROOT_PARAMETER rootParameters[GPU_MAX_CB_BINDED + 3];
|
|
||||||
for (int32 i = 0; i < GPU_MAX_CB_BINDED; i++)
|
|
||||||
{
|
|
||||||
// CB
|
|
||||||
D3D12_ROOT_PARAMETER& rootParam = rootParameters[DX12_ROOT_SIGNATURE_CB + i];
|
|
||||||
rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
|
|
||||||
rootParam.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
||||||
rootParam.Descriptor.ShaderRegister = i;
|
|
||||||
rootParam.Descriptor.RegisterSpace = 0;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// SRVs
|
|
||||||
D3D12_ROOT_PARAMETER& rootParam = rootParameters[DX12_ROOT_SIGNATURE_SR];
|
|
||||||
rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
|
||||||
rootParam.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
||||||
rootParam.DescriptorTable.NumDescriptorRanges = 1;
|
|
||||||
rootParam.DescriptorTable.pDescriptorRanges = &r[0];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// UAVs
|
|
||||||
D3D12_ROOT_PARAMETER& rootParam = rootParameters[DX12_ROOT_SIGNATURE_UA];
|
|
||||||
rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
|
||||||
rootParam.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
||||||
rootParam.DescriptorTable.NumDescriptorRanges = 1;
|
|
||||||
rootParam.DescriptorTable.pDescriptorRanges = &r[1];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
// Samplers
|
|
||||||
D3D12_ROOT_PARAMETER& rootParam = rootParameters[DX12_ROOT_SIGNATURE_SAMPLER];
|
|
||||||
rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
|
||||||
rootParam.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
||||||
rootParam.DescriptorTable.NumDescriptorRanges = 1;
|
|
||||||
rootParam.DescriptorTable.pDescriptorRanges = &r[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Static samplers
|
|
||||||
D3D12_STATIC_SAMPLER_DESC staticSamplers[6];
|
|
||||||
static_assert(GPU_STATIC_SAMPLERS_COUNT == ARRAY_COUNT(staticSamplers), "Update static samplers setup.");
|
|
||||||
// Linear Clamp
|
|
||||||
staticSamplers[0].Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
|
||||||
staticSamplers[0].AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
||||||
staticSamplers[0].AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
||||||
staticSamplers[0].AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
||||||
staticSamplers[0].MipLODBias = 0.0f;
|
|
||||||
staticSamplers[0].MaxAnisotropy = 1;
|
|
||||||
staticSamplers[0].BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;
|
|
||||||
staticSamplers[0].MinLOD = 0;
|
|
||||||
staticSamplers[0].MaxLOD = D3D12_FLOAT32_MAX;
|
|
||||||
staticSamplers[0].ShaderRegister = 0;
|
|
||||||
staticSamplers[0].RegisterSpace = 0;
|
|
||||||
staticSamplers[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
||||||
// Point Clamp
|
|
||||||
staticSamplers[1].Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
|
||||||
staticSamplers[1].AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
||||||
staticSamplers[1].AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
||||||
staticSamplers[1].AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
||||||
staticSamplers[1].MipLODBias = 0.0f;
|
|
||||||
staticSamplers[1].MaxAnisotropy = 1;
|
|
||||||
staticSamplers[1].BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;
|
|
||||||
staticSamplers[1].MinLOD = 0;
|
|
||||||
staticSamplers[1].MaxLOD = D3D12_FLOAT32_MAX;
|
|
||||||
staticSamplers[1].ShaderRegister = 1;
|
|
||||||
staticSamplers[1].RegisterSpace = 0;
|
|
||||||
staticSamplers[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
||||||
// Linear Wrap
|
|
||||||
staticSamplers[2].Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
|
||||||
staticSamplers[2].AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
|
||||||
staticSamplers[2].AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
|
||||||
staticSamplers[2].AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
|
||||||
staticSamplers[2].MipLODBias = 0.0f;
|
|
||||||
staticSamplers[2].MaxAnisotropy = 1;
|
|
||||||
staticSamplers[2].BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;
|
|
||||||
staticSamplers[2].MinLOD = 0;
|
|
||||||
staticSamplers[2].MaxLOD = D3D12_FLOAT32_MAX;
|
|
||||||
staticSamplers[2].ShaderRegister = 2;
|
|
||||||
staticSamplers[2].RegisterSpace = 0;
|
|
||||||
staticSamplers[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
||||||
// Point Wrap
|
|
||||||
staticSamplers[3].Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
|
||||||
staticSamplers[3].AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
|
||||||
staticSamplers[3].AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
|
||||||
staticSamplers[3].AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
|
||||||
staticSamplers[3].MipLODBias = 0.0f;
|
|
||||||
staticSamplers[3].MaxAnisotropy = 1;
|
|
||||||
staticSamplers[3].BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;
|
|
||||||
staticSamplers[3].MinLOD = 0;
|
|
||||||
staticSamplers[3].MaxLOD = D3D12_FLOAT32_MAX;
|
|
||||||
staticSamplers[3].ShaderRegister = 3;
|
|
||||||
staticSamplers[3].RegisterSpace = 0;
|
|
||||||
staticSamplers[3].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
||||||
// Shadow
|
|
||||||
staticSamplers[4].Filter = D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT;
|
|
||||||
staticSamplers[4].AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
||||||
staticSamplers[4].AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
||||||
staticSamplers[4].AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
||||||
staticSamplers[4].MipLODBias = 0.0f;
|
|
||||||
staticSamplers[4].MaxAnisotropy = 1;
|
|
||||||
staticSamplers[4].ComparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
|
|
||||||
staticSamplers[4].BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;
|
|
||||||
staticSamplers[4].MinLOD = 0;
|
|
||||||
staticSamplers[4].MaxLOD = D3D12_FLOAT32_MAX;
|
|
||||||
staticSamplers[4].ShaderRegister = 4;
|
|
||||||
staticSamplers[4].RegisterSpace = 0;
|
|
||||||
staticSamplers[4].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
||||||
// Shadow PCF
|
|
||||||
staticSamplers[5].Filter = D3D12_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR;
|
|
||||||
staticSamplers[5].AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
||||||
staticSamplers[5].AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
||||||
staticSamplers[5].AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
|
||||||
staticSamplers[5].MipLODBias = 0.0f;
|
|
||||||
staticSamplers[5].MaxAnisotropy = 1;
|
|
||||||
staticSamplers[5].ComparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
|
|
||||||
staticSamplers[5].BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK;
|
|
||||||
staticSamplers[5].MinLOD = 0;
|
|
||||||
staticSamplers[5].MaxLOD = D3D12_FLOAT32_MAX;
|
|
||||||
staticSamplers[5].ShaderRegister = 5;
|
|
||||||
staticSamplers[5].RegisterSpace = 0;
|
|
||||||
staticSamplers[5].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
|
||||||
|
|
||||||
// Init
|
|
||||||
D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc;
|
|
||||||
rootSignatureDesc.NumParameters = ARRAY_COUNT(rootParameters);
|
|
||||||
rootSignatureDesc.pParameters = rootParameters;
|
|
||||||
rootSignatureDesc.NumStaticSamplers = ARRAY_COUNT(staticSamplers);
|
|
||||||
rootSignatureDesc.pStaticSamplers = staticSamplers;
|
|
||||||
rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
|
||||||
|
|
||||||
// Serialize
|
|
||||||
ComPtr<ID3DBlob> signature;
|
|
||||||
ComPtr<ID3DBlob> error;
|
|
||||||
VALIDATE_DIRECTX_CALL(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));
|
|
||||||
|
|
||||||
// Create
|
|
||||||
VALIDATE_DIRECTX_CALL(_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&_rootSignature)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TimestampQueryHeap.Init())
|
if (TimestampQueryHeap.Init())
|
||||||
|
|||||||
@@ -18,11 +18,6 @@
|
|||||||
#define DX12_BACK_BUFFER_COUNT 2
|
#define DX12_BACK_BUFFER_COUNT 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DX12_ROOT_SIGNATURE_CB 0
|
|
||||||
#define DX12_ROOT_SIGNATURE_SR (GPU_MAX_CB_BINDED+0)
|
|
||||||
#define DX12_ROOT_SIGNATURE_UA (GPU_MAX_CB_BINDED+1)
|
|
||||||
#define DX12_ROOT_SIGNATURE_SAMPLER (GPU_MAX_CB_BINDED+2)
|
|
||||||
|
|
||||||
class Engine;
|
class Engine;
|
||||||
class WindowsWindow;
|
class WindowsWindow;
|
||||||
class GPUContextDX12;
|
class GPUContextDX12;
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ bool GPUTextureDX12::OnInit()
|
|||||||
initialState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
|
initialState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
|
||||||
|
|
||||||
// Create texture
|
// Create texture
|
||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS && 0
|
||||||
D3D12_HEAP_FLAGS heapFlags = useRTV || useDSV ? D3D12_HEAP_FLAG_CREATE_NOT_ZEROED : D3D12_HEAP_FLAG_NONE;
|
D3D12_HEAP_FLAGS heapFlags = useRTV || useDSV ? D3D12_HEAP_FLAG_CREATE_NOT_ZEROED : D3D12_HEAP_FLAG_NONE;
|
||||||
#else
|
#else
|
||||||
D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_NONE;
|
D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_NONE;
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Engine/Graphics/Config.h"
|
||||||
|
#include "../IncludeDirectXHeaders.h"
|
||||||
|
|
||||||
|
#define DX12_ROOT_SIGNATURE_CB 0
|
||||||
|
#define DX12_ROOT_SIGNATURE_SR (GPU_MAX_CB_BINDED+0)
|
||||||
|
#define DX12_ROOT_SIGNATURE_UA (GPU_MAX_CB_BINDED+1)
|
||||||
|
#define DX12_ROOT_SIGNATURE_SAMPLER (GPU_MAX_CB_BINDED+2)
|
||||||
|
|
||||||
|
struct RootSignatureDX12
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
D3D12_ROOT_SIGNATURE_DESC _desc;
|
||||||
|
D3D12_DESCRIPTOR_RANGE _ranges[3];
|
||||||
|
D3D12_ROOT_PARAMETER _parameters[GPU_MAX_CB_BINDED + 3];
|
||||||
|
D3D12_STATIC_SAMPLER_DESC _staticSamplers[6];
|
||||||
|
|
||||||
|
public:
|
||||||
|
RootSignatureDX12();
|
||||||
|
|
||||||
|
ComPtr<ID3DBlob> Serialize() const;
|
||||||
|
#if USE_EDITOR
|
||||||
|
void ToString(class StringBuilder& sb, bool singleLine = false) const;
|
||||||
|
String ToString() const;
|
||||||
|
StringAnsi ToStringAnsi() const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
void InitSampler(int32 i, D3D12_FILTER filter, D3D12_TEXTURE_ADDRESS_MODE address, D3D12_COMPARISON_FUNC comparisonFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL);
|
||||||
|
};
|
||||||
@@ -177,7 +177,7 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearState() override
|
void ResetState() override
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ GPUContextVulkan::GPUContextVulkan(GPUDeviceVulkan* device, QueueVulkan* queue)
|
|||||||
#if GPU_ENABLE_TRACY
|
#if GPU_ENABLE_TRACY
|
||||||
#if VK_EXT_calibrated_timestamps && VK_EXT_host_query_reset && !PLATFORM_SWITCH
|
#if VK_EXT_calibrated_timestamps && VK_EXT_host_query_reset && !PLATFORM_SWITCH
|
||||||
// Use calibrated timestamps extension
|
// Use calibrated timestamps extension
|
||||||
if (vkResetQueryPoolEXT && vkGetCalibratedTimestampsEXT)
|
if (vkResetQueryPoolEXT && vkGetCalibratedTimestampsEXT && _device->PhysicalDeviceFeatures12.hostQueryReset)
|
||||||
{
|
{
|
||||||
_tracyContext = tracy::CreateVkContext(_device->Adapter->Gpu, _device->Device, vkResetQueryPoolEXT, vkGetPhysicalDeviceCalibrateableTimeDomainsEXT, vkGetCalibratedTimestampsEXT);
|
_tracyContext = tracy::CreateVkContext(_device->Adapter->Gpu, _device->Device, vkResetQueryPoolEXT, vkGetPhysicalDeviceCalibrateableTimeDomainsEXT, vkGetCalibratedTimestampsEXT);
|
||||||
}
|
}
|
||||||
@@ -192,6 +192,7 @@ void GPUContextVulkan::AddImageBarrier(VkImage image, VkImageLayout srcLayout, V
|
|||||||
|
|
||||||
void GPUContextVulkan::AddImageBarrier(GPUTextureViewVulkan* handle, VkImageLayout dstLayout)
|
void GPUContextVulkan::AddImageBarrier(GPUTextureViewVulkan* handle, VkImageLayout dstLayout)
|
||||||
{
|
{
|
||||||
|
ASSERT(handle->Owner);
|
||||||
auto& state = handle->Owner->State;
|
auto& state = handle->Owner->State;
|
||||||
const auto subresourceIndex = handle->SubresourceIndex;
|
const auto subresourceIndex = handle->SubresourceIndex;
|
||||||
if (subresourceIndex == -1)
|
if (subresourceIndex == -1)
|
||||||
@@ -516,7 +517,7 @@ void GPUContextVulkan::UpdateDescriptorSets(const SpirvShaderDescriptorInfo& des
|
|||||||
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
||||||
{
|
{
|
||||||
auto handle = (GPUTextureViewVulkan*)handles[slot];
|
auto handle = (GPUTextureViewVulkan*)handles[slot];
|
||||||
if (!handle)
|
if (!handle || !handle->Owner)
|
||||||
{
|
{
|
||||||
const auto dummy = _device->HelperResources.GetDummyTexture(descriptor.ResourceType);
|
const auto dummy = _device->HelperResources.GetDummyTexture(descriptor.ResourceType);
|
||||||
switch (descriptor.ResourceType)
|
switch (descriptor.ResourceType)
|
||||||
@@ -1328,7 +1329,7 @@ void GPUContextVulkan::SetState(GPUPipelineState* state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPUContextVulkan::ClearState()
|
void GPUContextVulkan::ResetState()
|
||||||
{
|
{
|
||||||
ResetRenderTarget();
|
ResetRenderTarget();
|
||||||
ResetSR();
|
ResetSR();
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ public:
|
|||||||
void SetScissor(const Rectangle& scissorRect) override;
|
void SetScissor(const Rectangle& scissorRect) override;
|
||||||
GPUPipelineState* GetState() const override;
|
GPUPipelineState* GetState() const override;
|
||||||
void SetState(GPUPipelineState* state) override;
|
void SetState(GPUPipelineState* state) override;
|
||||||
void ClearState() override;
|
void ResetState() override;
|
||||||
void FlushState() override;
|
void FlushState() override;
|
||||||
void Flush() override;
|
void Flush() override;
|
||||||
void UpdateBuffer(GPUBuffer* buffer, const void* data, uint32 size, uint32 offset) override;
|
void UpdateBuffer(GPUBuffer* buffer, const void* data, uint32 size, uint32 offset) override;
|
||||||
|
|||||||
@@ -1568,7 +1568,15 @@ bool GPUDeviceVulkan::Init()
|
|||||||
vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queueCount, QueueFamilyProps.Get());
|
vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queueCount, QueueFamilyProps.Get());
|
||||||
|
|
||||||
// Query device features
|
// Query device features
|
||||||
|
RenderToolsVulkan::ZeroStruct(PhysicalDeviceFeatures12, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES);
|
||||||
vkGetPhysicalDeviceFeatures(gpu, &PhysicalDeviceFeatures);
|
vkGetPhysicalDeviceFeatures(gpu, &PhysicalDeviceFeatures);
|
||||||
|
if (vkGetPhysicalDeviceFeatures2)
|
||||||
|
{
|
||||||
|
VkPhysicalDeviceFeatures2 features2;
|
||||||
|
RenderToolsVulkan::ZeroStruct(features2, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2);
|
||||||
|
features2.pNext = &PhysicalDeviceFeatures12;
|
||||||
|
vkGetPhysicalDeviceFeatures2(gpu, &features2);
|
||||||
|
}
|
||||||
|
|
||||||
// Get extensions and layers
|
// Get extensions and layers
|
||||||
Array<const char*> deviceExtensions;
|
Array<const char*> deviceExtensions;
|
||||||
@@ -1671,6 +1679,16 @@ bool GPUDeviceVulkan::Init()
|
|||||||
VulkanPlatform::RestrictEnabledPhysicalDeviceFeatures(PhysicalDeviceFeatures, enabledFeatures);
|
VulkanPlatform::RestrictEnabledPhysicalDeviceFeatures(PhysicalDeviceFeatures, enabledFeatures);
|
||||||
deviceInfo.pEnabledFeatures = &enabledFeatures;
|
deviceInfo.pEnabledFeatures = &enabledFeatures;
|
||||||
|
|
||||||
|
#if GPU_ENABLE_TRACY && VK_EXT_calibrated_timestamps && VK_EXT_host_query_reset
|
||||||
|
VkPhysicalDeviceHostQueryResetFeatures resetFeatures;
|
||||||
|
if (PhysicalDeviceFeatures12.hostQueryReset)
|
||||||
|
{
|
||||||
|
RenderToolsVulkan::ZeroStruct(resetFeatures, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES);
|
||||||
|
resetFeatures.hostQueryReset = VK_TRUE;
|
||||||
|
deviceInfo.pNext = &resetFeatures;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Create the device
|
// Create the device
|
||||||
VALIDATE_VULKAN_RESULT(vkCreateDevice(gpu, &deviceInfo, nullptr, &Device));
|
VALIDATE_VULKAN_RESULT(vkCreateDevice(gpu, &deviceInfo, nullptr, &Device));
|
||||||
|
|
||||||
|
|||||||
@@ -496,6 +496,7 @@ public:
|
|||||||
/// The physical device enabled features.
|
/// The physical device enabled features.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
VkPhysicalDeviceFeatures PhysicalDeviceFeatures;
|
VkPhysicalDeviceFeatures PhysicalDeviceFeatures;
|
||||||
|
VkPhysicalDeviceVulkan12Features PhysicalDeviceFeatures12;
|
||||||
|
|
||||||
Array<BufferedQueryPoolVulkan*> TimestampQueryPools;
|
Array<BufferedQueryPoolVulkan*> TimestampQueryPools;
|
||||||
Array<BufferedQueryPoolVulkan*> OcclusionQueryPools;
|
Array<BufferedQueryPoolVulkan*> OcclusionQueryPools;
|
||||||
|
|||||||
@@ -554,10 +554,11 @@ void AnimatedModel::StopSlotAnimation(const StringView& slotName, Animation* ani
|
|||||||
{
|
{
|
||||||
for (auto& slot : GraphInstance.Slots)
|
for (auto& slot : GraphInstance.Slots)
|
||||||
{
|
{
|
||||||
if (slot.Animation == anim && slot.Name == slotName)
|
if ((slot.Animation == anim || anim == nullptr) && slot.Name == slotName)
|
||||||
{
|
{
|
||||||
//slot.Animation = nullptr; // TODO: make an immediate version of this method and set the animation to nullptr.
|
//slot.Animation = nullptr; // TODO: make an immediate version of this method and set the animation to nullptr.
|
||||||
slot.Reset = true;
|
if (slot.Animation != nullptr)
|
||||||
|
slot.Reset = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -573,7 +574,7 @@ void AnimatedModel::PauseSlotAnimation(const StringView& slotName, Animation* an
|
|||||||
{
|
{
|
||||||
for (auto& slot : GraphInstance.Slots)
|
for (auto& slot : GraphInstance.Slots)
|
||||||
{
|
{
|
||||||
if (slot.Animation == anim && slot.Name == slotName)
|
if ((slot.Animation == anim || anim == nullptr) && slot.Name == slotName)
|
||||||
{
|
{
|
||||||
slot.Pause = true;
|
slot.Pause = true;
|
||||||
break;
|
break;
|
||||||
@@ -595,7 +596,7 @@ bool AnimatedModel::IsPlayingSlotAnimation(const StringView& slotName, Animation
|
|||||||
{
|
{
|
||||||
for (auto& slot : GraphInstance.Slots)
|
for (auto& slot : GraphInstance.Slots)
|
||||||
{
|
{
|
||||||
if (slot.Animation == anim && slot.Name == slotName && !slot.Pause)
|
if ((slot.Animation == anim || anim == nullptr) && slot.Name == slotName && !slot.Pause)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -412,8 +412,8 @@ public:
|
|||||||
/// Stops the animation playback on the slot in Anim Graph.
|
/// Stops the animation playback on the slot in Anim Graph.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="slotName">The name of the slot.</param>
|
/// <param name="slotName">The name of the slot.</param>
|
||||||
/// <param name="anim">The animation to stop.</param>
|
/// <param name="anim">The animation to check. Null to use slot name only.</param>
|
||||||
API_FUNCTION() void StopSlotAnimation(const StringView& slotName, Animation* anim);
|
API_FUNCTION() void StopSlotAnimation(const StringView& slotName, Animation* anim = nullptr);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pauses all the animations playback on the all slots in Anim Graph.
|
/// Pauses all the animations playback on the all slots in Anim Graph.
|
||||||
@@ -424,8 +424,8 @@ public:
|
|||||||
/// Pauses the animation playback on the slot in Anim Graph.
|
/// Pauses the animation playback on the slot in Anim Graph.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="slotName">The name of the slot.</param>
|
/// <param name="slotName">The name of the slot.</param>
|
||||||
/// <param name="anim">The animation to pause.</param>
|
/// <param name="anim">The animation to check. Null to use slot name only.</param>
|
||||||
API_FUNCTION() void PauseSlotAnimation(const StringView& slotName, Animation* anim);
|
API_FUNCTION() void PauseSlotAnimation(const StringView& slotName, Animation* anim = nullptr);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if any animation playback is active on any slot in Anim Graph (not paused).
|
/// Checks if any animation playback is active on any slot in Anim Graph (not paused).
|
||||||
@@ -436,8 +436,8 @@ public:
|
|||||||
/// Checks if the animation playback is active on the slot in Anim Graph (not paused).
|
/// Checks if the animation playback is active on the slot in Anim Graph (not paused).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="slotName">The name of the slot.</param>
|
/// <param name="slotName">The name of the slot.</param>
|
||||||
/// <param name="anim">The animation to check.</param>
|
/// <param name="anim">The animation to check. Null to use slot name only.</param>
|
||||||
API_FUNCTION() bool IsPlayingSlotAnimation(const StringView& slotName, Animation* anim);
|
API_FUNCTION() bool IsPlayingSlotAnimation(const StringView& slotName, Animation* anim = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ApplyRootMotion(const Transform& rootMotionDelta);
|
void ApplyRootMotion(const Transform& rootMotionDelta);
|
||||||
|
|||||||
@@ -42,38 +42,38 @@ public:
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The reflections texture resolution.
|
/// The reflections texture resolution.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD(Attributes="EditorOrder(0), EditorDisplay(\"Probe\")")
|
API_FIELD(Attributes="EditorOrder(0), EditorDisplay(\"Quality\")")
|
||||||
ProbeCubemapResolution CubemapResolution = ProbeCubemapResolution::UseGraphicsSettings;
|
ProbeCubemapResolution CubemapResolution = ProbeCubemapResolution::UseGraphicsSettings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The probe update mode.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(Attributes = "EditorOrder(10), EditorDisplay(\"Quality\")")
|
||||||
|
ProbeUpdateMode UpdateMode = ProbeUpdateMode::Manual;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The reflections brightness.
|
/// The reflections brightness.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD(Attributes="EditorOrder(10), Limit(0, 1000, 0.01f), EditorDisplay(\"Probe\")")
|
API_FIELD(Attributes="EditorOrder(0), Limit(0, 1000, 0.01f), EditorDisplay(\"Probe\")")
|
||||||
float Brightness = 1.0f;
|
float Brightness = 1.0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The probe rendering order. The higher values are render later (on top).
|
/// The probe rendering order. The higher values are render later (on top).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD(Attributes = "EditorOrder(25), EditorDisplay(\"Probe\")")
|
API_FIELD(Attributes = "EditorOrder(20), EditorDisplay(\"Probe\")")
|
||||||
int32 SortOrder = 0;
|
int32 SortOrder = 0;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The probe update mode.
|
|
||||||
/// </summary>
|
|
||||||
API_FIELD(Attributes="EditorOrder(30), EditorDisplay(\"Probe\")")
|
|
||||||
ProbeUpdateMode UpdateMode = ProbeUpdateMode::Manual;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The probe capture camera near plane distance.
|
/// The probe capture camera near plane distance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD(Attributes="EditorOrder(30), Limit(0, float.MaxValue, 0.01f), EditorDisplay(\"Probe\")")
|
API_FIELD(Attributes="EditorOrder(25), Limit(0, float.MaxValue, 0.01f), EditorDisplay(\"Probe\")")
|
||||||
float CaptureNearPlane = 10.0f;
|
float CaptureNearPlane = 10.0f;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the probe radius.
|
/// Gets the probe radius.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_PROPERTY(Attributes="EditorOrder(20), DefaultValue(3000.0f), Limit(0), EditorDisplay(\"Probe\")")
|
API_PROPERTY(Attributes="EditorOrder(15), DefaultValue(3000.0f), Limit(0), EditorDisplay(\"Probe\")")
|
||||||
float GetRadius() const;
|
float GetRadius() const;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -518,7 +518,7 @@ namespace
|
|||||||
Vector3 nextPos = transform.LocalToWorld(next->Value.Translation);
|
Vector3 nextPos = transform.LocalToWorld(next->Value.Translation);
|
||||||
DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(nextPos, NodeSizeByDistance(nextPos, scaleByDistance)), color, 0.0f, depthTest);
|
DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(nextPos, NodeSizeByDistance(nextPos, scaleByDistance)), color, 0.0f, depthTest);
|
||||||
const float d = (next->Time - prev->Time) / 3.0f;
|
const float d = (next->Time - prev->Time) / 3.0f;
|
||||||
DEBUG_DRAW_BEZIER(prevPos, prevPos + prev->TangentOut.Translation * d, nextPos + next->TangentIn.Translation * d, nextPos, color, 0.0f, depthTest);
|
DEBUG_DRAW_BEZIER(prevPos, transform.LocalToWorld(prev->Value.Translation + prev->TangentOut.Translation * d), transform.LocalToWorld(next->Value.Translation + next->TangentIn.Translation * d), nextPos, color, 0.0f, depthTest);
|
||||||
prev = next;
|
prev = next;
|
||||||
prevPos = nextPos;
|
prevPos = nextPos;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const Char* GetCommandLine(int argc, char* argv[])
|
|||||||
const Char* cmdLine;
|
const Char* cmdLine;
|
||||||
if (length != 0)
|
if (length != 0)
|
||||||
{
|
{
|
||||||
Char* str = (Char*)malloc(length * sizeof(Char));
|
Char* str = (Char*)malloc((length + 1) * sizeof(Char));
|
||||||
cmdLine = str;
|
cmdLine = str;
|
||||||
for (int i = 1; i < argc; i++)
|
for (int i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Internal version number of networking implementation. Updated once engine changes serialization or connection rules.
|
// Internal version number of networking implementation. Updated once engine changes serialization or connection rules.
|
||||||
#define NETWORK_PROTOCOL_VERSION 4
|
#define NETWORK_PROTOCOL_VERSION 5
|
||||||
|
|
||||||
// Enables encoding object ids and typenames via uint32 keys rather than full data send.
|
// Enables encoding object ids and typenames via uint32 keys rather than full data send.
|
||||||
#define USE_NETWORK_KEYS 1
|
#define USE_NETWORK_KEYS 1
|
||||||
@@ -29,6 +29,7 @@ enum class NetworkMessageIDs : uint8
|
|||||||
ObjectDespawn,
|
ObjectDespawn,
|
||||||
ObjectRole,
|
ObjectRole,
|
||||||
ObjectRpc,
|
ObjectRpc,
|
||||||
|
ObjectRpcPart,
|
||||||
|
|
||||||
MAX,
|
MAX,
|
||||||
};
|
};
|
||||||
@@ -48,6 +49,7 @@ public:
|
|||||||
static void OnNetworkMessageObjectDespawn(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer);
|
static void OnNetworkMessageObjectDespawn(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer);
|
||||||
static void OnNetworkMessageObjectRole(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer);
|
static void OnNetworkMessageObjectRole(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer);
|
||||||
static void OnNetworkMessageObjectRpc(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer);
|
static void OnNetworkMessageObjectRpc(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer);
|
||||||
|
static void OnNetworkMessageObjectRpcPart(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer);
|
||||||
|
|
||||||
#if COMPILE_WITH_PROFILER
|
#if COMPILE_WITH_PROFILER
|
||||||
|
|
||||||
|
|||||||
@@ -391,6 +391,7 @@ namespace
|
|||||||
NetworkInternal::OnNetworkMessageObjectDespawn,
|
NetworkInternal::OnNetworkMessageObjectDespawn,
|
||||||
NetworkInternal::OnNetworkMessageObjectRole,
|
NetworkInternal::OnNetworkMessageObjectRole,
|
||||||
NetworkInternal::OnNetworkMessageObjectRpc,
|
NetworkInternal::OnNetworkMessageObjectRpc,
|
||||||
|
NetworkInternal::OnNetworkMessageObjectRpcPart,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user