Merge branch 'master' of https://github.com/Menotdan/FlaxEngine into material_import
Merge Upstream Changes.
This commit is contained in:
@@ -11,16 +11,6 @@ for %%I in (Source\Logo.png) do if %%~zI LSS 2000 (
|
||||
call "Development\Scripts\Windows\GetMSBuildPath.bat"
|
||||
if errorlevel 1 goto Error_NoVisualStudioEnvironment
|
||||
|
||||
if not exist "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" goto Compile
|
||||
for /f "delims=" %%i in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere" -latest -products * -requires Microsoft.Component.MSBuild -property installationPath') do (
|
||||
for %%j in (15.0, Current) do (
|
||||
if exist "%%i\MSBuild\%%j\Bin\MSBuild.exe" (
|
||||
set MSBUILD_PATH="%%i\MSBuild\%%j\Bin\MSBuild.exe"
|
||||
goto Compile
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
:Compile
|
||||
md Cache\Intermediate >nul 2>nul
|
||||
dir /s /b Source\Tools\Flax.Build\*.cs >Cache\Intermediate\Flax.Build.Files.txt
|
||||
@@ -44,7 +34,7 @@ goto Exit
|
||||
echo CallBuildTool ERROR: The script is in invalid directory.
|
||||
goto Exit
|
||||
:Error_NoVisualStudioEnvironment
|
||||
echo CallBuildTool ERROR: Missing Visual Studio 2015 or newer.
|
||||
echo CallBuildTool ERROR: Missing Visual Studio 2022 or newer.
|
||||
goto Exit
|
||||
:Error_CompilationFailed
|
||||
echo CallBuildTool ERROR: Failed to compile Flax.Build project.
|
||||
|
||||
@@ -4,66 +4,26 @@ rem Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||
|
||||
set MSBUILD_PATH=
|
||||
|
||||
rem Look for MSBuild version 17.0 or later
|
||||
if not exist "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" goto VsWhereNotFound
|
||||
for /f "delims=" %%i in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere" -latest -products * -requires Microsoft.Component.MSBuild -property installationPath') do (
|
||||
if exist "%%i\MSBuild\15.0\Bin\MSBuild.exe" (
|
||||
set MSBUILD_PATH="%%i\MSBuild\15.0\Bin\MSBuild.exe"
|
||||
goto End
|
||||
)
|
||||
)
|
||||
for /f "delims=" %%i in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere" -latest -prerelease -products * -requires Microsoft.Component.MSBuild -property installationPath') do (
|
||||
if exist "%%i\MSBuild\15.0\Bin\MSBuild.exe" (
|
||||
set MSBUILD_PATH="%%i\MSBuild\15.0\Bin\MSBuild.exe"
|
||||
goto End
|
||||
)
|
||||
for /f "delims=" %%i in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere" -version 17.0 -latest -products * -requires Microsoft.Component.MSBuild -property installationPath') do (
|
||||
if exist "%%i\MSBuild\Current\Bin\MSBuild.exe" (
|
||||
set MSBUILD_PATH="%%i\MSBuild\Current\Bin\MSBuild.exe"
|
||||
goto End
|
||||
)
|
||||
)
|
||||
:VsWhereNotFound
|
||||
|
||||
if exist "%ProgramFiles(x86)%\MSBuild\14.0\bin\MSBuild.exe" (
|
||||
set MSBUILD_PATH="%ProgramFiles(x86)%\MSBuild\14.0\bin\MSBuild.exe"
|
||||
goto End
|
||||
rem Look for MSBuild version 17.0 or later in pre-release versions
|
||||
for /f "delims=" %%i in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere" -version 17.0 -latest -prerelease -products * -requires Microsoft.Component.MSBuild -property installationPath') do (
|
||||
if exist "%%i\MSBuild\Current\Bin\MSBuild.exe" (
|
||||
set MSBUILD_PATH="%%i\MSBuild\Current\Bin\MSBuild.exe"
|
||||
goto End
|
||||
)
|
||||
)
|
||||
|
||||
call :GetInstallPath Microsoft\VisualStudio\SxS\VS7 15.0 MSBuild\15.0\bin\MSBuild.exe
|
||||
if not errorlevel 1 goto End
|
||||
call :GetInstallPath Microsoft\MSBuild\ToolsVersions\14.0 MSBuildToolsPath MSBuild.exe
|
||||
if not errorlevel 1 goto End
|
||||
call :GetInstallPath Microsoft\MSBuild\ToolsVersions\12.0 MSBuildToolsPath MSBuild.exe
|
||||
if not errorlevel 1 goto End
|
||||
call :GetInstallPath Microsoft\MSBuild\ToolsVersions\4.0 MSBuildToolsPath MSBuild.exe
|
||||
if not errorlevel 1 goto End
|
||||
|
||||
echo GetMSBuildPath ERROR: Could not find MSBuild version 17.0 or later.
|
||||
exit /B 1
|
||||
:VsWhereNotFound
|
||||
echo GetMSBuildPath ERROR: vswhere.exe was not found.
|
||||
exit /B 1
|
||||
:End
|
||||
exit /B 0
|
||||
|
||||
:GetInstallPath
|
||||
for /f "tokens=2,*" %%A in ('REG.exe query HKCU\SOFTWARE\%1 /v %2 2^>Nul') do (
|
||||
if exist "%%B%%3" (
|
||||
set MSBUILD_PATH="%%B%3"
|
||||
exit /B 0
|
||||
)
|
||||
)
|
||||
for /f "tokens=2,*" %%A in ('REG.exe query HKLM\SOFTWARE\%1 /v %2 2^>Nul') do (
|
||||
if exist "%%B%3" (
|
||||
set MSBUILD_PATH="%%B%3"
|
||||
exit /B 0
|
||||
)
|
||||
)
|
||||
for /f "tokens=2,*" %%A in ('REG.exe query HKCU\SOFTWARE\Wow6432Node\%1 /v %2 2^>Nul') do (
|
||||
if exist "%%B%%3" (
|
||||
set MSBUILD_PATH="%%B%3"
|
||||
exit /B 0
|
||||
)
|
||||
)
|
||||
for /f "tokens=2,*" %%A in ('REG.exe query HKLM\SOFTWARE\Wow6432Node\%1 /v %2 2^>Nul') do (
|
||||
if exist "%%B%3" (
|
||||
set MSBUILD_PATH="%%B%3"
|
||||
exit /B 0
|
||||
)
|
||||
)
|
||||
exit /B 1
|
||||
exit /B 0
|
||||
@@ -3,7 +3,7 @@
|
||||
"Version": {
|
||||
"Major": 1,
|
||||
"Minor": 6,
|
||||
"Build": 6344
|
||||
"Build": 6345
|
||||
},
|
||||
"Company": "Flax",
|
||||
"Copyright": "Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.",
|
||||
|
||||
@@ -31,19 +31,20 @@ Follow the instructions below to compile and run the engine from source.
|
||||
* Install Visual Studio 2022 or newer
|
||||
* Install Windows 8.1 SDK or newer (via Visual Studio Installer)
|
||||
* Install Microsoft Visual C++ 2015 v140 toolset or newer (via Visual Studio Installer)
|
||||
* Install .Net 7 SDK (via Visual Studio Installer or [from web](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
||||
* Install .NET 7 SDK for **Windows x64** (via Visual Studio Installer or [from web](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
||||
* Install Git with LFS
|
||||
* Clone repo (with LFS)
|
||||
* Run **GenerateProjectFiles.bat**
|
||||
* Open `Flax.sln` and set solution configuration to **Editor.Development** and solution platform to **Win64**
|
||||
* Set Flax (C++) or FlaxEngine (C#) as startup project
|
||||
* Compile Flax project (hit F7 or CTRL+Shift+B)
|
||||
* Optionally set Debug Type to **Managed Only (.NET Core)** to debug C#-only, or **Mixed (.NET Core)** to debug both C++ and C#
|
||||
* Run Flax (hit F5 key)
|
||||
|
||||
## Linux
|
||||
|
||||
* Install Visual Studio Code
|
||||
* Install .Net 7 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/7.0](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
||||
* Install .NET 7 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/7.0](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
||||
* Ubuntu: `sudo apt install dotnet-sdk-7.0`
|
||||
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
|
||||
* Ubuntu: `sudo apt install vulkan-sdk`
|
||||
@@ -66,7 +67,7 @@ Follow the instructions below to compile and run the engine from source.
|
||||
## Mac
|
||||
|
||||
* Install XCode
|
||||
* Install .Net 7 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/7.0](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
||||
* Install .NET 7 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/7.0](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
||||
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
|
||||
* Clone repo (with LFS)
|
||||
* Run `GenerateProjectFiles.command`
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "MacPlatformTools.h"
|
||||
#include "Engine/Platform/File.h"
|
||||
#include "Engine/Platform/FileSystem.h"
|
||||
#include "Engine/Platform/CreateProcessSettings.h"
|
||||
#include "Engine/Platform/Mac/MacPlatformSettings.h"
|
||||
#include "Engine/Core/Config/GameSettings.h"
|
||||
#include "Engine/Core/Config/BuildSettings.h"
|
||||
@@ -124,17 +125,35 @@ bool MacPlatformTools::OnPostProcess(CookingData& data)
|
||||
LOG(Error, "Failed to export application icon.");
|
||||
return true;
|
||||
}
|
||||
bool failed = Platform::RunProcess(TEXT("sips -z 16 16 icon_1024x1024.png --out icon_16x16.png"), tmpFolderPath);
|
||||
failed |= Platform::RunProcess(TEXT("sips -z 32 32 icon_1024x1024.png --out icon_16x16@2x.png"), tmpFolderPath);
|
||||
failed |= Platform::RunProcess(TEXT("sips -z 32 32 icon_1024x1024.png --out icon_32x32.png"), tmpFolderPath);
|
||||
failed |= Platform::RunProcess(TEXT("sips -z 64 64 icon_1024x1024.png --out icon_32x32@2x.png"), tmpFolderPath);
|
||||
failed |= Platform::RunProcess(TEXT("sips -z 128 128 icon_1024x1024.png --out icon_128x128.png"), tmpFolderPath);
|
||||
failed |= Platform::RunProcess(TEXT("sips -z 256 256 icon_1024x1024.png --out icon_128x128@2x.png"), tmpFolderPath);
|
||||
failed |= Platform::RunProcess(TEXT("sips -z 256 256 icon_1024x1024.png --out icon_256x256.png"), tmpFolderPath);
|
||||
failed |= Platform::RunProcess(TEXT("sips -z 512 512 icon_1024x1024.png --out icon_256x256@2x.png"), tmpFolderPath);
|
||||
failed |= Platform::RunProcess(TEXT("sips -z 512 512 icon_1024x1024.png --out icon_512x512.png"), tmpFolderPath);
|
||||
failed |= Platform::RunProcess(TEXT("sips -z 1024 1024 icon_1024x1024.png --out icon_512x512@2x.png"), tmpFolderPath);
|
||||
failed |= Platform::RunProcess(TEXT("iconutil -c icns icon.iconset"), iconFolderPath);
|
||||
CreateProcessSettings procSettings;
|
||||
procSettings.HiddenWindow = true;
|
||||
procSettings.FileName = TEXT("/usr/bin/sips");
|
||||
procSettings.WorkingDirectory = tmpFolderPath;
|
||||
procSettings.Arguments = TEXT("-z 16 16 icon_1024x1024.png --out icon_16x16.png");
|
||||
bool failed = false;
|
||||
failed |= Platform::CreateProcess(procSettings);
|
||||
procSettings.Arguments = TEXT("-z 32 32 icon_1024x1024.png --out icon_16x16@2x.png");
|
||||
failed |= Platform::CreateProcess(procSettings);
|
||||
procSettings.Arguments = TEXT("-z 32 32 icon_1024x1024.png --out icon_32x32.png");
|
||||
failed |= Platform::CreateProcess(procSettings);
|
||||
procSettings.Arguments = TEXT("-z 64 64 icon_1024x1024.png --out icon_32x32@2x.png");
|
||||
failed |= Platform::CreateProcess(procSettings);
|
||||
procSettings.Arguments = TEXT("-z 128 128 icon_1024x1024.png --out icon_128x128.png");
|
||||
failed |= Platform::CreateProcess(procSettings);
|
||||
procSettings.Arguments = TEXT("-z 256 256 icon_1024x1024.png --out icon_128x128@2x.png");
|
||||
failed |= Platform::CreateProcess(procSettings);
|
||||
procSettings.Arguments = TEXT("-z 256 256 icon_1024x1024.png --out icon_256x256.png");
|
||||
failed |= Platform::CreateProcess(procSettings);
|
||||
procSettings.Arguments = TEXT("-z 512 512 icon_1024x1024.png --out icon_256x256@2x.png");
|
||||
failed |= Platform::CreateProcess(procSettings);
|
||||
procSettings.Arguments = TEXT("-z 512 512 icon_1024x1024.png --out icon_512x512.png");
|
||||
failed |= Platform::CreateProcess(procSettings);
|
||||
procSettings.Arguments = TEXT("-z 1024 1024 icon_1024x1024.png --out icon_512x512@2x.png");
|
||||
failed |= Platform::CreateProcess(procSettings);
|
||||
procSettings.FileName = TEXT("/usr/bin/iconutil");
|
||||
procSettings.Arguments = TEXT("-c icns icon.iconset");
|
||||
procSettings.WorkingDirectory = iconFolderPath;
|
||||
failed |= Platform::CreateProcess(procSettings);
|
||||
if (failed)
|
||||
{
|
||||
LOG(Error, "Failed to export application icon.");
|
||||
@@ -210,16 +229,22 @@ bool MacPlatformTools::OnPostProcess(CookingData& data)
|
||||
return false;
|
||||
GameCooker::PackageFiles();
|
||||
LOG(Info, "Building app package...");
|
||||
const String dmgPath = data.OriginalOutputPath / appName + TEXT(".dmg");
|
||||
const String dmgCommand = String::Format(TEXT("hdiutil create {0}.dmg -volname {0} -fs HFS+ -srcfolder {0}.app"), appName);
|
||||
const int32 result = Platform::RunProcess(dmgCommand, data.OriginalOutputPath);
|
||||
if (result != 0)
|
||||
{
|
||||
data.Error(String::Format(TEXT("Failed to package app (result code: {0}). See log for more info."), result));
|
||||
return true;
|
||||
const String dmgPath = data.OriginalOutputPath / appName + TEXT(".dmg");
|
||||
CreateProcessSettings procSettings;
|
||||
procSettings.HiddenWindow = true;
|
||||
procSettings.WorkingDirectory = data.OriginalOutputPath;
|
||||
procSettings.FileName = TEXT("/usr/bin/hdiutil");
|
||||
procSettings.Arguments = String::Format(TEXT("create {0}.dmg -volname {0} -fs HFS+ -srcfolder {0}.app"), appName);
|
||||
const int32 result = Platform::CreateProcess(procSettings);
|
||||
if (result != 0)
|
||||
{
|
||||
data.Error(String::Format(TEXT("Failed to package app (result code: {0}). See log for more info."), result));
|
||||
return true;
|
||||
}
|
||||
// TODO: sign dmg
|
||||
LOG(Info, "Output application package: {0} (size: {1} MB)", dmgPath, FileSystem::GetFileSize(dmgPath) / 1024 / 1024);
|
||||
}
|
||||
// TODO: sign dmg
|
||||
LOG(Info, "Output application package: {0} (size: {1} MB)", dmgPath, FileSystem::GetFileSize(dmgPath) / 1024 / 1024);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -260,15 +260,20 @@ bool iOSPlatformTools::OnPostProcess(CookingData& data)
|
||||
{
|
||||
LOG(Info, "Building app package...");
|
||||
const Char* configuration = data.Configuration == BuildConfiguration::Release ? TEXT("Release") : TEXT("Debug");
|
||||
String command = String::Format(TEXT("xcodebuild -project FlaxGame.xcodeproj -configuration {} -scheme FlaxGame -archivePath FlaxGame.xcarchive archive"), configuration);
|
||||
int32 result = Platform::RunProcess(command, data.OriginalOutputPath);
|
||||
CreateProcessSettings procSettings;
|
||||
procSettings.HiddenWindow = true;
|
||||
procSettings.WorkingDirectory = data.OriginalOutputPath;
|
||||
procSettings.FileName = TEXT("/usr/bin/xcodebuild");
|
||||
procSettings.Arguments = String::Format(TEXT("-project FlaxGame.xcodeproj -configuration {} -scheme FlaxGame -archivePath FlaxGame.xcarchive archive"), configuration);
|
||||
int32 result = Platform::CreateProcess(procSettings);
|
||||
if (result != 0)
|
||||
{
|
||||
data.Error(String::Format(TEXT("Failed to package app (result code: {0}). See log for more info."), result));
|
||||
return true;
|
||||
}
|
||||
command = TEXT("xcodebuild -exportArchive -archivePath FlaxGame.xcarchive -allowProvisioningUpdates -exportPath . -exportOptionsPlist ExportOptions.plist");
|
||||
result = Platform::RunProcess(command, data.OriginalOutputPath);
|
||||
procSettings.FileName = TEXT("/usr/bin/xcodebuild");
|
||||
procSettings.Arguments = TEXT("-exportArchive -archivePath FlaxGame.xcarchive -allowProvisioningUpdates -exportPath . -exportOptionsPlist ExportOptions.plist");
|
||||
result = Platform::CreateProcess(procSettings);
|
||||
if (result != 0)
|
||||
{
|
||||
data.Error(String::Format(TEXT("Failed to package app (result code: {0}). See log for more info."), result));
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using FlaxEditor.CustomEditors.GUI;
|
||||
using FlaxEditor.GUI;
|
||||
using FlaxEditor.GUI.ContextMenu;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
|
||||
namespace FlaxEditor.CustomEditors.Editors
|
||||
{
|
||||
@@ -12,7 +14,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
[CustomEditor(typeof(InputEvent)), DefaultEditor]
|
||||
public class InputEventEditor : CustomEditor
|
||||
{
|
||||
private Dropdown _dropdown;
|
||||
private ComboBox _comboBox;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DisplayStyle Style => DisplayStyle.Inline;
|
||||
@@ -20,23 +22,30 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
/// <inheritdoc />
|
||||
public override void Initialize(LayoutElementsContainer layout)
|
||||
{
|
||||
var dropdownElement = layout.Custom<Dropdown>();
|
||||
_dropdown = dropdownElement.CustomControl;
|
||||
var names = new List<LocalizedString>();
|
||||
LinkedLabel.SetupContextMenu += OnSetupContextMenu;
|
||||
var comboBoxElement = layout.ComboBox();
|
||||
_comboBox = comboBoxElement.ComboBox;
|
||||
var names = new List<string>();
|
||||
foreach (var mapping in Input.ActionMappings)
|
||||
{
|
||||
if (!names.Contains(mapping.Name))
|
||||
names.Add(mapping.Name);
|
||||
}
|
||||
_dropdown.Items = names;
|
||||
_comboBox.Items = names;
|
||||
if (Values[0] is InputEvent inputEvent && names.Contains(inputEvent.Name))
|
||||
_dropdown.SelectedItem = inputEvent.Name;
|
||||
_dropdown.SelectedIndexChanged += OnSelectedIndexChanged;
|
||||
_comboBox.SelectedItem = inputEvent.Name;
|
||||
_comboBox.SelectedIndexChanged += OnSelectedIndexChanged;
|
||||
}
|
||||
|
||||
private void OnSelectedIndexChanged(Dropdown dropdown)
|
||||
private void OnSetupContextMenu(PropertyNameLabel label, ContextMenu menu, CustomEditor linkededitor)
|
||||
{
|
||||
SetValue(new InputEvent(dropdown.SelectedItem));
|
||||
var button = menu.AddButton("Set to null");
|
||||
button.Clicked += () => _comboBox.SelectedItem = null;
|
||||
}
|
||||
|
||||
private void OnSelectedIndexChanged(ComboBox comboBox)
|
||||
{
|
||||
SetValue(comboBox.SelectedItem == null ? null : new InputEvent(comboBox.SelectedItem));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -49,17 +58,21 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Values[0] is InputEvent inputEvent && _dropdown.Items.Contains(inputEvent.Name))
|
||||
_dropdown.SelectedItem = inputEvent.Name;
|
||||
if (Values[0] is InputEvent inputEvent && _comboBox.Items.Contains(inputEvent.Name))
|
||||
_comboBox.SelectedItem = inputEvent.Name;
|
||||
else
|
||||
_comboBox.SelectedItem = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Deinitialize()
|
||||
{
|
||||
if (_dropdown != null)
|
||||
_dropdown.SelectedIndexChanged -= OnSelectedIndexChanged;
|
||||
_dropdown = null;
|
||||
if (LinkedLabel != null)
|
||||
LinkedLabel.SetupContextMenu -= OnSetupContextMenu;
|
||||
if (_comboBox != null)
|
||||
_comboBox.SelectedIndexChanged -= OnSelectedIndexChanged;
|
||||
_comboBox = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +82,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
[CustomEditor(typeof(InputAxis)), DefaultEditor]
|
||||
public class InputAxisEditor : CustomEditor
|
||||
{
|
||||
private Dropdown _dropdown;
|
||||
private ComboBox _comboBox;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DisplayStyle Style => DisplayStyle.Inline;
|
||||
@@ -77,23 +90,30 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
/// <inheritdoc />
|
||||
public override void Initialize(LayoutElementsContainer layout)
|
||||
{
|
||||
var dropdownElement = layout.Custom<Dropdown>();
|
||||
_dropdown = dropdownElement.CustomControl;
|
||||
var names = new List<LocalizedString>();
|
||||
LinkedLabel.SetupContextMenu += OnSetupContextMenu;
|
||||
var comboBoxElement = layout.ComboBox();
|
||||
_comboBox = comboBoxElement.ComboBox;
|
||||
var names = new List<string>();
|
||||
foreach (var mapping in Input.AxisMappings)
|
||||
{
|
||||
if (!names.Contains(mapping.Name))
|
||||
names.Add(mapping.Name);
|
||||
}
|
||||
_dropdown.Items = names;
|
||||
_comboBox.Items = names;
|
||||
if (Values[0] is InputAxis inputAxis && names.Contains(inputAxis.Name))
|
||||
_dropdown.SelectedItem = inputAxis.Name;
|
||||
_dropdown.SelectedIndexChanged += OnSelectedIndexChanged;
|
||||
_comboBox.SelectedItem = inputAxis.Name;
|
||||
_comboBox.SelectedIndexChanged += OnSelectedIndexChanged;
|
||||
}
|
||||
|
||||
private void OnSelectedIndexChanged(Dropdown dropdown)
|
||||
private void OnSetupContextMenu(PropertyNameLabel label, ContextMenu menu, CustomEditor linkededitor)
|
||||
{
|
||||
SetValue(new InputAxis(dropdown.SelectedItem));
|
||||
var button = menu.AddButton("Set to null");
|
||||
button.Clicked += () => _comboBox.SelectedItem = null;
|
||||
}
|
||||
|
||||
private void OnSelectedIndexChanged(ComboBox comboBox)
|
||||
{
|
||||
SetValue(comboBox.SelectedItem == null ? null : new InputAxis(comboBox.SelectedItem));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -106,17 +126,21 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Values[0] is InputAxis inputAxis && _dropdown.Items.Contains(inputAxis.Name))
|
||||
_dropdown.SelectedItem = inputAxis.Name;
|
||||
if (Values[0] is InputAxis inputAxis && _comboBox.Items.Contains(inputAxis.Name))
|
||||
_comboBox.SelectedItem = inputAxis.Name;
|
||||
else
|
||||
_comboBox.SelectedItem = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Deinitialize()
|
||||
{
|
||||
if (_dropdown != null)
|
||||
_dropdown.SelectedIndexChanged -= OnSelectedIndexChanged;
|
||||
_dropdown = null;
|
||||
if (LinkedLabel != null)
|
||||
LinkedLabel.SetupContextMenu -= OnSetupContextMenu;
|
||||
if (_comboBox != null)
|
||||
_comboBox.SelectedIndexChanged -= OnSelectedIndexChanged;
|
||||
_comboBox = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -545,7 +545,7 @@ namespace FlaxEditor.GUI
|
||||
Render2D.DrawRectangle(clientRect.MakeExpanded(-2.0f), borderColor);
|
||||
|
||||
// Check if has selected item
|
||||
if (_selectedIndices.Count > 0)
|
||||
if (_selectedIndices != null && _selectedIndices.Count > 0)
|
||||
{
|
||||
string text = _selectedIndices.Count == 1 ? _items[_selectedIndices[0]] : "Multiple Values";
|
||||
|
||||
|
||||
@@ -290,7 +290,11 @@ namespace FlaxEditor.GUI.Dialogs
|
||||
OnCancel();
|
||||
return true;
|
||||
case KeyboardKeys.Tab:
|
||||
Root?.Navigate(NavDirection.Next);
|
||||
if (Root != null)
|
||||
{
|
||||
bool shiftDown = Root.GetKey(KeyboardKeys.Shift);
|
||||
Root.Navigate(shiftDown ? NavDirection.Previous : NavDirection.Next);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -476,6 +476,7 @@ namespace FlaxEditor.GUI.Docking
|
||||
settings.ShowInTaskbar = false;
|
||||
settings.ActivateWhenFirstShown = false;
|
||||
settings.IsTopmost = true;
|
||||
settings.ShowAfterFirstPaint = false;
|
||||
|
||||
win = Platform.CreateWindow(ref settings);
|
||||
|
||||
|
||||
@@ -292,7 +292,8 @@ namespace FlaxEditor.GUI
|
||||
return true;
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
if (_useCustomWindowSystem)
|
||||
var child = GetChildAtRecursive(location);
|
||||
if (_useCustomWindowSystem && child is not Button && child is not MainMenuButton)
|
||||
{
|
||||
if (_window.IsMaximized)
|
||||
_window.Restore();
|
||||
|
||||
@@ -643,7 +643,8 @@ namespace FlaxEditor.Modules
|
||||
/// Deletes the specified item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
public void Delete(ContentItem item)
|
||||
/// <param name="deletedByUser">If the file was deleted by the user and not outside the editor.</param>
|
||||
public void Delete(ContentItem item, bool deletedByUser = false)
|
||||
{
|
||||
if (item == null)
|
||||
throw new ArgumentNullException();
|
||||
@@ -667,12 +668,12 @@ namespace FlaxEditor.Modules
|
||||
var children = folder.Children.ToArray();
|
||||
for (int i = 0; i < children.Length; i++)
|
||||
{
|
||||
Delete(children[i]);
|
||||
Delete(children[i], deletedByUser);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove directory
|
||||
if (Directory.Exists(path))
|
||||
if (deletedByUser && Directory.Exists(path))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -701,7 +702,7 @@ namespace FlaxEditor.Modules
|
||||
// Delete asset by using content pool
|
||||
FlaxEngine.Content.DeleteAsset(path);
|
||||
}
|
||||
else
|
||||
else if (deletedByUser)
|
||||
{
|
||||
// Delete file
|
||||
if (File.Exists(path))
|
||||
@@ -847,7 +848,7 @@ namespace FlaxEditor.Modules
|
||||
Editor.Log(string.Format($"Content item \'{child.Path}\' has been removed"));
|
||||
|
||||
// Destroy it
|
||||
Delete(child);
|
||||
Delete(child, false);
|
||||
|
||||
i--;
|
||||
}
|
||||
|
||||
@@ -90,6 +90,12 @@ namespace FlaxEditor.Modules
|
||||
hint = "Too long name.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item.IsFolder && shortName.EndsWith("."))
|
||||
{
|
||||
hint = "Name cannot end with '.'";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find invalid characters
|
||||
if (Utilities.Utils.HasInvalidPathChar(shortName))
|
||||
@@ -120,7 +126,7 @@ namespace FlaxEditor.Modules
|
||||
// Cache data
|
||||
string sourcePath = item.Path;
|
||||
string sourceFolder = System.IO.Path.GetDirectoryName(sourcePath);
|
||||
string extension = System.IO.Path.GetExtension(sourcePath);
|
||||
string extension = item.IsFolder ? "" : System.IO.Path.GetExtension(sourcePath);
|
||||
string destinationPath = StringUtils.CombinePaths(sourceFolder, shortName + extension);
|
||||
|
||||
if (item.IsFolder)
|
||||
|
||||
@@ -24,7 +24,8 @@ namespace
|
||||
String version;
|
||||
|
||||
RiderInstallation(const String& path_, const String& version_)
|
||||
: path(path_), version(version_)
|
||||
: path(path_)
|
||||
, version(version_)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -44,6 +45,10 @@ namespace
|
||||
if (document.HasParseError())
|
||||
return;
|
||||
|
||||
// Check if this is actually rider and not another jetbrains product
|
||||
if (document.FindMember("name")->value != "JetBrains Rider")
|
||||
return;
|
||||
|
||||
// Find version
|
||||
auto versionMember = document.FindMember("version");
|
||||
if (versionMember == document.MemberEnd())
|
||||
@@ -141,14 +146,14 @@ bool sortInstallations(RiderInstallation* const& i1, RiderInstallation* const& i
|
||||
int32 version2[3] = { 0 };
|
||||
StringUtils::Parse(values1[0].Get(), &version1[0]);
|
||||
StringUtils::Parse(values1[1].Get(), &version1[1]);
|
||||
|
||||
if(values1.Count() > 2)
|
||||
|
||||
if (values1.Count() > 2)
|
||||
StringUtils::Parse(values1[2].Get(), &version1[2]);
|
||||
|
||||
|
||||
StringUtils::Parse(values2[0].Get(), &version2[0]);
|
||||
StringUtils::Parse(values2[1].Get(), &version2[1]);
|
||||
|
||||
if(values2.Count() > 2)
|
||||
|
||||
if (values2.Count() > 2)
|
||||
StringUtils::Parse(values2[2].Get(), &version2[2]);
|
||||
|
||||
// Compare by MAJOR.MINOR.BUILD
|
||||
@@ -174,7 +179,7 @@ void RiderCodeEditor::FindEditors(Array<CodeEditor*>* output)
|
||||
|
||||
String localAppDataPath;
|
||||
FileSystem::GetSpecialFolderPath(SpecialFolder::LocalAppData, localAppDataPath);
|
||||
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
// Lookup from all known registry locations
|
||||
SearchRegistry(&installations, HKEY_CURRENT_USER, TEXT("SOFTWARE\\WOW6432Node\\JetBrains\\Rider for Unreal Engine"));
|
||||
@@ -187,6 +192,7 @@ void RiderCodeEditor::FindEditors(Array<CodeEditor*>* output)
|
||||
SearchRegistry(&installations, HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\WOW6432Node\\JetBrains\\JetBrains Rider"));
|
||||
|
||||
// Versions installed via JetBrains Toolbox
|
||||
FileSystem::GetChildDirectories(subDirectories, localAppDataPath / TEXT("Programs"));
|
||||
FileSystem::GetChildDirectories(subDirectories, localAppDataPath / TEXT("JetBrains\\Toolbox\\apps\\Rider\\ch-0\\"));
|
||||
FileSystem::GetChildDirectories(subDirectories, localAppDataPath / TEXT("JetBrains\\Toolbox\\apps\\Rider\\ch-1\\")); // Beta versions
|
||||
#endif
|
||||
@@ -201,6 +207,7 @@ void RiderCodeEditor::FindEditors(Array<CodeEditor*>* output)
|
||||
FileSystem::GetChildDirectories(subDirectories, TEXT("/opt/"));
|
||||
|
||||
// Versions installed via JetBrains Toolbox
|
||||
SearchDirectory(&installations, localAppDataPath / TEXT(".local/share/JetBrains/Toolbox/apps/rider/"));
|
||||
FileSystem::GetChildDirectories(subDirectories, localAppDataPath / TEXT(".local/share/JetBrains/Toolbox/apps/Rider/ch-0"));
|
||||
FileSystem::GetChildDirectories(subDirectories, localAppDataPath / TEXT(".local/share/JetBrains/Toolbox/apps/Rider/ch-1")); // Beta versions
|
||||
|
||||
@@ -210,7 +217,24 @@ void RiderCodeEditor::FindEditors(Array<CodeEditor*>* output)
|
||||
TEXT("flatpak run com.jetbrains.Rider"));
|
||||
#endif
|
||||
|
||||
for (auto directory : subDirectories)
|
||||
#if PLATFORM_MAC
|
||||
String applicationSupportFolder;
|
||||
FileSystem::GetSpecialFolderPath(SpecialFolder::ProgramData, applicationSupportFolder);
|
||||
|
||||
Array<String> subMacDirectories;
|
||||
FileSystem::GetChildDirectories(subMacDirectories, applicationSupportFolder / TEXT("JetBrains/Toolbox/apps/Rider/ch-0/"));
|
||||
FileSystem::GetChildDirectories(subMacDirectories, applicationSupportFolder / TEXT("JetBrains/Toolbox/apps/Rider/ch-1/"));
|
||||
for (const String& directory : subMacDirectories)
|
||||
{
|
||||
String riderAppDirectory = directory / TEXT("Rider.app/Contents/Resources");
|
||||
SearchDirectory(&installations, riderAppDirectory);
|
||||
}
|
||||
|
||||
// Check the local installer version
|
||||
SearchDirectory(&installations, TEXT("/Applications/Rider.app/Contents/Resources"));
|
||||
#endif
|
||||
|
||||
for (const String& directory : subDirectories)
|
||||
SearchDirectory(&installations, directory);
|
||||
|
||||
// Sort found installations by version number
|
||||
@@ -244,8 +268,16 @@ void RiderCodeEditor::OpenFile(const String& path, int32 line)
|
||||
// Open file
|
||||
line = line > 0 ? line : 1;
|
||||
CreateProcessSettings procSettings;
|
||||
|
||||
#if !PLATFORM_MAC
|
||||
procSettings.FileName = _execPath;
|
||||
procSettings.Arguments = String::Format(TEXT("\"{0}\" --line {2} \"{1}\""), _solutionPath, path, line);
|
||||
#else
|
||||
// This follows pretty much how all the other engines open rider which deals with cross architecture issues
|
||||
procSettings.FileName = "/usr/bin/open";
|
||||
procSettings.Arguments = String::Format(TEXT("-n -a \"{0}\" --args \"{1}\" --line {3} \"{2}\""), _execPath, _solutionPath, path, line);
|
||||
#endif
|
||||
|
||||
procSettings.HiddenWindow = false;
|
||||
procSettings.WaitForEnd = false;
|
||||
procSettings.LogOutput = false;
|
||||
@@ -263,8 +295,14 @@ void RiderCodeEditor::OpenSolution()
|
||||
|
||||
// Open solution
|
||||
CreateProcessSettings procSettings;
|
||||
#if !PLATFORM_MAC
|
||||
procSettings.FileName = _execPath;
|
||||
procSettings.Arguments = String::Format(TEXT("\"{0}\""), _solutionPath);
|
||||
#else
|
||||
// This follows pretty much how all the other engines open rider which deals with cross architecture issues
|
||||
procSettings.FileName = "/usr/bin/open";
|
||||
procSettings.Arguments = String::Format(TEXT("-n -a \"{0}\" \"{1}\""), _execPath, _solutionPath);
|
||||
#endif
|
||||
procSettings.HiddenWindow = false;
|
||||
procSettings.WaitForEnd = false;
|
||||
procSettings.LogOutput = false;
|
||||
|
||||
@@ -246,20 +246,17 @@ bool ScriptsBuilder::RunBuildTool(const StringView& args, const StringView& work
|
||||
Log::FileNotFoundException(monoPath).SetLevel(LogType::Fatal);
|
||||
return true;
|
||||
}
|
||||
//const String monoPath = TEXT("mono");
|
||||
cmdLine.Append(TEXT("\""));
|
||||
const String monoPath = TEXT("mono");
|
||||
cmdLine.Append(monoPath);
|
||||
cmdLine.Append(TEXT("\" "));
|
||||
cmdLine.Append(TEXT(" "));
|
||||
// TODO: Set env var for the mono MONO_GC_PARAMS=nursery-size64m to boost build performance -> profile it
|
||||
#endif
|
||||
cmdLine.Append(TEXT("\""));
|
||||
cmdLine.Append(buildToolPath);
|
||||
cmdLine.Append(TEXT("\" "));
|
||||
cmdLine.Append(args.Get(), args.Length());
|
||||
|
||||
// Call build tool
|
||||
CreateProcessSettings procSettings;
|
||||
procSettings.FileName = StringView(*cmdLine, cmdLine.Length());
|
||||
procSettings.Arguments = args.Get();
|
||||
procSettings.WorkingDirectory = workingDir;
|
||||
const int32 result = Platform::CreateProcess(procSettings);
|
||||
if (result != 0)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.Utilities;
|
||||
|
||||
@@ -54,6 +55,13 @@ namespace FlaxEditor.States
|
||||
}
|
||||
else if (Editor.Options.Options.General.ForceScriptCompilationOnStartup && !skipCompile)
|
||||
{
|
||||
// Generate project files when Cache is missing or was cleared previously
|
||||
if (!Directory.Exists(Path.Combine(Editor.GameProject?.ProjectFolderPath, "Cache", "Intermediate")) ||
|
||||
!Directory.Exists(Path.Combine(Editor.GameProject?.ProjectFolderPath, "Cache", "Projects")))
|
||||
{
|
||||
var customArgs = Editor.Instance.CodeEditing.SelectedEditor.GenerateProjectCustomArgs;
|
||||
ScriptsBuilder.GenerateProject(customArgs);
|
||||
}
|
||||
// Compile scripts before loading any scenes, then we load them and can open scenes
|
||||
ScriptsBuilder.Compile();
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
Title = "Clamp",
|
||||
Description = "Clamps value to the specified range",
|
||||
Flags = NodeFlags.AllGraphs,
|
||||
Size = new Float2(110, 60),
|
||||
Size = new Float2(140, 60),
|
||||
ConnectionsHints = ConnectionsHint.Numeric,
|
||||
IndependentBoxes = new[] { 0 },
|
||||
DependentBoxes = new[] { 1, 2, 3 },
|
||||
|
||||
@@ -213,6 +213,23 @@ namespace FlaxEditor.Surface
|
||||
return;
|
||||
}
|
||||
|
||||
if (_middleMouseDown)
|
||||
{
|
||||
// Calculate delta
|
||||
var delta = location - _middleMouseDownPos;
|
||||
if (delta.LengthSquared > 0.01f)
|
||||
{
|
||||
// Move view
|
||||
_mouseMoveAmount += delta.Length;
|
||||
_rootControl.Location += delta;
|
||||
_middleMouseDownPos = location;
|
||||
Cursor = CursorType.SizeAll;
|
||||
}
|
||||
|
||||
// Handled
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if user is selecting or moving node(s)
|
||||
if (_leftMouseDown)
|
||||
{
|
||||
@@ -269,6 +286,11 @@ namespace FlaxEditor.Surface
|
||||
_rightMouseDown = false;
|
||||
Cursor = CursorType.Default;
|
||||
}
|
||||
if (_middleMouseDown)
|
||||
{
|
||||
_middleMouseDown = false;
|
||||
Cursor = CursorType.Default;
|
||||
}
|
||||
_isMovingSelection = false;
|
||||
ConnectingEnd(null);
|
||||
|
||||
@@ -291,7 +313,7 @@ namespace FlaxEditor.Surface
|
||||
if (IsMouseOver && !_leftMouseDown && !IsPrimaryMenuOpened)
|
||||
{
|
||||
var nextViewScale = ViewScale + delta * 0.1f;
|
||||
|
||||
|
||||
if (delta > 0 && !_rightMouseDown)
|
||||
{
|
||||
// Scale towards mouse when zooming in
|
||||
@@ -306,7 +328,7 @@ namespace FlaxEditor.Surface
|
||||
ViewScale = nextViewScale;
|
||||
ViewCenterPosition = viewCenter;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -380,6 +402,7 @@ namespace FlaxEditor.Surface
|
||||
_isMovingSelection = false;
|
||||
_rightMouseDown = false;
|
||||
_leftMouseDown = false;
|
||||
_middleMouseDown = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -399,6 +422,11 @@ namespace FlaxEditor.Surface
|
||||
_rightMouseDown = true;
|
||||
_rightMouseDownPos = location;
|
||||
}
|
||||
if (button == MouseButton.Middle)
|
||||
{
|
||||
_middleMouseDown = true;
|
||||
_middleMouseDownPos = location;
|
||||
}
|
||||
|
||||
// Check if any node is under the mouse
|
||||
SurfaceControl controlUnderMouse = GetControlUnderMouse();
|
||||
@@ -444,7 +472,7 @@ namespace FlaxEditor.Surface
|
||||
Focus();
|
||||
return true;
|
||||
}
|
||||
if (_rightMouseDown)
|
||||
if (_rightMouseDown || _middleMouseDown)
|
||||
{
|
||||
// Start navigating
|
||||
StartMouseCapture();
|
||||
@@ -513,6 +541,13 @@ namespace FlaxEditor.Surface
|
||||
}
|
||||
_mouseMoveAmount = 0;
|
||||
}
|
||||
if (_middleMouseDown && button == MouseButton.Middle)
|
||||
{
|
||||
_middleMouseDown = false;
|
||||
EndMouseCapture();
|
||||
Cursor = CursorType.Default;
|
||||
_mouseMoveAmount = 0;
|
||||
}
|
||||
|
||||
// Base
|
||||
bool handled = base.OnMouseUp(location, button);
|
||||
@@ -523,6 +558,7 @@ namespace FlaxEditor.Surface
|
||||
// Clear flags
|
||||
_rightMouseDown = false;
|
||||
_leftMouseDown = false;
|
||||
_middleMouseDown = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -706,6 +742,8 @@ namespace FlaxEditor.Surface
|
||||
{
|
||||
if (_inputBrackets.Count == 0)
|
||||
{
|
||||
if (currentInputText.StartsWith(' '))
|
||||
currentInputText = "";
|
||||
ResetInput();
|
||||
ShowPrimaryMenu(_mousePos, false, currentInputText);
|
||||
}
|
||||
|
||||
@@ -59,6 +59,11 @@ namespace FlaxEditor.Surface
|
||||
/// </summary>
|
||||
protected bool _rightMouseDown;
|
||||
|
||||
/// <summary>
|
||||
/// The middle mouse down flag.
|
||||
/// </summary>
|
||||
protected bool _middleMouseDown;
|
||||
|
||||
/// <summary>
|
||||
/// The left mouse down position.
|
||||
/// </summary>
|
||||
@@ -69,6 +74,11 @@ namespace FlaxEditor.Surface
|
||||
/// </summary>
|
||||
protected Float2 _rightMouseDownPos = Float2.Minimum;
|
||||
|
||||
/// <summary>
|
||||
/// The middle mouse down position.
|
||||
/// </summary>
|
||||
protected Float2 _middleMouseDownPos = Float2.Minimum;
|
||||
|
||||
/// <summary>
|
||||
/// The mouse position.
|
||||
/// </summary>
|
||||
@@ -902,7 +912,7 @@ namespace FlaxEditor.Surface
|
||||
{
|
||||
return _context.FindNode(id);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds the undo action to be batched (eg. if multiple undo actions is performed in a sequence during single update).
|
||||
/// </summary>
|
||||
|
||||
@@ -145,10 +145,9 @@ namespace FlaxEditor.Windows
|
||||
cm.AddButton("Refresh all thumbnails", RefreshViewItemsThumbnails);
|
||||
}
|
||||
|
||||
cm.AddSeparator();
|
||||
|
||||
if (!isRootFolder)
|
||||
if (!isRootFolder && !(item is ContentFolder projectFolder && projectFolder.Node is ProjectTreeNode))
|
||||
{
|
||||
cm.AddSeparator();
|
||||
cm.AddButton("New folder", NewFolder);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace FlaxEditor.Windows
|
||||
private TextBox _itemsSearchBox;
|
||||
private ViewDropdown _viewDropdown;
|
||||
private SortType _sortType;
|
||||
private bool _showEngineFiles = true, _showPluginsFiles = true, _showAllFiles = true;
|
||||
private bool _showEngineFiles = true, _showPluginsFiles = true, _showAllFiles = true, _showGeneratedFiles = false;
|
||||
|
||||
private RootContentTreeNode _root;
|
||||
|
||||
@@ -106,6 +106,19 @@ namespace FlaxEditor.Windows
|
||||
}
|
||||
}
|
||||
|
||||
internal bool ShowGeneratedFiles
|
||||
{
|
||||
get => _showGeneratedFiles;
|
||||
set
|
||||
{
|
||||
if (_showGeneratedFiles != value)
|
||||
{
|
||||
_showGeneratedFiles = value;
|
||||
RefreshView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal bool ShowAllFiles
|
||||
{
|
||||
get => _showAllFiles;
|
||||
@@ -314,6 +327,12 @@ namespace FlaxEditor.Windows
|
||||
b.Checked = ShowPluginsFiles;
|
||||
b.CloseMenuOnClick = false;
|
||||
b.AutoCheck = true;
|
||||
|
||||
b = show.ContextMenu.AddButton("Generated files", () => ShowGeneratedFiles = !ShowGeneratedFiles);
|
||||
b.TooltipText = "Shows generated files";
|
||||
b.Checked = ShowGeneratedFiles;
|
||||
b.CloseMenuOnClick = false;
|
||||
b.AutoCheck = true;
|
||||
|
||||
b = show.ContextMenu.AddButton("All files", () => ShowAllFiles = !ShowAllFiles);
|
||||
b.TooltipText = "Shows all files including other than assets and source code";
|
||||
@@ -520,7 +539,7 @@ namespace FlaxEditor.Windows
|
||||
}
|
||||
|
||||
// Cache data
|
||||
string extension = Path.GetExtension(item.Path);
|
||||
string extension = item.IsFolder ? "" : Path.GetExtension(item.Path);
|
||||
var newPath = StringUtils.CombinePaths(item.ParentFolder.Path, newShortName + extension);
|
||||
|
||||
// Check if was renaming mock element
|
||||
@@ -626,7 +645,7 @@ namespace FlaxEditor.Windows
|
||||
|
||||
// Delete items
|
||||
for (int i = 0; i < toDelete.Count; i++)
|
||||
Editor.ContentDatabase.Delete(toDelete[i]);
|
||||
Editor.ContentDatabase.Delete(toDelete[i], true);
|
||||
|
||||
RefreshView();
|
||||
}
|
||||
@@ -722,7 +741,12 @@ namespace FlaxEditor.Windows
|
||||
{
|
||||
var item = Editor.ContentDatabase.Find(sourcePath);
|
||||
if (item != null)
|
||||
Editor.ContentDatabase.Copy(item, Path.Combine(CurrentViewFolder.Path, item.FileName));
|
||||
{
|
||||
var newPath = StringUtils.NormalizePath(Path.Combine(CurrentViewFolder.Path, item.FileName));
|
||||
if (sourcePath.Equals(newPath))
|
||||
newPath = GetClonedAssetPath(item);
|
||||
Editor.ContentDatabase.Copy(item, newPath);
|
||||
}
|
||||
else
|
||||
importFiles.Add(sourcePath);
|
||||
}
|
||||
@@ -969,6 +993,8 @@ namespace FlaxEditor.Windows
|
||||
var items = target.Folder.Children;
|
||||
if (!_showAllFiles)
|
||||
items = items.Where(x => !(x is FileItem)).ToList();
|
||||
if (!_showGeneratedFiles)
|
||||
items = items.Where(x => !(x.Path.EndsWith(".Gen.cs", StringComparison.Ordinal) || x.Path.EndsWith(".Gen.h", StringComparison.Ordinal) || x.Path.EndsWith(".Gen.cpp", StringComparison.Ordinal) || x.Path.EndsWith(".csproj", StringComparison.Ordinal) || x.Path.Contains(".CSharp"))).ToList();
|
||||
_view.ShowItems(items, _sortType, false, true);
|
||||
}
|
||||
}
|
||||
@@ -1145,6 +1171,7 @@ namespace FlaxEditor.Windows
|
||||
writer.WriteAttributeString("ShowEngineFiles", ShowEngineFiles.ToString());
|
||||
writer.WriteAttributeString("ShowPluginsFiles", ShowPluginsFiles.ToString());
|
||||
writer.WriteAttributeString("ShowAllFiles", ShowAllFiles.ToString());
|
||||
writer.WriteAttributeString("ShowGeneratedFiles", ShowGeneratedFiles.ToString());
|
||||
writer.WriteAttributeString("ViewType", _view.ViewType.ToString());
|
||||
}
|
||||
|
||||
@@ -1162,6 +1189,8 @@ namespace FlaxEditor.Windows
|
||||
ShowPluginsFiles = value2;
|
||||
if (bool.TryParse(node.GetAttribute("ShowAllFiles"), out value2))
|
||||
ShowAllFiles = value2;
|
||||
if (bool.TryParse(node.GetAttribute("ShowGeneratedFiles"), out value2))
|
||||
ShowGeneratedFiles = value2;
|
||||
if (Enum.TryParse(node.GetAttribute("ViewType"), out ContentViewType viewType))
|
||||
_view.ViewType = viewType;
|
||||
}
|
||||
|
||||
@@ -544,7 +544,7 @@ namespace FlaxEditor.Windows
|
||||
if (noLocation)
|
||||
{
|
||||
desc.LocationFile = match.Groups[2].Value;
|
||||
int.TryParse(match.Groups[5].Value, out desc.LocationLine);
|
||||
int.TryParse(match.Groups[4].Value, out desc.LocationLine);
|
||||
noLocation = false;
|
||||
}
|
||||
fineStackTrace.AppendLine(match.Groups[0].Value);
|
||||
@@ -573,7 +573,7 @@ namespace FlaxEditor.Windows
|
||||
if (match.Success)
|
||||
{
|
||||
desc.LocationFile = match.Groups[2].Value;
|
||||
int.TryParse(match.Groups[3].Value, out desc.LocationLine);
|
||||
int.TryParse(match.Groups[4].Value, out desc.LocationLine);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -207,7 +207,8 @@ namespace FlaxEditor.Windows
|
||||
case KeyboardKeys.Tab:
|
||||
if (CanUseNavigation && Root != null)
|
||||
{
|
||||
Root.Navigate(NavDirection.Next);
|
||||
bool shiftDown = Root.GetKey(KeyboardKeys.Shift);
|
||||
Root.Navigate(shiftDown ? NavDirection.Previous : NavDirection.Next);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -205,8 +205,6 @@ void MaterialInstance::Bind(BindParameters& params)
|
||||
|
||||
Asset::LoadResult MaterialInstance::load()
|
||||
{
|
||||
ASSERT(_baseMaterial == nullptr);
|
||||
|
||||
// Get main chunk
|
||||
auto chunk0 = GetChunk(0);
|
||||
if (chunk0 == nullptr || chunk0->IsMissing())
|
||||
@@ -229,6 +227,7 @@ Asset::LoadResult MaterialInstance::load()
|
||||
else
|
||||
{
|
||||
// Clear parameters if has no material loaded
|
||||
_baseMaterial = nullptr;
|
||||
Params.Dispose();
|
||||
ParamsChanged();
|
||||
}
|
||||
|
||||
@@ -32,14 +32,21 @@ CreateAssetResult ImportShader::Import(CreateAssetContext& context)
|
||||
LOG(Warning, "Empty shader source file.");
|
||||
return CreateAssetResult::Error;
|
||||
}
|
||||
|
||||
// Ensure the source code has an empty line at the end (expected by glslang)
|
||||
auto sourceCodeChunkSize = sourceCodeSize + 1;
|
||||
if (sourceCodeText[sourceCodeSize - 1] != '\n')
|
||||
sourceCodeChunkSize++;
|
||||
|
||||
const auto& sourceCodeChunk = context.Data.Header.Chunks[SourceCodeChunk];
|
||||
sourceCodeChunk->Data.Allocate(sourceCodeSize + 1);
|
||||
sourceCodeChunk->Data.Allocate(sourceCodeChunkSize);
|
||||
const auto sourceCode = sourceCodeChunk->Get();
|
||||
Platform::MemoryCopy(sourceCode, sourceCodeText.Get(), sourceCodeSize);
|
||||
sourceCode[sourceCodeChunkSize - 2] = '\n';
|
||||
|
||||
// Encrypt source code
|
||||
Encryption::EncryptBytes(sourceCode, sourceCodeSize);
|
||||
sourceCode[sourceCodeSize] = 0;
|
||||
Encryption::EncryptBytes(sourceCode, sourceCodeChunkSize - 1);
|
||||
sourceCode[sourceCodeChunkSize - 1] = 0;
|
||||
|
||||
// Set Custom Data with Header
|
||||
ShaderStorage::Header20 shaderHeader;
|
||||
|
||||
@@ -223,10 +223,10 @@ void Log::Logger::ProcessLogMessage(LogType type, const StringView& msg, fmt_fla
|
||||
else
|
||||
{
|
||||
//w.append(msg.Get(), msg.Get() + msg.Length());
|
||||
fmt_flax::format(w, TEXT("{}"), (const Char*)msg.Get());
|
||||
fmt_flax::format(w, TEXT("{}"), msg);
|
||||
}
|
||||
#else
|
||||
fmt_flax::format(w, TEXT("{}"), (const Char*)msg.Get());
|
||||
fmt_flax::format(w, TEXT("{}"), msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ void String::Set(const char* chars, int32 length)
|
||||
}
|
||||
_length = length;
|
||||
}
|
||||
if (chars)
|
||||
if (chars && length)
|
||||
StringUtils::ConvertANSI2UTF16(chars, _data, length, _length);
|
||||
}
|
||||
|
||||
@@ -298,8 +298,10 @@ String String::TrimTrailing() const
|
||||
end--;
|
||||
}
|
||||
|
||||
ASSERT_LOW_LAYER(end >= start);
|
||||
return Substring(start, end - start + 1);
|
||||
const int32 count = end - start + 1;
|
||||
if (start >= 0 && start + count <= Length() && count >= 0)
|
||||
return String(_data + start, count);
|
||||
return Empty;
|
||||
}
|
||||
|
||||
String& String::operator/=(const Char* str)
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace FlaxEngine.Interop
|
||||
public static class NativeToManaged
|
||||
{
|
||||
public static object ConvertToManaged(IntPtr unmanaged) => unmanaged == IntPtr.Zero ? null : ManagedHandle.FromIntPtr(unmanaged).Target;
|
||||
public static IntPtr ConvertToUnmanaged(object managed) => managed != null ? ManagedHandle.ToIntPtr(managed, GCHandleType.Weak) : IntPtr.Zero;
|
||||
|
||||
public static void Free(IntPtr unmanaged)
|
||||
{
|
||||
@@ -44,6 +45,7 @@ namespace FlaxEngine.Interop
|
||||
#endif
|
||||
public static class ManagedToNative
|
||||
{
|
||||
public static object ConvertToManaged(IntPtr unmanaged) => unmanaged == IntPtr.Zero ? null : ManagedHandle.FromIntPtr(unmanaged).Target;
|
||||
public static IntPtr ConvertToUnmanaged(object managed) => managed != null ? ManagedHandle.ToIntPtr(managed, GCHandleType.Weak) : IntPtr.Zero;
|
||||
|
||||
public static void Free(IntPtr unmanaged)
|
||||
@@ -147,29 +149,16 @@ namespace FlaxEngine.Interop
|
||||
#if FLAX_EDITOR
|
||||
[HideInEditor]
|
||||
#endif
|
||||
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.ManagedToUnmanagedIn, typeof(ObjectMarshaller.ManagedToNative))]
|
||||
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.UnmanagedToManagedOut, typeof(ObjectMarshaller.ManagedToNative))]
|
||||
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.ElementIn, typeof(ObjectMarshaller.ManagedToNative))]
|
||||
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.ManagedToUnmanagedOut, typeof(ObjectMarshaller.NativeToManaged))]
|
||||
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.UnmanagedToManagedIn, typeof(ObjectMarshaller.NativeToManaged))]
|
||||
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.ElementOut, typeof(ObjectMarshaller.NativeToManaged))]
|
||||
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.ManagedToUnmanagedIn, typeof(ObjectMarshaller))]
|
||||
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.UnmanagedToManagedOut, typeof(ObjectMarshaller))]
|
||||
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.ElementIn, typeof(ObjectMarshaller))]
|
||||
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.ManagedToUnmanagedOut, typeof(ObjectMarshaller))]
|
||||
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.UnmanagedToManagedIn, typeof(ObjectMarshaller))]
|
||||
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.ElementOut, typeof(ObjectMarshaller))]
|
||||
public static class ObjectMarshaller
|
||||
{
|
||||
#if FLAX_EDITOR
|
||||
[HideInEditor]
|
||||
#endif
|
||||
public static class NativeToManaged
|
||||
{
|
||||
public static FlaxEngine.Object ConvertToManaged(IntPtr unmanaged) => unmanaged != IntPtr.Zero ? Unsafe.As<FlaxEngine.Object>(ManagedHandle.FromIntPtr(unmanaged).Target) : null;
|
||||
}
|
||||
|
||||
#if FLAX_EDITOR
|
||||
[HideInEditor]
|
||||
#endif
|
||||
public static class ManagedToNative
|
||||
{
|
||||
public static IntPtr ConvertToUnmanaged(FlaxEngine.Object managed) => Unsafe.As<object>(managed) != null ? ManagedHandle.ToIntPtr(managed) : IntPtr.Zero;
|
||||
}
|
||||
public static FlaxEngine.Object ConvertToManaged(IntPtr unmanaged) => unmanaged != IntPtr.Zero ? Unsafe.As<FlaxEngine.Object>(ManagedHandle.FromIntPtr(unmanaged).Target) : null;
|
||||
public static IntPtr ConvertToUnmanaged(FlaxEngine.Object managed) => Unsafe.As<object>(managed) != null ? ManagedHandle.ToIntPtr(managed) : IntPtr.Zero;
|
||||
}
|
||||
|
||||
#if FLAX_EDITOR
|
||||
@@ -342,6 +331,7 @@ namespace FlaxEngine.Interop
|
||||
public static class NativeToManaged
|
||||
{
|
||||
public static Dictionary<T, U> ConvertToManaged(IntPtr unmanaged) => DictionaryMarshaller<T, U>.ToManaged(unmanaged);
|
||||
public static IntPtr ConvertToUnmanaged(Dictionary<T, U> managed) => DictionaryMarshaller<T, U>.ToNative(managed, GCHandleType.Weak);
|
||||
public static void Free(IntPtr unmanaged) => DictionaryMarshaller<T, U>.Free(unmanaged);
|
||||
}
|
||||
|
||||
@@ -350,8 +340,8 @@ namespace FlaxEngine.Interop
|
||||
#endif
|
||||
public static class ManagedToNative
|
||||
{
|
||||
public static Dictionary<T, U> ConvertToManaged(IntPtr unmanaged) => DictionaryMarshaller<T, U>.ToManaged(unmanaged);
|
||||
public static IntPtr ConvertToUnmanaged(Dictionary<T, U> managed) => DictionaryMarshaller<T, U>.ToNative(managed, GCHandleType.Weak);
|
||||
|
||||
public static void Free(IntPtr unmanaged)
|
||||
{
|
||||
//DictionaryMarshaller<T, U>.Free(unmanaged); // No need to free weak handles
|
||||
@@ -425,6 +415,28 @@ namespace FlaxEngine.Interop
|
||||
return new T[numElements];
|
||||
}
|
||||
|
||||
public static TUnmanagedElement* AllocateContainerForUnmanagedElements(T[] managed, out int numElements)
|
||||
{
|
||||
if (managed is null)
|
||||
{
|
||||
numElements = 0;
|
||||
return null;
|
||||
}
|
||||
numElements = managed.Length;
|
||||
(ManagedHandle managedArrayHandle, _) = ManagedArray.AllocatePooledArray<TUnmanagedElement>(managed.Length);
|
||||
return (TUnmanagedElement*)ManagedHandle.ToIntPtr(managedArrayHandle);
|
||||
}
|
||||
|
||||
public static ReadOnlySpan<T> GetManagedValuesSource(T[] managed) => managed;
|
||||
|
||||
public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged)
|
||||
{
|
||||
if (unmanaged == null)
|
||||
return Span<TUnmanagedElement>.Empty;
|
||||
ManagedArray managedArray = Unsafe.As<ManagedArray>(ManagedHandle.FromIntPtr(new IntPtr(unmanaged)).Target);
|
||||
return managedArray.ToSpan<TUnmanagedElement>();
|
||||
}
|
||||
|
||||
public static Span<T> GetManagedValuesDestination(T[] managed) => managed;
|
||||
|
||||
public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TUnmanagedElement* unmanaged, int numElements)
|
||||
@@ -591,6 +603,7 @@ namespace FlaxEngine.Interop
|
||||
public static class NativeToManaged
|
||||
{
|
||||
public static string ConvertToManaged(IntPtr unmanaged) => ManagedString.ToManaged(unmanaged);
|
||||
public static unsafe IntPtr ConvertToUnmanaged(string managed) => managed == null ? IntPtr.Zero : ManagedHandle.ToIntPtr(managed, GCHandleType.Weak);
|
||||
public static void Free(IntPtr unmanaged) => ManagedString.Free(unmanaged);
|
||||
}
|
||||
|
||||
@@ -599,11 +612,8 @@ namespace FlaxEngine.Interop
|
||||
#endif
|
||||
public static class ManagedToNative
|
||||
{
|
||||
public static unsafe IntPtr ConvertToUnmanaged(string managed)
|
||||
{
|
||||
return managed == null ? IntPtr.Zero : ManagedHandle.ToIntPtr(managed, GCHandleType.Weak);
|
||||
}
|
||||
|
||||
public static string ConvertToManaged(IntPtr unmanaged) => ManagedString.ToManaged(unmanaged);
|
||||
public static unsafe IntPtr ConvertToUnmanaged(string managed) => managed == null ? IntPtr.Zero : ManagedHandle.ToIntPtr(managed, GCHandleType.Weak);
|
||||
public static void Free(IntPtr unmanaged)
|
||||
{
|
||||
//ManagedString.Free(unmanaged); // No need to free weak handles
|
||||
|
||||
@@ -184,7 +184,7 @@ namespace FlaxEngine.Interop
|
||||
{
|
||||
string moduleName = Marshal.PtrToStringAnsi(moduleNamePtr);
|
||||
string modulePath = Marshal.PtrToStringAnsi(modulePathPtr);
|
||||
nativeLibraryPaths[moduleName] = modulePath;
|
||||
libraryPaths[moduleName] = modulePath;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
@@ -297,7 +297,7 @@ namespace FlaxEngine.Interop
|
||||
internal static void GetClassFields(ManagedHandle typeHandle, NativeFieldDefinitions** classFields, int* classFieldsCount)
|
||||
{
|
||||
Type type = Unsafe.As<Type>(typeHandle.Target);
|
||||
var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
var fields = type.GetFields(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
|
||||
NativeFieldDefinitions* arr = (NativeFieldDefinitions*)NativeAlloc(fields.Length, Unsafe.SizeOf<NativeFieldDefinitions>());
|
||||
for (int i = 0; i < fields.Length; i++)
|
||||
@@ -331,7 +331,7 @@ namespace FlaxEngine.Interop
|
||||
internal static void GetClassProperties(ManagedHandle typeHandle, NativePropertyDefinitions** classProperties, int* classPropertiesCount)
|
||||
{
|
||||
Type type = Unsafe.As<Type>(typeHandle.Target);
|
||||
var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
var properties = type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
|
||||
var arr = (NativePropertyDefinitions*)NativeAlloc(properties.Length, Unsafe.SizeOf<NativePropertyDefinitions>());
|
||||
for (int i = 0; i < properties.Length; i++)
|
||||
@@ -559,6 +559,19 @@ namespace FlaxEngine.Interop
|
||||
return managedArray.Pointer;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static IntPtr GetArray(ManagedHandle handle)
|
||||
{
|
||||
if (!handle.IsAllocated)
|
||||
return IntPtr.Zero;
|
||||
object value = handle.Target;
|
||||
if (value is ManagedArray)
|
||||
return (IntPtr)handle;
|
||||
if (value is Array)
|
||||
return Invoker.MarshalReturnValueGeneric(value.GetType(), value);
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static int GetArrayLength(ManagedHandle arrayHandle)
|
||||
{
|
||||
@@ -804,8 +817,8 @@ namespace FlaxEngine.Interop
|
||||
[UnmanagedCallersOnly]
|
||||
internal static IntPtr FieldGetValueBoxed(ManagedHandle fieldOwnerHandle, ManagedHandle fieldHandle)
|
||||
{
|
||||
object fieldOwner = fieldOwnerHandle.Target;
|
||||
FieldHolder field = Unsafe.As<FieldHolder>(fieldHandle.Target);
|
||||
object fieldOwner = field.field.IsStatic ? null : fieldOwnerHandle.Target;
|
||||
object fieldValue = field.field.GetValue(fieldOwner);
|
||||
return Invoker.MarshalReturnValueGeneric(field.field.FieldType, fieldValue);
|
||||
}
|
||||
@@ -838,39 +851,46 @@ namespace FlaxEngine.Interop
|
||||
*assemblyFullName = NativeAllocStringAnsi(flaxEngineAssembly.FullName);
|
||||
return GetAssemblyHandle(flaxEngineAssembly);
|
||||
}
|
||||
try
|
||||
{
|
||||
string assemblyPath = Marshal.PtrToStringUni(assemblyPathPtr);
|
||||
|
||||
string assemblyPath = Marshal.PtrToStringAnsi(assemblyPathPtr);
|
||||
|
||||
Assembly assembly;
|
||||
Assembly assembly;
|
||||
#if FLAX_EDITOR
|
||||
// Load assembly from loaded bytes to prevent file locking in Editor
|
||||
var assemblyBytes = File.ReadAllBytes(assemblyPath);
|
||||
using MemoryStream stream = new MemoryStream(assemblyBytes);
|
||||
var pdbPath = Path.ChangeExtension(assemblyPath, "pdb");
|
||||
if (File.Exists(pdbPath))
|
||||
{
|
||||
// Load including debug symbols
|
||||
using FileStream pdbStream = new FileStream(Path.ChangeExtension(assemblyPath, "pdb"), FileMode.Open);
|
||||
assembly = scriptingAssemblyLoadContext.LoadFromStream(stream, pdbStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
assembly = scriptingAssemblyLoadContext.LoadFromStream(stream);
|
||||
}
|
||||
// Load assembly from loaded bytes to prevent file locking in Editor
|
||||
var assemblyBytes = File.ReadAllBytes(assemblyPath);
|
||||
using MemoryStream stream = new MemoryStream(assemblyBytes);
|
||||
var pdbPath = Path.ChangeExtension(assemblyPath, "pdb");
|
||||
if (File.Exists(pdbPath))
|
||||
{
|
||||
// Load including debug symbols
|
||||
using FileStream pdbStream = new FileStream(Path.ChangeExtension(assemblyPath, "pdb"), FileMode.Open);
|
||||
assembly = scriptingAssemblyLoadContext.LoadFromStream(stream, pdbStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
assembly = scriptingAssemblyLoadContext.LoadFromStream(stream);
|
||||
}
|
||||
#else
|
||||
// Load assembly from file
|
||||
assembly = scriptingAssemblyLoadContext.LoadFromAssemblyPath(assemblyPath);
|
||||
// Load assembly from file
|
||||
assembly = scriptingAssemblyLoadContext.LoadFromAssemblyPath(assemblyPath);
|
||||
#endif
|
||||
if (assembly == null)
|
||||
return new ManagedHandle();
|
||||
NativeLibrary.SetDllImportResolver(assembly, NativeLibraryImportResolver);
|
||||
if (assembly == null)
|
||||
return new ManagedHandle();
|
||||
NativeLibrary.SetDllImportResolver(assembly, NativeLibraryImportResolver);
|
||||
|
||||
// Assemblies loaded via streams have no Location: https://github.com/dotnet/runtime/issues/12822
|
||||
AssemblyLocations.Add(assembly.FullName, assemblyPath);
|
||||
// Assemblies loaded via streams have no Location: https://github.com/dotnet/runtime/issues/12822
|
||||
AssemblyLocations.Add(assembly.FullName, assemblyPath);
|
||||
|
||||
*assemblyName = NativeAllocStringAnsi(assembly.GetName().Name);
|
||||
*assemblyFullName = NativeAllocStringAnsi(assembly.FullName);
|
||||
return GetAssemblyHandle(assembly);
|
||||
*assemblyName = NativeAllocStringAnsi(assembly.GetName().Name);
|
||||
*assemblyFullName = NativeAllocStringAnsi(assembly.FullName);
|
||||
return GetAssemblyHandle(assembly);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogException(ex);
|
||||
}
|
||||
return new ManagedHandle();
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
@@ -909,7 +929,7 @@ namespace FlaxEngine.Interop
|
||||
loadedNativeLibraries.Remove(nativeLibraryName);
|
||||
}
|
||||
if (nativeLibraryName != null)
|
||||
nativeLibraryPaths.Remove(nativeLibraryName);
|
||||
libraryPaths.Remove(nativeLibraryName);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
|
||||
@@ -24,7 +24,8 @@ namespace FlaxEngine.Interop
|
||||
/// <summary>
|
||||
/// Provides a Mono-like API for native code to access managed runtime.
|
||||
/// </summary>
|
||||
internal static unsafe partial class NativeInterop
|
||||
[HideInEditor]
|
||||
public static unsafe partial class NativeInterop
|
||||
{
|
||||
internal static Dictionary<string, string> AssemblyLocations = new();
|
||||
|
||||
@@ -50,7 +51,7 @@ namespace FlaxEngine.Interop
|
||||
private static Dictionary<Type, int> _typeSizeCache = new();
|
||||
|
||||
private static Dictionary<string, IntPtr> loadedNativeLibraries = new();
|
||||
internal static Dictionary<string, string> nativeLibraryPaths = new();
|
||||
internal static Dictionary<string, string> libraryPaths = new();
|
||||
private static Dictionary<Assembly, string> assemblyOwnedNativeLibraries = new();
|
||||
internal static AssemblyLoadContext scriptingAssemblyLoadContext;
|
||||
|
||||
@@ -59,7 +60,7 @@ namespace FlaxEngine.Interop
|
||||
{
|
||||
if (!loadedNativeLibraries.TryGetValue(libraryName, out IntPtr nativeLibrary))
|
||||
{
|
||||
if (!nativeLibraryPaths.TryGetValue(libraryName, out var nativeLibraryPath))
|
||||
if (!libraryPaths.TryGetValue(libraryName, out var nativeLibraryPath))
|
||||
nativeLibraryPath = libraryName;
|
||||
|
||||
nativeLibrary = NativeLibrary.Load(nativeLibraryPath, assembly, dllImportSearchPath);
|
||||
@@ -101,9 +102,9 @@ namespace FlaxEngine.Interop
|
||||
private static Assembly OnScriptingAssemblyLoadContextResolving(AssemblyLoadContext assemblyLoadContext, AssemblyName assemblyName)
|
||||
{
|
||||
// FIXME: There should be a better way to resolve the path to EditorTargetPath where the dependencies are stored
|
||||
foreach (string nativeLibraryPath in nativeLibraryPaths.Values)
|
||||
foreach (string libraryPath in libraryPaths.Values)
|
||||
{
|
||||
string editorTargetPath = Path.GetDirectoryName(nativeLibraryPath);
|
||||
string editorTargetPath = Path.GetDirectoryName(libraryPath);
|
||||
|
||||
var assemblyPath = Path.Combine(editorTargetPath, assemblyName.Name + ".dll");
|
||||
if (File.Exists(assemblyPath))
|
||||
@@ -147,7 +148,27 @@ namespace FlaxEngine.Interop
|
||||
NativeMemory.AlignedFree(ptr);
|
||||
}
|
||||
|
||||
internal static T[] GCHandleArrayToManagedArray<T>(ManagedArray ptrArray) where T : class
|
||||
/// <summary>
|
||||
/// Converts a delegate into a function pointer that is callable from unmanaged code via <see cref="Marshal.GetFunctionPointerForDelegate{TDelegate}"/> but cached <paramref name="d"/> delegate to prevent collecting it by GC.
|
||||
/// </summary>
|
||||
/// <typeparam name="TDelegate">The type of delegate to convert.</typeparam>
|
||||
/// <param name="d">The delegate to be passed to unmanaged code.</param>
|
||||
/// <returns>A value that can be passed to unmanaged code, which, in turn, can use it to call the underlying managed delegate.</returns>
|
||||
public static IntPtr GetFunctionPointerForDelegate<TDelegate>(TDelegate d) where TDelegate : notnull
|
||||
{
|
||||
// Example use-case: C# script runs actions via JobSystem.Dispatch which causes crash due to GC collecting Delegate object
|
||||
ManagedHandle.Alloc(d, GCHandleType.Weak);
|
||||
|
||||
return Marshal.GetFunctionPointerForDelegate<TDelegate>(d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts array of GC Handles from native runtime to managed array.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Array element type.</typeparam>
|
||||
/// <param name="ptrArray">Input array.</param>
|
||||
/// <returns>Output array.</returns>
|
||||
public static T[] GCHandleArrayToManagedArray<T>(ManagedArray ptrArray) where T : class
|
||||
{
|
||||
Span<IntPtr> span = ptrArray.ToSpan<IntPtr>();
|
||||
T[] managedArray = new T[ptrArray.Length];
|
||||
@@ -156,7 +177,12 @@ namespace FlaxEngine.Interop
|
||||
return managedArray;
|
||||
}
|
||||
|
||||
internal static IntPtr[] ManagedArrayToGCHandleArray(Array array)
|
||||
/// <summary>
|
||||
/// Converts managed array wrapper into array of GC Handles for native runtime.
|
||||
/// </summary>
|
||||
/// <param name="array">Input array.</param>
|
||||
/// <returns>Output array.</returns>
|
||||
public static IntPtr[] ManagedArrayToGCHandleArray(Array array)
|
||||
{
|
||||
if (array.Length == 0)
|
||||
return Array.Empty<IntPtr>();
|
||||
@@ -170,13 +196,26 @@ namespace FlaxEngine.Interop
|
||||
return pointerArray;
|
||||
}
|
||||
|
||||
internal static ManagedArray ManagedArrayToGCHandleWrappedArray(Array array)
|
||||
/// <summary>
|
||||
/// Converts managed array wrapper into array of GC Handles for native runtime.
|
||||
/// </summary>
|
||||
/// <param name="array">Input array.</param>
|
||||
/// <returns>Output array.</returns>
|
||||
public static ManagedArray ManagedArrayToGCHandleWrappedArray(Array array)
|
||||
{
|
||||
IntPtr[] pointerArray = ManagedArrayToGCHandleArray(array);
|
||||
return ManagedArray.WrapNewArray(pointerArray, array.GetType());
|
||||
}
|
||||
|
||||
internal static TDst[] ConvertArray<TSrc, TDst>(Span<TSrc> src, Func<TSrc, TDst> convertFunc)
|
||||
/// <summary>
|
||||
/// Converts array with a custom converter function for each element.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSrc">Input data type.</typeparam>
|
||||
/// <typeparam name="TDst">Output data type.</typeparam>
|
||||
/// <param name="src">The input array.</param>
|
||||
/// <param name="convertFunc">Converter callback.</param>
|
||||
/// <returns>The output array.</returns>
|
||||
public static TDst[] ConvertArray<TSrc, TDst>(Span<TSrc> src, Func<TSrc, TDst> convertFunc)
|
||||
{
|
||||
TDst[] dst = new TDst[src.Length];
|
||||
for (int i = 0; i < src.Length; i++)
|
||||
@@ -184,7 +223,15 @@ namespace FlaxEngine.Interop
|
||||
return dst;
|
||||
}
|
||||
|
||||
internal static TDst[] ConvertArray<TSrc, TDst>(TSrc[] src, Func<TSrc, TDst> convertFunc)
|
||||
/// <summary>
|
||||
/// Converts array with a custom converter function for each element.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSrc">Input data type.</typeparam>
|
||||
/// <typeparam name="TDst">Output data type.</typeparam>
|
||||
/// <param name="src">The input array.</param>
|
||||
/// <param name="convertFunc">Converter callback.</param>
|
||||
/// <returns>The output array.</returns>
|
||||
public static TDst[] ConvertArray<TSrc, TDst>(TSrc[] src, Func<TSrc, TDst> convertFunc)
|
||||
{
|
||||
TDst[] dst = new TDst[src.Length];
|
||||
for (int i = 0; i < src.Length; i++)
|
||||
@@ -1024,11 +1071,12 @@ namespace FlaxEngine.Interop
|
||||
private static uint pinnedBoxedValuesPointer = 0;
|
||||
private static (IntPtr ptr, int size)[] pinnedAllocations = new (IntPtr ptr, int size)[256];
|
||||
private static uint pinnedAllocationsPointer = 0;
|
||||
|
||||
|
||||
private delegate TInternal ToNativeDelegate<T, TInternal>(T value);
|
||||
|
||||
private delegate IntPtr UnboxerDelegate(object value, object converter);
|
||||
|
||||
private static ConcurrentDictionary<Type, (UnboxerDelegate deleg, object toNativeDeleg)> unboxers = new (1, 3);
|
||||
private static ConcurrentDictionary<Type, (UnboxerDelegate deleg, object toNativeDeleg)> unboxers = new(1, 3);
|
||||
private static MethodInfo unboxerMethod = typeof(ValueTypeUnboxer).GetMethod(nameof(ValueTypeUnboxer.UnboxPointer), BindingFlags.Static | BindingFlags.NonPublic);
|
||||
private static MethodInfo unboxerToNativeMethod = typeof(ValueTypeUnboxer).GetMethod(nameof(ValueTypeUnboxer.UnboxPointerWithConverter), BindingFlags.Static | BindingFlags.NonPublic);
|
||||
|
||||
@@ -1089,7 +1137,8 @@ namespace FlaxEngine.Interop
|
||||
return new IntPtr(Unsafe.AsPointer(ref Unsafe.Unbox<T>(value)));
|
||||
}
|
||||
|
||||
private static IntPtr UnboxPointerWithConverter<T, TInternal>(object value, object converter) where T : struct where TInternal : struct
|
||||
private static IntPtr UnboxPointerWithConverter<T, TInternal>(object value, object converter) where T : struct
|
||||
where TInternal : struct
|
||||
{
|
||||
ToNativeDelegate<T, TInternal> toNative = Unsafe.As<ToNativeDelegate<T, TInternal>>(converter);
|
||||
return PinValue<TInternal>(toNative(Unsafe.Unbox<T>(value)));
|
||||
@@ -1099,12 +1148,12 @@ namespace FlaxEngine.Interop
|
||||
private delegate IntPtr InvokeThunkDelegate(ManagedHandle instanceHandle, IntPtr param1, IntPtr param2, IntPtr param3, IntPtr param4, IntPtr param5, IntPtr param6, IntPtr param7);
|
||||
|
||||
/// <summary>
|
||||
/// Returns all types that that owned by this assembly.
|
||||
/// Returns all types owned by this assembly.
|
||||
/// </summary>
|
||||
private static Type[] GetAssemblyTypes(Assembly assembly)
|
||||
{
|
||||
var referencedAssemblies = assembly.GetReferencedAssemblies();
|
||||
var allAssemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
var allAssemblies = Utils.GetAssemblies();
|
||||
var referencedTypes = new List<string>();
|
||||
foreach (var assemblyName in referencedAssemblies)
|
||||
{
|
||||
|
||||
@@ -76,11 +76,11 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
|
||||
// Set reflection probe data
|
||||
EnvironmentProbe* probe = nullptr;
|
||||
// TODO: optimize env probe searching for a transparent material - use spatial cache for renderer to find it
|
||||
const Vector3 drawCallOrigin = drawCall.ObjectPosition + view.Origin;
|
||||
const BoundingSphere objectBoundsWorld(drawCall.ObjectPosition + view.Origin, drawCall.ObjectRadius);
|
||||
for (int32 i = 0; i < cache->EnvironmentProbes.Count(); i++)
|
||||
{
|
||||
const auto p = cache->EnvironmentProbes[i];
|
||||
if (p->GetSphere().Contains(drawCallOrigin) != ContainmentType::Disjoint)
|
||||
if (CollisionsHelper::SphereIntersectsSphere(objectBoundsWorld, p->GetSphere()))
|
||||
{
|
||||
probe = p;
|
||||
break;
|
||||
@@ -99,10 +99,12 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
|
||||
|
||||
// Set local lights
|
||||
data.LocalLightsCount = 0;
|
||||
const BoundingSphere objectBounds(drawCall.ObjectPosition, drawCall.ObjectRadius);
|
||||
// TODO: optimize lights searching for a transparent material - use spatial cache for renderer to find it
|
||||
for (int32 i = 0; i < cache->PointLights.Count() && data.LocalLightsCount < MaxLocalLights; i++)
|
||||
{
|
||||
const auto& light = cache->PointLights[i];
|
||||
if (BoundingSphere(light.Position, light.Radius).Contains(drawCall.ObjectPosition) != ContainmentType::Disjoint)
|
||||
if (CollisionsHelper::SphereIntersectsSphere(objectBounds, BoundingSphere(light.Position, light.Radius)))
|
||||
{
|
||||
light.SetupLightData(&data.LocalLights[data.LocalLightsCount], false);
|
||||
data.LocalLightsCount++;
|
||||
@@ -111,7 +113,7 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
|
||||
for (int32 i = 0; i < cache->SpotLights.Count() && data.LocalLightsCount < MaxLocalLights; i++)
|
||||
{
|
||||
const auto& light = cache->SpotLights[i];
|
||||
if (BoundingSphere(light.Position, light.Radius).Contains(drawCall.ObjectPosition) != ContainmentType::Disjoint)
|
||||
if (CollisionsHelper::SphereIntersectsSphere(objectBounds, BoundingSphere(light.Position, light.Radius)))
|
||||
{
|
||||
light.SetupLightData(&data.LocalLights[data.LocalLightsCount], false);
|
||||
data.LocalLightsCount++;
|
||||
|
||||
@@ -429,6 +429,7 @@ void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, cons
|
||||
drawCall.Material = material;
|
||||
drawCall.World = world;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = _sphere.Radius * drawCall.World.GetScaleVector().GetAbsolute().MaxValue();
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.Surface.PrevWorld = world;
|
||||
drawCall.Surface.Lightmap = nullptr;
|
||||
@@ -495,6 +496,7 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float
|
||||
drawCall.Material = material;
|
||||
drawCall.World = *info.World;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = info.Bounds.Radius; // TODO: should it be kept in sync with ObjectPosition?
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
|
||||
drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr;
|
||||
@@ -555,6 +557,7 @@ void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& in
|
||||
drawCall.Material = material;
|
||||
drawCall.World = *info.World;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = info.Bounds.Radius; // TODO: should it be kept in sync with ObjectPosition?
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
|
||||
drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr;
|
||||
|
||||
@@ -198,6 +198,7 @@ void SkinnedMesh::Draw(const RenderContext& renderContext, const DrawInfo& info,
|
||||
drawCall.Material = material;
|
||||
drawCall.World = *info.World;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = info.Bounds.Radius; // TODO: should it be kept in sync with ObjectPosition?
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
|
||||
drawCall.Surface.Lightmap = nullptr;
|
||||
@@ -258,6 +259,7 @@ void SkinnedMesh::Draw(const RenderContextBatch& renderContextBatch, const DrawI
|
||||
drawCall.Material = material;
|
||||
drawCall.World = *info.World;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = info.Bounds.Radius; // TODO: should it be kept in sync with ObjectPosition?
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
|
||||
drawCall.Surface.Lightmap = nullptr;
|
||||
|
||||
@@ -120,7 +120,7 @@ bool GPUShader::Create(MemoryReadStream& stream)
|
||||
GPUShaderProgram* shader = CreateGPUShaderProgram(type, initializer, cache, cacheSize, stream);
|
||||
if (shader == nullptr)
|
||||
{
|
||||
LOG(Warning, "Failed to create shader program.");
|
||||
LOG(Error, "Failed to create {} Shader program '{}'.", ::ToString(type), String(initializer.Name));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ bool GPUBufferDX11::OnInit()
|
||||
data.SysMemPitch = bufferDesc.ByteWidth;
|
||||
data.SysMemSlicePitch = 0;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateBuffer(&bufferDesc, _desc.InitData ? &data : nullptr, &_resource));
|
||||
VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateBuffer(&bufferDesc, _desc.InitData ? &data : nullptr, &_resource));
|
||||
|
||||
// Set state
|
||||
DX_SET_DEBUG_NAME(_resource, GetName());
|
||||
@@ -135,7 +135,7 @@ bool GPUBufferDX11::OnInit()
|
||||
srvDesc.Buffer.NumElements = numElements;
|
||||
}
|
||||
ID3D11ShaderResourceView* srv;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateShaderResourceView(_resource, &srvDesc, &srv));
|
||||
VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateShaderResourceView(_resource, &srvDesc, &srv));
|
||||
_view.SetSRV(srv);
|
||||
}
|
||||
if (useUAV)
|
||||
@@ -156,7 +156,7 @@ bool GPUBufferDX11::OnInit()
|
||||
else
|
||||
uavDesc.Format = RenderToolsDX::ToDxgiFormat(PixelFormatExtensions::FindUnorderedAccessFormat(_desc.Format));
|
||||
ID3D11UnorderedAccessView* uav;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateUnorderedAccessView(_resource, &uavDesc, &uav));
|
||||
VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateUnorderedAccessView(_resource, &uavDesc, &uav));
|
||||
_view.SetUAV(uav);
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ GPUDevice* GPUDeviceDX11::Create()
|
||||
if (tempAdapter && TryCreateDevice(tempAdapter, maxAllowedFeatureLevel, &adapter.MaxFeatureLevel))
|
||||
{
|
||||
adapter.Index = index;
|
||||
VALIDATE_DIRECTX_RESULT(tempAdapter->GetDesc(&adapter.Description));
|
||||
VALIDATE_DIRECTX_CALL(tempAdapter->GetDesc(&adapter.Description));
|
||||
uint32 outputs = RenderToolsDX::CountAdapterOutputs(tempAdapter);
|
||||
|
||||
LOG(Info, "Adapter {1}: '{0}', DirectX {2}", adapter.Description.Description, index, RenderToolsDX::GetFeatureLevelString(adapter.MaxFeatureLevel));
|
||||
@@ -163,7 +163,7 @@ GPUDevice* GPUDeviceDX11::Create()
|
||||
if (tempAdapter && TryCreateDevice(tempAdapter, maxAllowedFeatureLevel, &adapter.MaxFeatureLevel))
|
||||
{
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
VALIDATE_DIRECTX_RESULT(tempAdapter->GetDesc(&desc));
|
||||
VALIDATE_DIRECTX_CALL(tempAdapter->GetDesc(&desc));
|
||||
for (int i = 0; i < adapters.Count(); i++)
|
||||
{
|
||||
if (adapters[i].Description.AdapterLuid.LowPart == desc.AdapterLuid.LowPart &&
|
||||
@@ -274,7 +274,7 @@ ID3D11BlendState* GPUDeviceDX11::GetBlendState(const BlendingMode& blending)
|
||||
#endif
|
||||
|
||||
// Create object
|
||||
VALIDATE_DIRECTX_RESULT(_device->CreateBlendState(&desc, &blendState));
|
||||
VALIDATE_DIRECTX_CALL(_device->CreateBlendState(&desc, &blendState));
|
||||
|
||||
// Cache blend state
|
||||
BlendStates.Add(blending, blendState);
|
||||
@@ -333,7 +333,7 @@ bool GPUDeviceDX11::Init()
|
||||
// Create DirectX device
|
||||
D3D_FEATURE_LEVEL createdFeatureLevel = static_cast<D3D_FEATURE_LEVEL>(0);
|
||||
auto targetFeatureLevel = GetD3DFeatureLevel();
|
||||
VALIDATE_DIRECTX_RESULT(D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, flags, &targetFeatureLevel, 1, D3D11_SDK_VERSION, &_device, &createdFeatureLevel, &_imContext));
|
||||
VALIDATE_DIRECTX_CALL(D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, flags, &targetFeatureLevel, 1, D3D11_SDK_VERSION, &_device, &createdFeatureLevel, &_imContext));
|
||||
|
||||
// Validate result
|
||||
ASSERT(_device);
|
||||
@@ -409,7 +409,7 @@ bool GPUDeviceDX11::Init()
|
||||
// Init debug layer
|
||||
#if GPU_ENABLE_DIAGNOSTICS
|
||||
ComPtr<ID3D11InfoQueue> infoQueue;
|
||||
VALIDATE_DIRECTX_RESULT(_device->QueryInterface(IID_PPV_ARGS(&infoQueue)));
|
||||
VALIDATE_DIRECTX_CALL(_device->QueryInterface(IID_PPV_ARGS(&infoQueue)));
|
||||
if (infoQueue)
|
||||
{
|
||||
D3D11_INFO_QUEUE_FILTER filter;
|
||||
@@ -457,7 +457,7 @@ bool GPUDeviceDX11::Init()
|
||||
samplerDesc.MinLOD = 0;
|
||||
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||
result = _device->CreateSamplerState(&samplerDesc, &_samplerLinearClamp);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
||||
|
||||
// Point Clamp
|
||||
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
@@ -467,7 +467,7 @@ bool GPUDeviceDX11::Init()
|
||||
samplerDesc.MinLOD = 0;
|
||||
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||
result = _device->CreateSamplerState(&samplerDesc, &_samplerPointClamp);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
||||
|
||||
// Linear Wrap
|
||||
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
@@ -477,7 +477,7 @@ bool GPUDeviceDX11::Init()
|
||||
samplerDesc.MinLOD = 0;
|
||||
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||
result = _device->CreateSamplerState(&samplerDesc, &_samplerLinearWrap);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
||||
|
||||
// Point Wrap
|
||||
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
@@ -487,7 +487,7 @@ bool GPUDeviceDX11::Init()
|
||||
samplerDesc.MinLOD = 0;
|
||||
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||
result = _device->CreateSamplerState(&samplerDesc, &_samplerPointWrap);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
||||
|
||||
// Shadow
|
||||
samplerDesc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT;
|
||||
@@ -500,7 +500,7 @@ bool GPUDeviceDX11::Init()
|
||||
samplerDesc.MinLOD = 0;
|
||||
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||
result = _device->CreateSamplerState(&samplerDesc, &_samplerShadow);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
||||
|
||||
// Shadow PCF
|
||||
samplerDesc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR;
|
||||
@@ -514,7 +514,7 @@ bool GPUDeviceDX11::Init()
|
||||
samplerDesc.MinLOD = 0;
|
||||
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||
result = _device->CreateSamplerState(&samplerDesc, &_samplerShadowPCF);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
||||
}
|
||||
|
||||
// Rasterizer States
|
||||
@@ -534,7 +534,7 @@ bool GPUDeviceDX11::Init()
|
||||
rDesc.AntialiasedLineEnable = !!wireframe; \
|
||||
rDesc.DepthClipEnable = !!depthClip; \
|
||||
result = _device->CreateRasterizerState(&rDesc, &RasterizerStates[index]); \
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result)
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, true)
|
||||
CREATE_RASTERIZER_STATE(CullMode::Normal, D3D11_CULL_BACK, false, false);
|
||||
CREATE_RASTERIZER_STATE(CullMode::Inverted, D3D11_CULL_FRONT, false, false);
|
||||
CREATE_RASTERIZER_STATE(CullMode::TwoSided, D3D11_CULL_NONE, false, false);
|
||||
@@ -568,7 +568,7 @@ bool GPUDeviceDX11::Init()
|
||||
dsDesc.DepthFunc = (D3D11_COMPARISON_FUNC)depthFunc; \
|
||||
index = (int32)depthFunc + (depthEnable ? 0 : 9) + (depthWrite ? 0 : 18); \
|
||||
HRESULT result = _device->CreateDepthStencilState(&dsDesc, &DepthStencilStates[index]); \
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result); }
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, true); }
|
||||
CREATE_DEPTH_STENCIL_STATE(false, false);
|
||||
CREATE_DEPTH_STENCIL_STATE(false, true);
|
||||
CREATE_DEPTH_STENCIL_STATE(true, true);
|
||||
@@ -666,7 +666,7 @@ void GPUDeviceDX11::DrawEnd()
|
||||
#if GPU_ENABLE_DIAGNOSTICS
|
||||
// Flush debug messages queue
|
||||
ComPtr<ID3D11InfoQueue> infoQueue;
|
||||
VALIDATE_DIRECTX_RESULT(_device->QueryInterface(IID_PPV_ARGS(&infoQueue)));
|
||||
VALIDATE_DIRECTX_CALL(_device->QueryInterface(IID_PPV_ARGS(&infoQueue)));
|
||||
if (infoQueue)
|
||||
{
|
||||
Array<uint8> data;
|
||||
|
||||
@@ -106,7 +106,7 @@ bool GPUSamplerDX11::OnInit()
|
||||
samplerDesc.MinLOD = _desc.MinMipLevel;
|
||||
samplerDesc.MaxLOD = _desc.MaxMipLevel;
|
||||
HRESULT result = _device->GetDevice()->CreateSamplerState(&samplerDesc, &SamplerState);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
||||
ASSERT(SamplerState != nullptr);
|
||||
_memoryUsage = sizeof(D3D11_SAMPLER_DESC);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream)
|
||||
{
|
||||
GPUShaderProgram* shader = nullptr;
|
||||
HRESULT result;
|
||||
switch (type)
|
||||
{
|
||||
case ShaderStage::Vertex:
|
||||
@@ -90,12 +91,13 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
||||
if (inputLayoutSize > 0)
|
||||
{
|
||||
// Create input layout
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateInputLayout(inputLayoutDesc, inputLayoutSize, cacheBytes, cacheSize, &inputLayout));
|
||||
VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateInputLayout(inputLayoutDesc, inputLayoutSize, cacheBytes, cacheSize, &inputLayout));
|
||||
}
|
||||
|
||||
// Create shader
|
||||
ID3D11VertexShader* buffer = nullptr;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateVertexShader(cacheBytes, cacheSize, nullptr, &buffer));
|
||||
result = _device->GetDevice()->CreateVertexShader(cacheBytes, cacheSize, nullptr, &buffer);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||
|
||||
// Create object
|
||||
shader = New<GPUShaderProgramVSDX11>(initializer, buffer, inputLayout, inputLayoutSize);
|
||||
@@ -109,7 +111,8 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
||||
|
||||
// Create shader
|
||||
ID3D11HullShader* buffer = nullptr;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateHullShader(cacheBytes, cacheSize, nullptr, &buffer));
|
||||
result = _device->GetDevice()->CreateHullShader(cacheBytes, cacheSize, nullptr, &buffer);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||
|
||||
// Create object
|
||||
shader = New<GPUShaderProgramHSDX11>(initializer, buffer, controlPointsCount);
|
||||
@@ -119,7 +122,8 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
||||
{
|
||||
// Create shader
|
||||
ID3D11DomainShader* buffer = nullptr;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateDomainShader(cacheBytes, cacheSize, nullptr, &buffer));
|
||||
result = _device->GetDevice()->CreateDomainShader(cacheBytes, cacheSize, nullptr, &buffer);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||
|
||||
// Create object
|
||||
shader = New<GPUShaderProgramDSDX11>(initializer, buffer);
|
||||
@@ -129,7 +133,8 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
||||
{
|
||||
// Create shader
|
||||
ID3D11GeometryShader* buffer = nullptr;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateGeometryShader(cacheBytes, cacheSize, nullptr, &buffer));
|
||||
result = _device->GetDevice()->CreateGeometryShader(cacheBytes, cacheSize, nullptr, &buffer);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||
|
||||
// Create object
|
||||
shader = New<GPUShaderProgramGSDX11>(initializer, buffer);
|
||||
@@ -139,7 +144,8 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
||||
{
|
||||
// Create shader
|
||||
ID3D11PixelShader* buffer = nullptr;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreatePixelShader(cacheBytes, cacheSize, nullptr, &buffer));
|
||||
result = _device->GetDevice()->CreatePixelShader(cacheBytes, cacheSize, nullptr, &buffer);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||
|
||||
// Create object
|
||||
shader = New<GPUShaderProgramPSDX11>(initializer, buffer);
|
||||
@@ -149,7 +155,8 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
||||
{
|
||||
// Create shader
|
||||
ID3D11ComputeShader* buffer = nullptr;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateComputeShader(cacheBytes, cacheSize, nullptr, &buffer));
|
||||
result = _device->GetDevice()->CreateComputeShader(cacheBytes, cacheSize, nullptr, &buffer);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||
|
||||
// Create object
|
||||
shader = New<GPUShaderProgramCSDX11>(initializer, buffer);
|
||||
|
||||
@@ -28,13 +28,13 @@ GPUSwapChainDX11::GPUSwapChainDX11(GPUDeviceDX11* device, Window* window)
|
||||
|
||||
void GPUSwapChainDX11::getBackBuffer()
|
||||
{
|
||||
VALIDATE_DIRECTX_RESULT(_swapChain->GetBuffer(0, __uuidof(_backBuffer), reinterpret_cast<void**>(&_backBuffer)));
|
||||
VALIDATE_DIRECTX_CALL(_swapChain->GetBuffer(0, __uuidof(_backBuffer), reinterpret_cast<void**>(&_backBuffer)));
|
||||
|
||||
ID3D11RenderTargetView* rtv;
|
||||
ID3D11ShaderResourceView* srv;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateRenderTargetView(_backBuffer, nullptr, &rtv));
|
||||
VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateRenderTargetView(_backBuffer, nullptr, &rtv));
|
||||
#if GPU_USE_WINDOW_SRV
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateShaderResourceView(_backBuffer, nullptr, &srv));
|
||||
VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateShaderResourceView(_backBuffer, nullptr, &srv));
|
||||
#else
|
||||
srv = nullptr;
|
||||
#endif
|
||||
@@ -55,7 +55,7 @@ void GPUSwapChainDX11::OnReleaseGPU()
|
||||
// Disable fullscreen mode
|
||||
if (_swapChain)
|
||||
{
|
||||
VALIDATE_DIRECTX_RESULT(_swapChain->SetFullscreenState(false, nullptr));
|
||||
VALIDATE_DIRECTX_CALL(_swapChain->SetFullscreenState(false, nullptr));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -78,7 +78,7 @@ bool GPUSwapChainDX11::IsFullscreen()
|
||||
|
||||
// Get state
|
||||
BOOL state;
|
||||
VALIDATE_DIRECTX_RESULT(_swapChain->GetFullscreenState(&state, nullptr));
|
||||
VALIDATE_DIRECTX_CALL(_swapChain->GetFullscreenState(&state, nullptr));
|
||||
return state == TRUE;
|
||||
}
|
||||
|
||||
@@ -229,21 +229,21 @@ bool GPUSwapChainDX11::Resize(int32 width, int32 height)
|
||||
// Create swap chain
|
||||
#if PLATFORM_WINDOWS
|
||||
auto dxgi = _device->GetDXGIFactory();
|
||||
VALIDATE_DIRECTX_RESULT(dxgi->CreateSwapChain(_device->GetDevice(), &swapChainDesc, &_swapChain));
|
||||
VALIDATE_DIRECTX_CALL(dxgi->CreateSwapChain(_device->GetDevice(), &swapChainDesc, &_swapChain));
|
||||
ASSERT(_swapChain);
|
||||
|
||||
// Disable DXGI changes to the window
|
||||
VALIDATE_DIRECTX_RESULT(dxgi->MakeWindowAssociation(_windowHandle, DXGI_MWA_NO_ALT_ENTER));
|
||||
VALIDATE_DIRECTX_CALL(dxgi->MakeWindowAssociation(_windowHandle, DXGI_MWA_NO_ALT_ENTER));
|
||||
#else
|
||||
auto dxgiFactory = (IDXGIFactory2*)_device->GetDXGIFactory();
|
||||
VALIDATE_DIRECTX_RESULT(dxgiFactory->CreateSwapChainForCoreWindow(_device->GetDevice(), static_cast<IUnknown*>(_windowHandle), &swapChainDesc, nullptr, &_swapChain));
|
||||
VALIDATE_DIRECTX_CALL(dxgiFactory->CreateSwapChainForCoreWindow(_device->GetDevice(), static_cast<IUnknown*>(_windowHandle), &swapChainDesc, nullptr, &_swapChain));
|
||||
ASSERT(_swapChain);
|
||||
|
||||
// Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
|
||||
// ensures that the application will only render after each VSync, minimizing power consumption.
|
||||
ComPtr<IDXGIDevice2> dxgiDevice;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->QueryInterface(IID_PPV_ARGS(&dxgiDevice)));
|
||||
VALIDATE_DIRECTX_RESULT(dxgiDevice->SetMaximumFrameLatency(1));
|
||||
VALIDATE_DIRECTX_CALL(_device->GetDevice()->QueryInterface(IID_PPV_ARGS(&dxgiDevice)));
|
||||
VALIDATE_DIRECTX_CALL(dxgiDevice->SetMaximumFrameLatency(1));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@@ -252,10 +252,10 @@ bool GPUSwapChainDX11::Resize(int32 width, int32 height)
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
_swapChain->GetDesc(&swapChainDesc);
|
||||
VALIDATE_DIRECTX_RESULT(_swapChain->ResizeBuffers(swapChainDesc.BufferCount, width, height, swapChainDesc.BufferDesc.Format, swapChainDesc.Flags));
|
||||
VALIDATE_DIRECTX_CALL(_swapChain->ResizeBuffers(swapChainDesc.BufferCount, width, height, swapChainDesc.BufferDesc.Format, swapChainDesc.Flags));
|
||||
#else
|
||||
_swapChain->GetDesc1(&swapChainDesc);
|
||||
VALIDATE_DIRECTX_RESULT(_swapChain->ResizeBuffers(swapChainDesc.BufferCount, width, height, swapChainDesc.Format, swapChainDesc.Flags));
|
||||
VALIDATE_DIRECTX_CALL(_swapChain->ResizeBuffers(swapChainDesc.BufferCount, width, height, swapChainDesc.Format, swapChainDesc.Flags));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ bool GPUTextureDX11::OnInit()
|
||||
result = device->CreateTexture2D(&textureDesc, nullptr, &texture);
|
||||
_resource = texture;
|
||||
}
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
||||
ASSERT(_resource != nullptr);
|
||||
DX_SET_DEBUG_NAME(_resource, GetName());
|
||||
|
||||
@@ -135,7 +135,7 @@ void GPUTextureDX11::OnResidentMipsChanged()
|
||||
}
|
||||
ID3D11ShaderResourceView* srView = nullptr;
|
||||
if (mipLevels != 0)
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
GPUTextureViewDX11& view = IsVolume() ? _handleVolume : _handlesPerSlice[0];
|
||||
if (view.GetParent() == nullptr)
|
||||
view.Init(this, nullptr, srView, nullptr, nullptr, Format(), MultiSampleLevel());
|
||||
@@ -201,7 +201,7 @@ void GPUTextureDX11::initHandles()
|
||||
srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
|
||||
srDesc.Texture3D.MostDetailedMip = 0;
|
||||
srDesc.Texture3D.MipLevels = mipLevels;
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
VALIDATE_DIRECTX_CALL(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
}
|
||||
if (useRTV)
|
||||
{
|
||||
@@ -209,7 +209,7 @@ void GPUTextureDX11::initHandles()
|
||||
rtDesc.Texture3D.MipSlice = 0;
|
||||
rtDesc.Texture3D.FirstWSlice = 0;
|
||||
rtDesc.Texture3D.WSize = Depth();
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
||||
VALIDATE_DIRECTX_CALL(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
||||
}
|
||||
if (useUAV)
|
||||
{
|
||||
@@ -217,7 +217,7 @@ void GPUTextureDX11::initHandles()
|
||||
uaDesc.Texture3D.MipSlice = 0;
|
||||
uaDesc.Texture3D.WSize = Depth();
|
||||
uaDesc.Texture3D.FirstWSlice = 0;
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateUnorderedAccessView(_resource, &uaDesc, &uaView));
|
||||
VALIDATE_DIRECTX_CALL(device->CreateUnorderedAccessView(_resource, &uaDesc, &uaView));
|
||||
}
|
||||
_handleVolume.Init(this, rtView, srView, nullptr, uaView, format, msaa);
|
||||
|
||||
@@ -232,7 +232,7 @@ void GPUTextureDX11::initHandles()
|
||||
for (int32 sliceIndex = 0; sliceIndex < Depth(); sliceIndex++)
|
||||
{
|
||||
rtDesc.Texture3D.FirstWSlice = sliceIndex;
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
||||
VALIDATE_DIRECTX_CALL(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
||||
_handlesPerSlice[sliceIndex].Init(this, rtView, nullptr, nullptr, nullptr, format, msaa);
|
||||
}
|
||||
}
|
||||
@@ -263,7 +263,7 @@ void GPUTextureDX11::initHandles()
|
||||
dsDesc.Texture2DArray.FirstArraySlice = arrayIndex;
|
||||
dsDesc.Texture2DArray.MipSlice = 0;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateDepthStencilView(_resource, &dsDesc, &dsView));
|
||||
VALIDATE_DIRECTX_CALL(device->CreateDepthStencilView(_resource, &dsDesc, &dsView));
|
||||
}
|
||||
if (useRTV)
|
||||
{
|
||||
@@ -281,7 +281,7 @@ void GPUTextureDX11::initHandles()
|
||||
rtDesc.Texture2DArray.FirstArraySlice = arrayIndex;
|
||||
rtDesc.Texture2DArray.MipSlice = 0;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
||||
VALIDATE_DIRECTX_CALL(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
||||
}
|
||||
if (useSRV)
|
||||
{
|
||||
@@ -305,7 +305,7 @@ void GPUTextureDX11::initHandles()
|
||||
srDesc.Texture2DArray.MipLevels = mipLevels;
|
||||
srDesc.Texture2DArray.MostDetailedMip = 0;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
VALIDATE_DIRECTX_CALL(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,7 +322,7 @@ void GPUTextureDX11::initHandles()
|
||||
dsDesc.Texture2DArray.ArraySize = arraySize;
|
||||
dsDesc.Texture2DArray.FirstArraySlice = 0;
|
||||
dsDesc.Texture2DArray.MipSlice = 0;
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateDepthStencilView(_resource, &dsDesc, &dsView));
|
||||
VALIDATE_DIRECTX_CALL(device->CreateDepthStencilView(_resource, &dsDesc, &dsView));
|
||||
}
|
||||
if (useRTV)
|
||||
{
|
||||
@@ -330,7 +330,7 @@ void GPUTextureDX11::initHandles()
|
||||
rtDesc.Texture2DArray.ArraySize = arraySize;
|
||||
rtDesc.Texture2DArray.FirstArraySlice = 0;
|
||||
rtDesc.Texture2DArray.MipSlice = 0;
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
||||
VALIDATE_DIRECTX_CALL(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
||||
}
|
||||
if (useSRV)
|
||||
{
|
||||
@@ -348,7 +348,7 @@ void GPUTextureDX11::initHandles()
|
||||
srDesc.Texture2DArray.MipLevels = mipLevels;
|
||||
srDesc.Texture2DArray.MostDetailedMip = 0;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
VALIDATE_DIRECTX_CALL(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
}
|
||||
if (useUAV)
|
||||
{
|
||||
@@ -356,7 +356,7 @@ void GPUTextureDX11::initHandles()
|
||||
uaDesc.Texture2DArray.MipSlice = 0;
|
||||
uaDesc.Texture2DArray.ArraySize = arraySize;
|
||||
uaDesc.Texture2DArray.FirstArraySlice = 0;
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateUnorderedAccessView(_resource, &uaDesc, &uaView));
|
||||
VALIDATE_DIRECTX_CALL(device->CreateUnorderedAccessView(_resource, &uaDesc, &uaView));
|
||||
}
|
||||
_handleArray.Init(this, rtView, srView, dsView, uaView, format, msaa);
|
||||
}
|
||||
@@ -386,7 +386,7 @@ void GPUTextureDX11::initHandles()
|
||||
dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||
dsDesc.Texture2D.MipSlice = 0;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateDepthStencilView(_resource, &dsDesc, &dsView));
|
||||
VALIDATE_DIRECTX_CALL(device->CreateDepthStencilView(_resource, &dsDesc, &dsView));
|
||||
}
|
||||
if (useRTV)
|
||||
{
|
||||
@@ -406,7 +406,7 @@ void GPUTextureDX11::initHandles()
|
||||
rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
rtDesc.Texture2D.MipSlice = 0;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
||||
VALIDATE_DIRECTX_CALL(device->CreateRenderTargetView(_resource, &rtDesc, &rtView));
|
||||
}
|
||||
if (useSRV)
|
||||
{
|
||||
@@ -426,13 +426,13 @@ void GPUTextureDX11::initHandles()
|
||||
srDesc.Texture2D.MostDetailedMip = 0;
|
||||
srDesc.Texture2D.MipLevels = mipLevels;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
VALIDATE_DIRECTX_CALL(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
}
|
||||
if (useUAV)
|
||||
{
|
||||
uaDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
|
||||
uaDesc.Texture2D.MipSlice = 0;
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateUnorderedAccessView(_resource, &uaDesc, &uaView));
|
||||
VALIDATE_DIRECTX_CALL(device->CreateUnorderedAccessView(_resource, &uaDesc, &uaView));
|
||||
}
|
||||
_handlesPerSlice[0].Init(this, rtView, srView, dsView, uaView, format, msaa);
|
||||
}
|
||||
@@ -521,7 +521,7 @@ void GPUTextureDX11::initHandles()
|
||||
dsDesc.Flags = D3D11_DSV_READ_ONLY_DEPTH;
|
||||
if (PixelFormatExtensions::HasStencil(format))
|
||||
dsDesc.Flags |= D3D11_DSV_READ_ONLY_STENCIL;
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateDepthStencilView(_resource, &dsDesc, &dsView));
|
||||
VALIDATE_DIRECTX_CALL(device->CreateDepthStencilView(_resource, &dsDesc, &dsView));
|
||||
}
|
||||
ASSERT(!useRTV);
|
||||
rtView = nullptr;
|
||||
@@ -543,7 +543,7 @@ void GPUTextureDX11::initHandles()
|
||||
srDesc.Texture2D.MostDetailedMip = 0;
|
||||
srDesc.Texture2D.MipLevels = mipLevels;
|
||||
}
|
||||
VALIDATE_DIRECTX_RESULT(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
VALIDATE_DIRECTX_CALL(device->CreateShaderResourceView(_resource, &srDesc, &srView));
|
||||
}
|
||||
_handleReadOnlyDepth.Init(this, rtView, srView, dsView, nullptr, format, msaa);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ ID3D12CommandAllocator* CommandAllocatorPoolDX12::RequestAllocator(uint64 comple
|
||||
if (firstPair.First <= completedFenceValue)
|
||||
{
|
||||
allocator = firstPair.Second;
|
||||
VALIDATE_DIRECTX_RESULT(allocator->Reset());
|
||||
VALIDATE_DIRECTX_CALL(allocator->Reset());
|
||||
_ready.RemoveAtKeepOrder(0);
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ ID3D12CommandAllocator* CommandAllocatorPoolDX12::RequestAllocator(uint64 comple
|
||||
// If no allocators were ready to be reused, create a new one
|
||||
if (allocator == nullptr)
|
||||
{
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateCommandAllocator(_type, IID_PPV_ARGS(&allocator)));
|
||||
VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateCommandAllocator(_type, IID_PPV_ARGS(&allocator)));
|
||||
#if GPU_ENABLE_RESOURCE_NAMING
|
||||
Char name[32];
|
||||
swprintf(name, 32, L"CommandAllocator %u", _pool.Count());
|
||||
|
||||
@@ -111,7 +111,7 @@ bool CommandQueueDX12::Init()
|
||||
desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
desc.NodeMask = 0;
|
||||
HRESULT result = _device->GetDevice()->CreateCommandQueue(&desc, IID_PPV_ARGS(&_commandQueue));
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
||||
#if GPU_ENABLE_RESOURCE_NAMING
|
||||
_commandQueue->SetName(TEXT("CommandQueueDX12::CommandQueue"));
|
||||
#endif
|
||||
@@ -148,7 +148,7 @@ void CommandQueueDX12::WaitForGPU()
|
||||
|
||||
uint64 CommandQueueDX12::ExecuteCommandList(ID3D12CommandList* list)
|
||||
{
|
||||
VALIDATE_DIRECTX_RESULT((static_cast<ID3D12GraphicsCommandList*>(list))->Close());
|
||||
VALIDATE_DIRECTX_CALL((static_cast<ID3D12GraphicsCommandList*>(list))->Close());
|
||||
|
||||
_commandQueue->ExecuteCommandLists(1, &list);
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ bool DescriptorHeapWithSlotsDX12::Create(D3D12_DESCRIPTOR_HEAP_TYPE type, uint32
|
||||
|
||||
// Create heap
|
||||
const HRESULT result = _device->GetDevice()->CreateDescriptorHeap(&desc, __uuidof(ID3D12DescriptorHeap), reinterpret_cast<void**>(&_heap));
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
||||
|
||||
// Setup
|
||||
_type = type;
|
||||
@@ -196,7 +196,7 @@ bool DescriptorHeapRingBufferDX12::Init()
|
||||
desc.Flags = _shaderVisible ? D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE : D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
desc.NodeMask = 0;
|
||||
const HRESULT result = _device->GetDevice()->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&_heap));
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
||||
|
||||
// Setup
|
||||
_firstFree = 0;
|
||||
|
||||
@@ -136,7 +136,7 @@ bool GPUBufferDX12::OnInit()
|
||||
// Create resource
|
||||
ID3D12Resource* resource;
|
||||
D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, initialState, nullptr, IID_PPV_ARGS(&resource)));
|
||||
VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, initialState, nullptr, IID_PPV_ARGS(&resource)));
|
||||
|
||||
// Set state
|
||||
initResource(resource, initialState, 1);
|
||||
|
||||
@@ -83,7 +83,7 @@ GPUContextDX12::GPUContextDX12(GPUDeviceDX12* device, D3D12_COMMAND_LIST_TYPE ty
|
||||
FrameFenceValues[0] = 0;
|
||||
FrameFenceValues[1] = 0;
|
||||
_currentAllocator = _device->GetCommandQueue()->RequestAllocator();
|
||||
VALIDATE_DIRECTX_RESULT(device->GetDevice()->CreateCommandList(0, type, _currentAllocator, nullptr, IID_PPV_ARGS(&_commandList)));
|
||||
VALIDATE_DIRECTX_CALL(device->GetDevice()->CreateCommandList(0, type, _currentAllocator, nullptr, IID_PPV_ARGS(&_commandList)));
|
||||
#if GPU_ENABLE_RESOURCE_NAMING
|
||||
_commandList->SetName(TEXT("GPUContextDX12::CommandList"));
|
||||
#endif
|
||||
|
||||
@@ -77,7 +77,7 @@ GPUDevice* GPUDeviceDX12::Create()
|
||||
#endif
|
||||
#ifdef __ID3D12DeviceRemovedExtendedDataSettings_FWD_DEFINED__
|
||||
ComPtr<ID3D12DeviceRemovedExtendedDataSettings> dredSettings;
|
||||
VALIDATE_DIRECTX_RESULT(D3D12GetDebugInterface(IID_PPV_ARGS(&dredSettings)));
|
||||
VALIDATE_DIRECTX_CALL(D3D12GetDebugInterface(IID_PPV_ARGS(&dredSettings)));
|
||||
if (dredSettings)
|
||||
{
|
||||
// Turn on AutoBreadcrumbs and Page Fault reporting
|
||||
@@ -116,7 +116,7 @@ GPUDevice* GPUDeviceDX12::Create()
|
||||
{
|
||||
adapter.Index = index;
|
||||
adapter.MaxFeatureLevel = D3D_FEATURE_LEVEL_12_0;
|
||||
VALIDATE_DIRECTX_RESULT(tempAdapter->GetDesc(&adapter.Description));
|
||||
VALIDATE_DIRECTX_CALL(tempAdapter->GetDesc(&adapter.Description));
|
||||
uint32 outputs = RenderToolsDX::CountAdapterOutputs(tempAdapter);
|
||||
|
||||
// Send that info to the log
|
||||
@@ -137,7 +137,7 @@ GPUDevice* GPUDeviceDX12::Create()
|
||||
if (tempAdapter && CheckDX12Support(tempAdapter))
|
||||
{
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
VALIDATE_DIRECTX_RESULT(tempAdapter->GetDesc(&desc));
|
||||
VALIDATE_DIRECTX_CALL(tempAdapter->GetDesc(&desc));
|
||||
for (int i = 0; i < adapters.Count(); i++)
|
||||
{
|
||||
if (adapters[i].Description.AdapterLuid.LowPart == desc.AdapterLuid.LowPart &&
|
||||
@@ -254,7 +254,7 @@ bool GPUDeviceDX12::Init()
|
||||
#if PLATFORM_XBOX_SCARLETT
|
||||
params.DisableDXR = TRUE;
|
||||
#endif
|
||||
VALIDATE_DIRECTX_RESULT(D3D12XboxCreateDevice(nullptr, ¶ms, IID_GRAPHICS_PPV_ARGS(&_device)));
|
||||
VALIDATE_DIRECTX_CALL(D3D12XboxCreateDevice(nullptr, ¶ms, IID_GRAPHICS_PPV_ARGS(&_device)));
|
||||
|
||||
// Setup adapter
|
||||
D3D12XBOX_GPU_HARDWARE_CONFIGURATION hwConfig = {};
|
||||
@@ -319,12 +319,12 @@ bool GPUDeviceDX12::Init()
|
||||
}
|
||||
|
||||
// Create DirectX device
|
||||
VALIDATE_DIRECTX_RESULT(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&_device)));
|
||||
VALIDATE_DIRECTX_CALL(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&_device)));
|
||||
|
||||
// Debug Layer
|
||||
#if GPU_ENABLE_DIAGNOSTICS
|
||||
ComPtr<ID3D12InfoQueue> infoQueue;
|
||||
VALIDATE_DIRECTX_RESULT(_device->QueryInterface(IID_PPV_ARGS(&infoQueue)));
|
||||
VALIDATE_DIRECTX_CALL(_device->QueryInterface(IID_PPV_ARGS(&infoQueue)));
|
||||
if (infoQueue)
|
||||
{
|
||||
D3D12_INFO_QUEUE_FILTER filter;
|
||||
@@ -363,7 +363,7 @@ bool GPUDeviceDX12::Init()
|
||||
|
||||
// Spawn some info about the hardware
|
||||
D3D12_FEATURE_DATA_D3D12_OPTIONS options;
|
||||
VALIDATE_DIRECTX_RESULT(_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)));
|
||||
VALIDATE_DIRECTX_CALL(_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)));
|
||||
LOG(Info, "Tiled Resources Tier: {0}", (int32)options.TiledResourcesTier);
|
||||
LOG(Info, "Resource Binding Tier: {0}", (int32)options.ResourceBindingTier);
|
||||
LOG(Info, "Conservative Rasterization Tier: {0}", (int32)options.ConservativeRasterizationTier);
|
||||
@@ -662,10 +662,10 @@ bool GPUDeviceDX12::Init()
|
||||
// Serialize
|
||||
ComPtr<ID3DBlob> signature;
|
||||
ComPtr<ID3DBlob> error;
|
||||
VALIDATE_DIRECTX_RESULT(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));
|
||||
VALIDATE_DIRECTX_CALL(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));
|
||||
|
||||
// Create
|
||||
VALIDATE_DIRECTX_RESULT(_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&_rootSignature)));
|
||||
VALIDATE_DIRECTX_CALL(_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&_rootSignature)));
|
||||
}
|
||||
|
||||
// Upload buffer
|
||||
@@ -896,14 +896,14 @@ void GPUDeviceDX12::OnResumed()
|
||||
void GPUDeviceDX12::updateFrameEvents()
|
||||
{
|
||||
ComPtr<IDXGIDevice1> dxgiDevice;
|
||||
VALIDATE_DIRECTX_RESULT(_device->QueryInterface(IID_GRAPHICS_PPV_ARGS(&dxgiDevice)));
|
||||
VALIDATE_DIRECTX_CALL(_device->QueryInterface(IID_GRAPHICS_PPV_ARGS(&dxgiDevice)));
|
||||
ComPtr<IDXGIAdapter> dxgiAdapter;
|
||||
VALIDATE_DIRECTX_RESULT(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf()));
|
||||
VALIDATE_DIRECTX_CALL(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf()));
|
||||
dxgiAdapter->GetDesc(&_adapter->Description);
|
||||
ComPtr<IDXGIOutput> dxgiOutput;
|
||||
VALIDATE_DIRECTX_RESULT(dxgiAdapter->EnumOutputs(0, dxgiOutput.GetAddressOf()));
|
||||
VALIDATE_DIRECTX_RESULT(_device->SetFrameIntervalX(dxgiOutput.Get(), D3D12XBOX_FRAME_INTERVAL_60_HZ, DX12_BACK_BUFFER_COUNT - 1u, D3D12XBOX_FRAME_INTERVAL_FLAG_NONE));
|
||||
VALIDATE_DIRECTX_RESULT(_device->ScheduleFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, 0U, nullptr, D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE));
|
||||
VALIDATE_DIRECTX_CALL(dxgiAdapter->EnumOutputs(0, dxgiOutput.GetAddressOf()));
|
||||
VALIDATE_DIRECTX_CALL(_device->SetFrameIntervalX(dxgiOutput.Get(), D3D12XBOX_FRAME_INTERVAL_60_HZ, DX12_BACK_BUFFER_COUNT - 1u, D3D12XBOX_FRAME_INTERVAL_FLAG_NONE));
|
||||
VALIDATE_DIRECTX_CALL(_device->ScheduleFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, 0U, nullptr, D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -66,7 +66,7 @@ void GPUSwapChainDX12::OnReleaseGPU()
|
||||
// Disable fullscreen mode
|
||||
if (_swapChain)
|
||||
{
|
||||
VALIDATE_DIRECTX_RESULT(_swapChain->SetFullscreenState(false, nullptr));
|
||||
VALIDATE_DIRECTX_CALL(_swapChain->SetFullscreenState(false, nullptr));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -100,7 +100,7 @@ bool GPUSwapChainDX12::IsFullscreen()
|
||||
|
||||
// Get state
|
||||
BOOL state;
|
||||
VALIDATE_DIRECTX_RESULT(_swapChain->GetFullscreenState(&state, nullptr));
|
||||
VALIDATE_DIRECTX_CALL(_swapChain->GetFullscreenState(&state, nullptr));
|
||||
return state == TRUE;
|
||||
#endif
|
||||
}
|
||||
@@ -221,7 +221,7 @@ bool GPUSwapChainDX12::Resize(int32 width, int32 height)
|
||||
// Create swap chain (it needs the queue so that it can force a flush on it)
|
||||
IDXGISwapChain1* swapChain;
|
||||
auto dxgiFactory = _device->GetDXGIFactory();
|
||||
VALIDATE_DIRECTX_RESULT(dxgiFactory->CreateSwapChainForHwnd(_device->GetCommandQueueDX12(), _windowHandle, &swapChainDesc, &fullscreenDesc, nullptr, &swapChain));
|
||||
VALIDATE_DIRECTX_CALL(dxgiFactory->CreateSwapChainForHwnd(_device->GetCommandQueueDX12(), _windowHandle, &swapChainDesc, &fullscreenDesc, nullptr, &swapChain));
|
||||
_swapChain = static_cast<IDXGISwapChain3*>(swapChain);
|
||||
ASSERT(_swapChain);
|
||||
DX_SET_DEBUG_NAME_EX(_swapChain, TEXT("RenderOutput"), TEXT("SwapChain"), TEXT(""));
|
||||
@@ -229,7 +229,7 @@ bool GPUSwapChainDX12::Resize(int32 width, int32 height)
|
||||
_backBuffers.Resize(swapChainDesc.BufferCount);
|
||||
|
||||
// Disable DXGI changes to the window
|
||||
VALIDATE_DIRECTX_RESULT(dxgiFactory->MakeWindowAssociation(_windowHandle, DXGI_MWA_NO_ALT_ENTER));
|
||||
VALIDATE_DIRECTX_CALL(dxgiFactory->MakeWindowAssociation(_windowHandle, DXGI_MWA_NO_ALT_ENTER));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -237,7 +237,7 @@ bool GPUSwapChainDX12::Resize(int32 width, int32 height)
|
||||
|
||||
_swapChain->GetDesc1(&swapChainDesc);
|
||||
|
||||
VALIDATE_DIRECTX_RESULT(_swapChain->ResizeBuffers(swapChainDesc.BufferCount, width, height, swapChainDesc.Format, swapChainDesc.Flags));
|
||||
VALIDATE_DIRECTX_CALL(_swapChain->ResizeBuffers(swapChainDesc.BufferCount, width, height, swapChainDesc.Format, swapChainDesc.Flags));
|
||||
}
|
||||
|
||||
_currentFrameIndex = _swapChain->GetCurrentBackBufferIndex();
|
||||
@@ -316,7 +316,7 @@ void GPUSwapChainDX12::getBackBuffer()
|
||||
swapChainBufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
D3D12_CLEAR_VALUE swapChainOptimizedClearValue = {};
|
||||
swapChainOptimizedClearValue.Format = swapChainBufferDesc.Format;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateCommittedResource(
|
||||
VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateCommittedResource(
|
||||
&swapChainHeapProperties,
|
||||
D3D12_HEAP_FLAG_ALLOW_DISPLAY,
|
||||
&swapChainBufferDesc,
|
||||
@@ -324,7 +324,7 @@ void GPUSwapChainDX12::getBackBuffer()
|
||||
&swapChainOptimizedClearValue,
|
||||
IID_GRAPHICS_PPV_ARGS(&backbuffer)));
|
||||
#else
|
||||
VALIDATE_DIRECTX_RESULT(_swapChain->GetBuffer(i, IID_PPV_ARGS(&backbuffer)));
|
||||
VALIDATE_DIRECTX_CALL(_swapChain->GetBuffer(i, IID_PPV_ARGS(&backbuffer)));
|
||||
#endif
|
||||
DX_SET_DEBUG_NAME_EX(backbuffer, TEXT("RenderOutput"), TEXT("BackBuffer"), i);
|
||||
_backBuffers[i].Setup(this, backbuffer);
|
||||
@@ -337,7 +337,7 @@ void GPUSwapChainDX12::Begin(RenderTask* task)
|
||||
{
|
||||
// Wait until frame start is signaled
|
||||
_framePipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &_framePipelineToken));
|
||||
VALIDATE_DIRECTX_CALL(_device->GetDevice()->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &_framePipelineToken));
|
||||
|
||||
GPUSwapChain::Begin(task);
|
||||
}
|
||||
@@ -366,7 +366,7 @@ void GPUSwapChainDX12::Present(bool vsync)
|
||||
planeParameters.Token = _framePipelineToken;
|
||||
planeParameters.ResourceCount = 1;
|
||||
planeParameters.ppResources = &backBuffer;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetCommandQueueDX12()->PresentX(1, &planeParameters, nullptr));
|
||||
VALIDATE_DIRECTX_CALL(_device->GetCommandQueueDX12()->PresentX(1, &planeParameters, nullptr));
|
||||
|
||||
// Base
|
||||
GPUSwapChain::Present(vsync);
|
||||
|
||||
@@ -113,7 +113,7 @@ bool GPUTextureDX12::OnInit()
|
||||
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
auto result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&resource));
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
||||
initResource(resource, D3D12_RESOURCE_STATE_COPY_DEST, 1);
|
||||
DX_SET_DEBUG_NAME(_resource, GetName());
|
||||
_memoryUsage = totalSize;
|
||||
@@ -184,7 +184,7 @@ bool GPUTextureDX12::OnInit()
|
||||
|
||||
// Create texture
|
||||
auto result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, initialState, clearValuePtr, IID_PPV_ARGS(&resource));
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
||||
|
||||
// Set state
|
||||
bool isRead = useSRV || useUAV;
|
||||
|
||||
@@ -37,7 +37,7 @@ void GPUTimerQueryDX12::End()
|
||||
heap.EndQuery(context, _end);
|
||||
|
||||
const auto queue = _device->GetCommandQueue()->GetCommandQueue();
|
||||
VALIDATE_DIRECTX_RESULT(queue->GetTimestampFrequency(&_gpuFrequency));
|
||||
VALIDATE_DIRECTX_CALL(queue->GetTimestampFrequency(&_gpuFrequency));
|
||||
|
||||
_endCalled = true;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ bool QueryHeapDX12::Init()
|
||||
heapDesc.Count = _queryHeapCount;
|
||||
heapDesc.NodeMask = 0;
|
||||
HRESULT result = _device->GetDevice()->CreateQueryHeap(&heapDesc, IID_PPV_ARGS(&_queryHeap));
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
||||
DX_SET_DEBUG_NAME(_queryHeap, "Query Heap");
|
||||
|
||||
// Create the result buffer
|
||||
@@ -64,7 +64,7 @@ bool QueryHeapDX12::Init()
|
||||
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
result = _device->GetDevice()->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&_resultBuffer));
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
||||
DX_SET_DEBUG_NAME(_resultBuffer, "Query Heap Result Buffer");
|
||||
|
||||
// Start out with an open query batch
|
||||
@@ -181,7 +181,7 @@ void* QueryHeapDX12::ResolveQuery(ElementHandle& handle)
|
||||
range.Begin = batch.Start * _resultSize;
|
||||
range.End = range.Begin + batch.Count * _resultSize;
|
||||
void* mapped = nullptr;
|
||||
VALIDATE_DIRECTX_RESULT(_resultBuffer->Map(0, &range, &mapped));
|
||||
VALIDATE_DIRECTX_CALL(_resultBuffer->Map(0, &range, &mapped));
|
||||
|
||||
// Copy the results data
|
||||
Platform::MemoryCopy(_resultData.Get() + range.Begin, (byte*)mapped + range.Begin, batch.Count * _resultSize);
|
||||
|
||||
@@ -229,7 +229,7 @@ UploadBufferPageDX12::UploadBufferPageDX12(GPUDeviceDX12* device, uint64 size)
|
||||
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
ID3D12Resource* resource;
|
||||
VALIDATE_DIRECTX_RESULT(_device->GetDevice()->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&resource)));
|
||||
VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&resource)));
|
||||
|
||||
// Set state
|
||||
initResource(resource, D3D12_RESOURCE_STATE_GENERIC_READ, 1);
|
||||
@@ -238,7 +238,7 @@ UploadBufferPageDX12::UploadBufferPageDX12(GPUDeviceDX12* device, uint64 size)
|
||||
GPUAddress = _resource->GetGPUVirtualAddress();
|
||||
|
||||
// Map buffer
|
||||
VALIDATE_DIRECTX_RESULT(_resource->Map(0, nullptr, &CPUAddress));
|
||||
VALIDATE_DIRECTX_CALL(_resource->Map(0, nullptr, &CPUAddress));
|
||||
}
|
||||
|
||||
void UploadBufferPageDX12::OnReleaseGPU()
|
||||
|
||||
@@ -272,15 +272,15 @@ namespace RenderToolsDX
|
||||
#if GPU_ENABLE_ASSERTION
|
||||
|
||||
// DirectX results validation
|
||||
#define VALIDATE_DIRECTX_RESULT(x) { HRESULT result = x; if (FAILED(result)) RenderToolsDX::ValidateD3DResult(result, __FILE__, __LINE__); }
|
||||
#define VALIDATE_DIRECTX_CALL(x) { HRESULT result = x; if (FAILED(result)) RenderToolsDX::ValidateD3DResult(result, __FILE__, __LINE__); }
|
||||
#define LOG_DIRECTX_RESULT(result) if (FAILED(result)) RenderToolsDX::LogD3DResult(result, __FILE__, __LINE__)
|
||||
#define LOG_DIRECTX_RESULT_WITH_RETURN(result) if (FAILED(result)) { RenderToolsDX::LogD3DResult(result, __FILE__, __LINE__); return true; }
|
||||
#define LOG_DIRECTX_RESULT_WITH_RETURN(result, returnValue) if (FAILED(result)) { RenderToolsDX::LogD3DResult(result, __FILE__, __LINE__); return returnValue; }
|
||||
|
||||
#else
|
||||
|
||||
#define VALIDATE_DIRECTX_RESULT(x) x
|
||||
#define VALIDATE_DIRECTX_CALL(x) x
|
||||
#define LOG_DIRECTX_RESULT(result) if(FAILED(result)) RenderToolsDX::LogD3DResult(result)
|
||||
#define LOG_DIRECTX_RESULT_WITH_RETURN(result) if(FAILED(result)) { RenderToolsDX::LogD3DResult(result); return true; }
|
||||
#define LOG_DIRECTX_RESULT_WITH_RETURN(result, returnValue) if(FAILED(result)) { RenderToolsDX::LogD3DResult(result); return returnValue; }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ void Skybox::ApplySky(GPUContext* context, RenderContext& renderContext, const M
|
||||
Platform::MemoryClear(&drawCall, sizeof(DrawCall));
|
||||
drawCall.World = world;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = _sphere.Radius;
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.WorldDeterminantSign = Math::FloatSelect(world.RotDeterminant(), 1, -1);
|
||||
drawCall.PerInstanceRandom = GetPerInstanceRandom();
|
||||
|
||||
@@ -405,6 +405,7 @@ void SplineModel::Draw(RenderContext& renderContext)
|
||||
const Transform splineTransform = GetTransform();
|
||||
renderContext.View.GetWorldMatrix(splineTransform, drawCall.World);
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation() + drawCall.Deformable.LocalMatrix.GetTranslation();
|
||||
drawCall.ObjectRadius = _sphere.Radius; // TODO: use radius for the spline chunk rather than whole spline
|
||||
const float worldDeterminantSign = drawCall.World.RotDeterminant() * drawCall.Deformable.LocalMatrix.RotDeterminant();
|
||||
for (int32 segment = 0; segment < _instances.Count(); segment++)
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ void SceneTicking::TickData::RemoveTick(void* callee)
|
||||
{
|
||||
for (int32 i = 0; i < Ticks.Count(); i++)
|
||||
{
|
||||
if (Ticks[i].Callee == callee)
|
||||
if (Ticks.Get()[i].Callee == callee)
|
||||
{
|
||||
Ticks.RemoveAt(i);
|
||||
break;
|
||||
@@ -45,7 +45,7 @@ void SceneTicking::TickData::Tick()
|
||||
TickScripts(Scripts);
|
||||
|
||||
for (int32 i = 0; i < Ticks.Count(); i++)
|
||||
Ticks[i].Call();
|
||||
Ticks.Get()[i].Call();
|
||||
}
|
||||
|
||||
#if USE_EDITOR
|
||||
@@ -54,7 +54,7 @@ void SceneTicking::TickData::RemoveTickExecuteInEditor(void* callee)
|
||||
{
|
||||
for (int32 i = 0; i < TicksExecuteInEditor.Count(); i++)
|
||||
{
|
||||
if (TicksExecuteInEditor[i].Callee == callee)
|
||||
if (TicksExecuteInEditor.Get()[i].Callee == callee)
|
||||
{
|
||||
TicksExecuteInEditor.RemoveAt(i);
|
||||
break;
|
||||
@@ -67,7 +67,7 @@ void SceneTicking::TickData::TickExecuteInEditor()
|
||||
TickScripts(ScriptsExecuteInEditor);
|
||||
|
||||
for (int32 i = 0; i < TicksExecuteInEditor.Count(); i++)
|
||||
TicksExecuteInEditor[i].Call();
|
||||
TicksExecuteInEditor.Get()[i].Call();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace
|
||||
FORCE_INLINE void InitFilter(dtQueryFilter& filter)
|
||||
{
|
||||
Platform::MemoryCopy(filter.m_areaCost, NavMeshRuntime::NavAreasCosts, sizeof(NavMeshRuntime::NavAreasCosts));
|
||||
static_assert(sizeof(dtQueryFilter::m_areaCost) == sizeof(NavMeshRuntime::NavAreasCosts), "Invalid navmesh area cost list.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -938,7 +938,8 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe
|
||||
// Setup a draw call common data
|
||||
DrawCall drawCall;
|
||||
drawCall.PerInstanceRandom = effect->GetPerInstanceRandom();
|
||||
drawCall.ObjectPosition = effect->GetPosition();
|
||||
drawCall.ObjectPosition = effect->GetSphere().Center - view.Origin;
|
||||
drawCall.ObjectRadius = effect->GetSphere().Radius;
|
||||
|
||||
// Draw all emitters
|
||||
for (int32 emitterIndex = 0; emitterIndex < effect->Instance.Emitters.Count(); emitterIndex++)
|
||||
|
||||
@@ -70,6 +70,53 @@ CFStringRef AppleUtils::ToString(const StringView& str)
|
||||
return CFStringCreateWithBytes(nullptr, (const UInt8*)str.GetText(), str.Length() * sizeof(Char), kCFStringEncodingUTF16LE, false);
|
||||
}
|
||||
|
||||
NSString* AppleUtils::ToNSString(const StringView& str)
|
||||
{
|
||||
NSString* ret = !str.IsEmpty() ? [[NSString alloc] initWithBytes: (const UInt8*)str.Get() length: str.Length() * sizeof(Char) encoding: NSUTF16LittleEndianStringEncoding] : nil;
|
||||
return ret ? ret : @"";
|
||||
}
|
||||
|
||||
NSString* AppleUtils::ToNSString(const char* string)
|
||||
{
|
||||
NSString* ret = string ? [NSString stringWithUTF8String: string] : nil;
|
||||
return ret ? ret : @"";
|
||||
}
|
||||
|
||||
|
||||
NSArray* AppleUtils::ParseArguments(NSString* argsString) {
|
||||
NSMutableArray *argsArray = [NSMutableArray array];
|
||||
NSMutableString *currentArg = [NSMutableString string];
|
||||
BOOL insideQuotes = NO;
|
||||
|
||||
for (NSInteger i = 0; i < argsString.length; ++i) {
|
||||
unichar c = [argsString characterAtIndex:i];
|
||||
|
||||
if (c == '\"') {
|
||||
if (insideQuotes) {
|
||||
[argsArray addObject:[currentArg copy]];
|
||||
[currentArg setString:@""];
|
||||
insideQuotes = NO;
|
||||
} else {
|
||||
insideQuotes = YES;
|
||||
}
|
||||
} else if (c == ' ' && !insideQuotes) {
|
||||
if (currentArg.length > 0) {
|
||||
[argsArray addObject:[currentArg copy]];
|
||||
[currentArg setString:@""];
|
||||
}
|
||||
} else {
|
||||
[currentArg appendFormat:@"%C", c];
|
||||
}
|
||||
}
|
||||
|
||||
if (currentArg.length > 0) {
|
||||
[argsArray addObject:[currentArg copy]];
|
||||
}
|
||||
|
||||
return [argsArray copy];
|
||||
}
|
||||
|
||||
|
||||
typedef uint16_t offset_t;
|
||||
#define align_mem_up(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
|
||||
@@ -13,6 +13,9 @@ class AppleUtils
|
||||
public:
|
||||
static String ToString(CFStringRef str);
|
||||
static CFStringRef ToString(const StringView& str);
|
||||
static NSString* ToNSString(const StringView& str);
|
||||
static NSString* ToNSString(const char* string);
|
||||
static NSArray* ParseArguments(NSString* argsString);
|
||||
#if PLATFORM_MAC
|
||||
static Float2 PosToCoca(const Float2& pos);
|
||||
static Float2 CocaToPos(const Float2& pos);
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace FlaxEngine
|
||||
AllowDragAndDrop = true,
|
||||
IsRegularWindow = true,
|
||||
HasSizingFrame = true,
|
||||
ShowAfterFirstPaint = true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(CreateWindowSettings);
|
||||
/// <summary>
|
||||
/// Enable/disable window auto-show after the first paint.
|
||||
/// </summary>
|
||||
API_FIELD() bool ShowAfterFirstPaint = false;
|
||||
API_FIELD() bool ShowAfterFirstPaint = true;
|
||||
|
||||
/// <summary>
|
||||
/// The custom data (platform dependant).
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "Windows/WindowsFileSystemWatcher.h"
|
||||
#elif PLATFORM_LINUX
|
||||
#include "Linux/LinuxFileSystemWatcher.h"
|
||||
#elif PLATFORM_MAC
|
||||
#include "Mac/MacFileSystemWatcher.h"
|
||||
#else
|
||||
#include "Base/FileSystemWatcherBase.h"
|
||||
#endif
|
||||
|
||||
@@ -136,7 +136,7 @@ bool LinuxFileSystem::ShowFileExplorer(const StringView& path)
|
||||
{
|
||||
const StringAsANSI<> pathAnsi(*path, path.Length());
|
||||
char cmd[2048];
|
||||
sprintf(cmd, "nautilus %s &", pathAnsi.Get());
|
||||
sprintf(cmd, "xdg-open %s &", pathAnsi.Get());
|
||||
system(cmd);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ bool MacFileSystem::ShowBrowseFolderDialog(Window* parentWindow, const StringVie
|
||||
|
||||
bool MacFileSystem::ShowFileExplorer(const StringView& path)
|
||||
{
|
||||
return Platform::StartProcess(TEXT("open"), String::Format(TEXT("\"{0}\""), path), StringView::Empty) != 0;
|
||||
return [[NSWorkspace sharedWorkspace] selectFile: AppleUtils::ToNSString(FileSystem::ConvertRelativePathToAbsolute(path)) inFileViewerRootedAtPath: @""];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
100
Source/Engine/Platform/Mac/MacFileSystemWatcher.cpp
Normal file
100
Source/Engine/Platform/Mac/MacFileSystemWatcher.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if PLATFORM_MAC
|
||||
#include "MacFileSystemWatcher.h"
|
||||
#include "Engine/Platform/Apple/AppleUtils.h"
|
||||
#include "Engine/Platform/CriticalSection.h"
|
||||
#include "Engine/Platform/Thread.h"
|
||||
#include "Engine/Threading/ThreadSpawner.h"
|
||||
#include "Engine/Core/Collections/Array.h"
|
||||
#include "Engine/Core/Types/StringView.h"
|
||||
|
||||
void DirectoryWatchCallback( ConstFSEventStreamRef StreamRef, void* FileWatcherPtr, size_t EventCount, void* EventPaths, const FSEventStreamEventFlags EventFlags[], const FSEventStreamEventId EventIDs[] )
|
||||
{
|
||||
MacFileSystemWatcher* macFileSystemWatcher = (MacFileSystemWatcher*)FileWatcherPtr;
|
||||
if (macFileSystemWatcher)
|
||||
{
|
||||
CFArrayRef EventPathArray = (CFArrayRef)EventPaths;
|
||||
for( size_t EventIndex = 0; EventIndex < EventCount; ++EventIndex )
|
||||
{
|
||||
const FSEventStreamEventFlags Flags = EventFlags[EventIndex];
|
||||
if( !(Flags & kFSEventStreamEventFlagItemIsFile) && !(Flags & kFSEventStreamEventFlagItemIsDir) )
|
||||
{
|
||||
// events about symlinks don't concern us
|
||||
continue;
|
||||
}
|
||||
|
||||
auto action = FileSystemAction::Unknown;
|
||||
|
||||
const bool added = ( Flags & kFSEventStreamEventFlagItemCreated );
|
||||
const bool renamed = ( Flags & kFSEventStreamEventFlagItemRenamed );
|
||||
const bool modified = ( Flags & kFSEventStreamEventFlagItemModified );
|
||||
const bool removed = ( Flags & kFSEventStreamEventFlagItemRemoved );
|
||||
|
||||
if (added)
|
||||
{
|
||||
action = FileSystemAction::Create;
|
||||
}
|
||||
|
||||
if (renamed || modified)
|
||||
{
|
||||
action = FileSystemAction::Delete;
|
||||
}
|
||||
|
||||
if (removed)
|
||||
{
|
||||
action = FileSystemAction::Modify;
|
||||
}
|
||||
|
||||
const String resolvedPath = AppleUtils::ToString((CFStringRef)CFArrayGetValueAtIndex(EventPathArray,EventIndex));
|
||||
|
||||
macFileSystemWatcher->OnEvent(resolvedPath, action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MacFileSystemWatcher::MacFileSystemWatcher(const String& directory, bool withSubDirs)
|
||||
: FileSystemWatcherBase(directory, withSubDirs)
|
||||
{
|
||||
|
||||
CFStringRef FullPathMac = AppleUtils::ToString(StringView(directory));
|
||||
CFArrayRef PathsToWatch = CFArrayCreate(NULL, (const void**)&FullPathMac, 1, NULL);
|
||||
|
||||
CFAbsoluteTime Latency = 0.2;
|
||||
|
||||
FSEventStreamContext Context;
|
||||
Context.version = 0;
|
||||
Context.info = this;
|
||||
Context.retain = NULL;
|
||||
Context.release = NULL;
|
||||
Context.copyDescription = NULL;
|
||||
|
||||
EventStream = FSEventStreamCreate( NULL,
|
||||
&DirectoryWatchCallback,
|
||||
&Context,
|
||||
PathsToWatch,
|
||||
kFSEventStreamEventIdSinceNow,
|
||||
Latency,
|
||||
kFSEventStreamCreateFlagUseCFTypes | kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents
|
||||
);
|
||||
|
||||
CFRelease(PathsToWatch);
|
||||
CFRelease(FullPathMac);
|
||||
|
||||
FSEventStreamScheduleWithRunLoop( EventStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode );
|
||||
FSEventStreamStart( EventStream );
|
||||
|
||||
IsRunning = true;
|
||||
}
|
||||
|
||||
MacFileSystemWatcher::~MacFileSystemWatcher()
|
||||
{
|
||||
if (IsRunning)
|
||||
{
|
||||
FSEventStreamStop(EventStream);
|
||||
FSEventStreamUnscheduleFromRunLoop(EventStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||
FSEventStreamInvalidate(EventStream);
|
||||
FSEventStreamRelease(EventStream);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
39
Source/Engine/Platform/Mac/MacFileSystemWatcher.h
Normal file
39
Source/Engine/Platform/Mac/MacFileSystemWatcher.h
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if PLATFORM_MAC
|
||||
#include "Engine/Platform/Base/FileSystemWatcherBase.h"
|
||||
|
||||
#include <CoreServices/CoreServices.h>
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Mac platform implementation of the file system watching object.
|
||||
/// </summary>
|
||||
class FLAXENGINE_API MacFileSystemWatcher : public FileSystemWatcherBase
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MacFileSystemWatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="directory">The directory to watch.</param>
|
||||
/// <param name="withSubDirs">True if monitor the directory tree rooted at the specified directory or just a given directory.</param>
|
||||
MacFileSystemWatcher(const String& directory, bool withSubDirs);
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="MacFileSystemWatcher"/> class.
|
||||
/// </summary>
|
||||
~MacFileSystemWatcher();
|
||||
|
||||
public:
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
FSEventStreamRef EventStream;
|
||||
bool IsRunning;
|
||||
};
|
||||
#endif
|
||||
@@ -324,13 +324,16 @@ void MacPlatform::BeforeRun()
|
||||
void MacPlatform::Tick()
|
||||
{
|
||||
// Process system events
|
||||
while (true)
|
||||
NSEvent* event = nil;
|
||||
do
|
||||
{
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES];
|
||||
if (event == nil)
|
||||
break;
|
||||
[NSApp sendEvent:event];
|
||||
}
|
||||
event = [NSApp nextEventMatchingMask: NSEventMaskAny untilDate: nil inMode: NSDefaultRunLoopMode dequeue: YES];
|
||||
if (event)
|
||||
{
|
||||
[NSApp sendEvent:event];
|
||||
}
|
||||
|
||||
} while(event);
|
||||
|
||||
ApplePlatform::Tick();
|
||||
}
|
||||
@@ -429,13 +432,6 @@ Window* MacPlatform::CreateWindow(const CreateWindowSettings& settings)
|
||||
int32 MacPlatform::CreateProcess(CreateProcessSettings& settings)
|
||||
{
|
||||
LOG(Info, "Command: {0} {1}", settings.FileName, settings.Arguments);
|
||||
String cwd;
|
||||
if (settings.WorkingDirectory.HasChars())
|
||||
{
|
||||
LOG(Info, "Working directory: {0}", settings.WorkingDirectory);
|
||||
cwd = Platform::GetWorkingDirectory();
|
||||
Platform::SetWorkingDirectory(settings.WorkingDirectory);
|
||||
}
|
||||
const bool captureStdOut = settings.LogOutput || settings.SaveOutput;
|
||||
|
||||
// Special case if filename points to the app package (use actual executable)
|
||||
@@ -462,44 +458,81 @@ int32 MacPlatform::CreateProcess(CreateProcessSettings& settings)
|
||||
}
|
||||
}
|
||||
|
||||
const String cmdLine = exePath + TEXT(" ") + settings.Arguments;
|
||||
const StringAsANSI<> cmdLineAnsi(*cmdLine, cmdLine.Length());
|
||||
FILE* pipe = popen(cmdLineAnsi.Get(), "r");
|
||||
if (cwd.Length() != 0)
|
||||
{
|
||||
Platform::SetWorkingDirectory(cwd);
|
||||
}
|
||||
if (!pipe)
|
||||
{
|
||||
LOG(Warning, "Failed to start process, errno={}", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO: environment
|
||||
NSTask *task = [[NSTask alloc] init];
|
||||
task.launchPath = AppleUtils::ToNSString(exePath);
|
||||
task.arguments = AppleUtils::ParseArguments(AppleUtils::ToNSString(settings.Arguments));
|
||||
if (settings.WorkingDirectory.HasChars())
|
||||
task.currentDirectoryPath = AppleUtils::ToNSString(settings.WorkingDirectory);
|
||||
|
||||
int32 returnCode = 0;
|
||||
if (settings.WaitForEnd)
|
||||
{
|
||||
id<NSObject> outputObserver = nil;
|
||||
|
||||
if (captureStdOut)
|
||||
{
|
||||
char lineBuffer[1024];
|
||||
while (fgets(lineBuffer, sizeof(lineBuffer), pipe) != NULL)
|
||||
NSPipe *stdoutPipe = [NSPipe pipe];
|
||||
[task setStandardOutput:stdoutPipe];
|
||||
|
||||
outputObserver = [[NSNotificationCenter defaultCenter]
|
||||
addObserverForName: NSFileHandleDataAvailableNotification
|
||||
object: [stdoutPipe fileHandleForReading]
|
||||
queue: nil
|
||||
usingBlock:^(NSNotification* notification)
|
||||
{
|
||||
char* p = lineBuffer + strlen(lineBuffer) - 1;
|
||||
if (*p == '\n') *p = 0;
|
||||
String line(lineBuffer);
|
||||
if (settings.SaveOutput)
|
||||
settings.Output.Add(line.Get(), line.Length());
|
||||
if (settings.LogOutput)
|
||||
Log::Logger::Write(LogType::Info, line);
|
||||
NSData* data = [stdoutPipe fileHandleForReading].availableData;
|
||||
if (data.length)
|
||||
{
|
||||
String line((const char*)data.bytes, data.length);
|
||||
if (settings.SaveOutput)
|
||||
settings.Output.Add(line.Get(), line.Length());
|
||||
if (settings.LogOutput)
|
||||
{
|
||||
StringView lineView(line);
|
||||
if (line[line.Length() - 1] == '\n')
|
||||
lineView = StringView(line.Get(), line.Length() - 1);
|
||||
Log::Logger::Write(LogType::Info, lineView);
|
||||
}
|
||||
[[stdoutPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
[[stdoutPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
|
||||
}
|
||||
else
|
||||
|
||||
String exception;
|
||||
@try
|
||||
{
|
||||
while (!feof(pipe))
|
||||
{
|
||||
sleep(1);
|
||||
}
|
||||
[task launch];
|
||||
[task waitUntilExit];
|
||||
returnCode = [task terminationStatus];
|
||||
}
|
||||
@catch (NSException* e)
|
||||
{
|
||||
exception = e.reason.UTF8String;
|
||||
}
|
||||
if (!exception.IsEmpty())
|
||||
{
|
||||
LOG(Error, "Failed to run command {0} {1} with error {2}", settings.FileName, settings.Arguments, exception);
|
||||
returnCode = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String exception;
|
||||
@try
|
||||
{
|
||||
[task launch];
|
||||
}
|
||||
@catch (NSException* e)
|
||||
{
|
||||
exception = e.reason.UTF8String;
|
||||
}
|
||||
if (!exception.IsEmpty())
|
||||
{
|
||||
LOG(Error, "Failed to run command {0} {1} with error {2}", settings.FileName, settings.Arguments, exception);
|
||||
returnCode = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -237,8 +237,8 @@ class UnixConditionVariable;
|
||||
typedef UnixConditionVariable ConditionVariable;
|
||||
class MacFileSystem;
|
||||
typedef MacFileSystem FileSystem;
|
||||
class FileSystemWatcherBase;
|
||||
typedef FileSystemWatcherBase FileSystemWatcher;
|
||||
class MacFileSystemWatcher;
|
||||
typedef MacFileSystemWatcher FileSystemWatcher;
|
||||
class UnixFile;
|
||||
typedef UnixFile File;
|
||||
class MacPlatform;
|
||||
|
||||
@@ -258,6 +258,11 @@ struct DrawCall
|
||||
/// </summary>
|
||||
Float3 ObjectPosition;
|
||||
|
||||
/// <summary>
|
||||
/// Object bounding sphere radius that contains it whole (sphere at ObjectPosition).
|
||||
/// </summary>
|
||||
float ObjectRadius;
|
||||
|
||||
/// <summary>
|
||||
/// The world matrix determinant sign (used for geometry that is two sided or has inverse scale - needs to flip normal vectors and change triangles culling).
|
||||
/// </summary>
|
||||
|
||||
@@ -464,6 +464,7 @@ void GBufferPass::DrawDecals(RenderContext& renderContext, GPUTextureView* light
|
||||
transform.Scale *= decal->GetSize();
|
||||
renderContext.View.GetWorldMatrix(transform, drawCall.World);
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = decal->GetSphere().Radius;
|
||||
|
||||
context->ResetRenderTarget();
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ PACK_STRUCT(struct HistogramData {
|
||||
GPUBuffer* HistogramPass::Render(RenderContext& renderContext, GPUTexture* colorBuffer)
|
||||
{
|
||||
auto device = GPUDevice::Instance;
|
||||
auto context = device->GetMainContext();;
|
||||
auto context = device->GetMainContext();
|
||||
if (checkIfSkipPass() || !_isSupported)
|
||||
return nullptr;
|
||||
|
||||
|
||||
@@ -855,6 +855,7 @@ DRAW:
|
||||
{
|
||||
auto& batch = BatchedDrawCalls.Get()[list.PreBatchedDrawCalls.Get()[i]];
|
||||
auto drawCall = batch.DrawCall;
|
||||
drawCall.ObjectRadius = 0.0f;
|
||||
bindParams.FirstDrawCall = &drawCall;
|
||||
const auto* instancesData = batch.Instances.Get();
|
||||
|
||||
|
||||
@@ -1009,12 +1009,36 @@ void ManagedBinaryModule::InitType(MClass* mclass)
|
||||
}
|
||||
if (baseType.Module == this)
|
||||
InitType(baseClass); // Ensure base is initialized before
|
||||
|
||||
baseType.Module->TypeNameToTypeIndex.TryGet(baseClass->GetFullName(), *(int32*)&baseType.TypeIndex);
|
||||
|
||||
// So we must special case this flow of a generic class of which its possible the generic base class is not in the same module
|
||||
if (baseType.TypeIndex == -1 && baseClass->IsGeneric())
|
||||
{
|
||||
auto genericNameIndex = baseClass->GetFullName().FindLast('`');
|
||||
// we add 2 because of the way generic names work its `N
|
||||
auto genericClassName = baseClass->GetFullName().Substring(0, genericNameIndex + 2);
|
||||
|
||||
// We check for the generic class name instead of the baseclass fullname
|
||||
baseType.Module->TypeNameToTypeIndex.TryGet(genericClassName, *(int32*)&baseType.TypeIndex);
|
||||
}
|
||||
|
||||
if (!baseType)
|
||||
{
|
||||
LOG(Error, "Missing base class for managed class {0} from assembly {1}.", String(typeName), Assembly->ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (baseType.TypeIndex == -1)
|
||||
{
|
||||
if (baseType.Module)
|
||||
LOG(Error, "Missing base class for managed class {0} from assembly {1}.", String(baseClass->GetFullName()), baseType.Module->GetName().ToString());
|
||||
else
|
||||
// Not sure this can happen but never hurts to account for it
|
||||
LOG(Error, "Missing base class for managed class {0} from unknown assembly.", String(baseClass->GetFullName()));
|
||||
return;
|
||||
}
|
||||
|
||||
ScriptingTypeHandle nativeType = baseType;
|
||||
while (true)
|
||||
{
|
||||
|
||||
@@ -85,6 +85,7 @@ public:
|
||||
static MClass* GetClass(MClass* elementKlass);
|
||||
static int32 GetLength(const MArray* obj);
|
||||
static void* GetAddress(const MArray* obj);
|
||||
static MArray* Unbox(MObject* obj);
|
||||
|
||||
template<typename T>
|
||||
FORCE_INLINE static T* GetAddress(const MArray* obj)
|
||||
|
||||
@@ -363,11 +363,12 @@ struct MConverter<Array<T>>
|
||||
|
||||
void Unbox(Array<T>& result, MObject* data)
|
||||
{
|
||||
const int32 length = data ? MCore::Array::GetLength((MArray*)data) : 0;
|
||||
MArray* array = MCore::Array::Unbox(data);
|
||||
const int32 length = array ? MCore::Array::GetLength(array) : 0;
|
||||
result.Resize(length);
|
||||
MConverter<T> converter;
|
||||
Span<T> resultSpan(result.Get(), length);
|
||||
converter.ToNativeArray(resultSpan, (MArray*)data);
|
||||
converter.ToNativeArray(resultSpan, array);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -408,6 +408,12 @@ void* MCore::Array::GetAddress(const MArray* obj)
|
||||
return CallStaticMethod<void*, void*>(GetArrayPointerPtr, (void*)obj);
|
||||
}
|
||||
|
||||
MArray* MCore::Array::Unbox(MObject* obj)
|
||||
{
|
||||
static void* GetArrayPtr = GetStaticMethodPointer(TEXT("GetArray"));
|
||||
return (MArray*)CallStaticMethod<void*, void*>(GetArrayPtr, (void*)obj);
|
||||
}
|
||||
|
||||
MGCHandle MCore::GCHandle::New(MObject* obj, bool pinned)
|
||||
{
|
||||
ASSERT(obj);
|
||||
@@ -697,13 +703,10 @@ bool MAssembly::LoadImage(const String& assemblyPath, const StringView& nativePa
|
||||
{
|
||||
// TODO: Use new hostfxr delegate load_assembly_bytes? (.NET 8+)
|
||||
// Open .Net assembly
|
||||
const StringAnsi assemblyPathAnsi = assemblyPath.ToStringAnsi();
|
||||
const char* name;
|
||||
const char* fullname;
|
||||
const char* name = nullptr;
|
||||
const char* fullname = nullptr;
|
||||
static void* LoadAssemblyImagePtr = GetStaticMethodPointer(TEXT("LoadAssemblyImage"));
|
||||
_handle = CallStaticMethod<void*, const char*, const char**, const char**>(LoadAssemblyImagePtr, assemblyPathAnsi.Get(), &name, &fullname);
|
||||
_name = name;
|
||||
_fullname = fullname;
|
||||
_handle = CallStaticMethod<void*, const Char*, const char**, const char**>(LoadAssemblyImagePtr, assemblyPath.Get(), &name, &fullname);
|
||||
MCore::GC::FreeMemory((void*)name);
|
||||
MCore::GC::FreeMemory((void*)fullname);
|
||||
if (_handle == nullptr)
|
||||
@@ -711,6 +714,8 @@ bool MAssembly::LoadImage(const String& assemblyPath, const StringView& nativePa
|
||||
Log::CLRInnerException(TEXT(".NET assembly image is invalid at ") + assemblyPath);
|
||||
return true;
|
||||
}
|
||||
_name = name;
|
||||
_fullname = fullname;
|
||||
CachedAssemblyHandles.Add(_handle, this);
|
||||
|
||||
// Provide new path of hot-reloaded native library path for managed DllImport
|
||||
@@ -719,6 +724,13 @@ bool MAssembly::LoadImage(const String& assemblyPath, const StringView& nativePa
|
||||
StringAnsi nativeName = _name.EndsWith(".CSharp") ? StringAnsi(_name.Get(), _name.Length() - 7) : StringAnsi(_name);
|
||||
RegisterNativeLibrary(nativeName.Get(), StringAnsi(nativePath).Get());
|
||||
}
|
||||
#if USE_EDITOR
|
||||
// Register the editor module location for Assembly resolver
|
||||
else
|
||||
{
|
||||
RegisterNativeLibrary(_name.Get(), StringAnsi(assemblyPath).Get());
|
||||
}
|
||||
#endif
|
||||
|
||||
_hasCachedClasses = false;
|
||||
_assemblyPath = assemblyPath;
|
||||
@@ -898,7 +910,6 @@ const Array<MMethod*>& MClass::GetMethods() const
|
||||
NativeMethodDefinitions& definition = methods[i];
|
||||
MMethod* method = New<MMethod>(const_cast<MClass*>(this), StringAnsi(definition.name), definition.handle, definition.numParameters, definition.methodAttributes);
|
||||
_methods.Add(method);
|
||||
|
||||
MCore::GC::FreeMemory((void*)definition.name);
|
||||
}
|
||||
MCore::GC::FreeMemory(methods);
|
||||
@@ -932,7 +943,6 @@ const Array<MField*>& MClass::GetFields() const
|
||||
NativeFieldDefinitions& definition = fields[i];
|
||||
MField* field = New<MField>(const_cast<MClass*>(this), definition.fieldHandle, definition.name, definition.fieldType, definition.fieldAttributes);
|
||||
_fields.Add(field);
|
||||
|
||||
MCore::GC::FreeMemory((void*)definition.name);
|
||||
}
|
||||
MCore::GC::FreeMemory(fields);
|
||||
@@ -977,7 +987,6 @@ const Array<MProperty*>& MClass::GetProperties() const
|
||||
const NativePropertyDefinitions& definition = foundProperties[i];
|
||||
MProperty* property = New<MProperty>(const_cast<MClass*>(this), definition.name, definition.getterHandle, definition.setterHandle, definition.getterAttributes, definition.setterAttributes);
|
||||
_properties.Add(property);
|
||||
|
||||
MCore::GC::FreeMemory((void*)definition.name);
|
||||
}
|
||||
MCore::GC::FreeMemory(foundProperties);
|
||||
@@ -1541,7 +1550,16 @@ bool InitHostfxr()
|
||||
get_hostfxr_params.size = sizeof(hostfxr_initialize_parameters);
|
||||
get_hostfxr_params.assembly_path = libraryPath.Get();
|
||||
#if PLATFORM_MAC
|
||||
get_hostfxr_params.dotnet_root = "/usr/local/share/dotnet";
|
||||
::String macOSDotnetRoot = TEXT("/usr/local/share/dotnet");
|
||||
#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(_M_X64)
|
||||
// When emulating x64 on arm
|
||||
const ::String dotnetRootEmulated = macOSDotnetRoot / TEXT("x64");
|
||||
if (FileSystem::FileExists(dotnetRootEmulated / TEXT("dotnet"))) {
|
||||
macOSDotnetRoot = dotnetRootEmulated;
|
||||
}
|
||||
#endif
|
||||
const FLAX_CORECLR_STRING& finalDotnetRootPath = FLAX_CORECLR_STRING(macOSDotnetRoot);
|
||||
get_hostfxr_params.dotnet_root = finalDotnetRootPath.Get();
|
||||
#else
|
||||
get_hostfxr_params.dotnet_root = nullptr;
|
||||
#endif
|
||||
@@ -1588,7 +1606,10 @@ bool InitHostfxr()
|
||||
void* hostfxr = Platform::LoadLibrary(path.Get());
|
||||
if (hostfxr == nullptr)
|
||||
{
|
||||
LOG(Fatal, "Failed to load hostfxr library ({0})", path);
|
||||
if (FileSystem::FileExists(path))
|
||||
LOG(Fatal, "Failed to load hostfxr library, possible platform/architecture mismatch with the library. See log for more information. ({0})", path);
|
||||
else
|
||||
LOG(Fatal, "Failed to load hostfxr library ({0})", path);
|
||||
return true;
|
||||
}
|
||||
hostfxr_initialize_for_runtime_config = (hostfxr_initialize_for_runtime_config_fn)Platform::GetProcAddress(hostfxr, "hostfxr_initialize_for_runtime_config");
|
||||
@@ -1627,7 +1648,28 @@ bool InitHostfxr()
|
||||
if (rc != 0 || handle == nullptr)
|
||||
{
|
||||
hostfxr_close(handle);
|
||||
LOG(Fatal, "Failed to initialize hostfxr: {0:x} ({1})", (unsigned int)rc, String(init_params.dotnet_root));
|
||||
if (rc == 0x80008096) // FrameworkMissingFailure
|
||||
{
|
||||
String platformStr;
|
||||
switch (PLATFORM_TYPE)
|
||||
{
|
||||
case PlatformType::Windows:
|
||||
case PlatformType::UWP:
|
||||
platformStr = PLATFORM_64BITS ? "Windows x64" : "Windows x86";
|
||||
break;
|
||||
case PlatformType::Linux:
|
||||
platformStr = PLATFORM_ARCH_ARM64 ? "Linux Arm64" : PLATFORM_ARCH_ARM ? "Linux Arm32" : PLATFORM_64BITS ? "Linux x64" : "Linux x86";
|
||||
break;
|
||||
case PlatformType::Mac:
|
||||
platformStr = PLATFORM_ARCH_ARM || PLATFORM_ARCH_ARM64 ? "macOS Arm64" : PLATFORM_64BITS ? "macOS x64" : "macOS x86";
|
||||
break;
|
||||
default:;
|
||||
platformStr = "";
|
||||
}
|
||||
LOG(Fatal, "Failed to resolve compatible .NET runtime version in '{0}'. Make sure the correct platform version for runtime is installed ({1})", platformStr, String(init_params.dotnet_root));
|
||||
}
|
||||
else
|
||||
LOG(Fatal, "Failed to initialize hostfxr: {0:x} ({1})", (unsigned int)rc, String(init_params.dotnet_root));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -804,6 +804,11 @@ void* MCore::Array::GetAddress(const MArray* obj)
|
||||
return mono_array_addr_with_size((MonoArray*)obj, 0, 0);
|
||||
}
|
||||
|
||||
MArray* MCore::Array::Unbox(MObject* obj)
|
||||
{
|
||||
return (MArray*)obj;
|
||||
}
|
||||
|
||||
MGCHandle MCore::GCHandle::New(MObject* obj, bool pinned)
|
||||
{
|
||||
return mono_gchandle_new(obj, pinned);
|
||||
|
||||
@@ -141,6 +141,11 @@ void* MCore::Array::GetAddress(const MArray* obj)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MArray* MCore::Array::Unbox(MObject* obj)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MGCHandle MCore::GCHandle::New(MObject* obj, bool pinned)
|
||||
{
|
||||
return (MGCHandle)(uintptr)obj;
|
||||
|
||||
@@ -45,7 +45,7 @@ bool TerrainChunk::PrepareDraw(const RenderContext& renderContext)
|
||||
|
||||
// Calculate chunk distance to view
|
||||
const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View);
|
||||
const float distance = Float3::Distance(_boundsCenter - lodView->Origin, lodView->Position);
|
||||
const float distance = Float3::Distance(_sphere.Center - lodView->Origin, lodView->Position);
|
||||
lod = (int32)Math::Pow(distance / chunkEdgeSize, lodDistribution);
|
||||
lod += lodBias;
|
||||
|
||||
@@ -88,6 +88,7 @@ void TerrainChunk::Draw(const RenderContext& renderContext) const
|
||||
drawCall.Material = _cachedDrawMaterial;
|
||||
renderContext.View.GetWorldMatrix(_transform, drawCall.World);
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = _sphere.Radius;
|
||||
drawCall.Terrain.Patch = _patch;
|
||||
drawCall.Terrain.HeightmapUVScaleBias = _heightmapUVScaleBias;
|
||||
drawCall.Terrain.OffsetUV = Vector2((float)(_patch->_x * TerrainPatch::CHUNKS_COUNT_EDGE + _x), (float)(_patch->_z * TerrainPatch::CHUNKS_COUNT_EDGE + _z));
|
||||
@@ -145,6 +146,7 @@ void TerrainChunk::Draw(const RenderContext& renderContext, MaterialBase* materi
|
||||
drawCall.Material = material;
|
||||
renderContext.View.GetWorldMatrix(_transform, drawCall.World);
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = _sphere.Radius;
|
||||
drawCall.Terrain.Patch = _patch;
|
||||
drawCall.Terrain.HeightmapUVScaleBias = _heightmapUVScaleBias;
|
||||
drawCall.Terrain.OffsetUV = Vector2((float)(_patch->_x * TerrainPatch::CHUNKS_COUNT_EDGE + _x), (float)(_patch->_z * TerrainPatch::CHUNKS_COUNT_EDGE + _z));
|
||||
@@ -202,7 +204,7 @@ void TerrainChunk::UpdateBounds()
|
||||
OrientedBoundingBox obb(Vector3::Zero, Vector3::One);
|
||||
obb.Transform(localTransform);
|
||||
obb.GetBoundingBox(_bounds);
|
||||
_boundsCenter = _bounds.GetCenter();
|
||||
BoundingSphere::FromBox(_bounds, _sphere);
|
||||
|
||||
_bounds.Minimum -= boundsExtent;
|
||||
_bounds.Maximum += boundsExtent;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Core/Math/BoundingBox.h"
|
||||
#include "Engine/Core/Math/BoundingSphere.h"
|
||||
#include "Engine/Core/Math/Matrix.h"
|
||||
#include "Engine/Core/Math/Transform.h"
|
||||
#include "Engine/Core/ISerializable.h"
|
||||
@@ -29,7 +30,7 @@ private:
|
||||
Float4 _heightmapUVScaleBias;
|
||||
Transform _transform;
|
||||
BoundingBox _bounds;
|
||||
Vector3 _boundsCenter;
|
||||
BoundingSphere _sphere;
|
||||
float _perInstanceRandom;
|
||||
float _yOffset, _yHeight;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace FlaxEngine.Tests
|
||||
{
|
||||
var result = 0;
|
||||
var libraryName = "FlaxEngine";
|
||||
var library = NativeLibrary.Load(Interop.NativeInterop.nativeLibraryPaths[libraryName]);
|
||||
var library = NativeLibrary.Load(Interop.NativeInterop.libraryPaths[libraryName]);
|
||||
if (library == IntPtr.Zero)
|
||||
return -1;
|
||||
var types = typeof(FlaxEngine.Object).Assembly.GetTypes();
|
||||
|
||||
@@ -42,7 +42,16 @@ public:
|
||||
void write(const char* message) override
|
||||
{
|
||||
String s(message);
|
||||
s.Replace('\n', ' ');
|
||||
if (s.Length() <= 0)
|
||||
return;
|
||||
for (int32 i = 0; i < s.Length(); i++)
|
||||
{
|
||||
Char& c = s[i];
|
||||
if (c == '\n')
|
||||
c = ' ';
|
||||
else if (c >= 255)
|
||||
c = '?';
|
||||
}
|
||||
LOG(Info, "[Assimp]: {0}", s);
|
||||
}
|
||||
};
|
||||
@@ -557,12 +566,17 @@ bool ImportMaterials(ImportedModelData& result, AssimpImporterData& data, String
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsMeshInvalid(const aiMesh* aMesh)
|
||||
{
|
||||
return aMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE || aMesh->mNumVertices == 0 || aMesh->mNumFaces == 0 || aMesh->mFaces[0].mNumIndices != 3;
|
||||
}
|
||||
|
||||
bool ImportMesh(int32 i, ImportedModelData& result, AssimpImporterData& data, String& errorMsg)
|
||||
{
|
||||
const auto aMesh = data.Scene->mMeshes[i];
|
||||
|
||||
// Skip invalid meshes
|
||||
if (aMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE || aMesh->mNumVertices == 0 || aMesh->mNumFaces == 0 || aMesh->mFaces[0].mNumIndices != 3)
|
||||
if (IsMeshInvalid(aMesh))
|
||||
return false;
|
||||
|
||||
// Skip unused meshes
|
||||
@@ -707,13 +721,13 @@ bool ModelTool::ImportDataAssimp(const char* path, ImportedModelData& data, Opti
|
||||
if (EnumHasAnyFlags(data.Types, ImportDataTypes::Geometry) && context->Scene->HasMeshes())
|
||||
{
|
||||
const int meshCount = context->Scene->mNumMeshes;
|
||||
if (options.SplitObjects && options.ObjectIndex == -1)
|
||||
if (options.SplitObjects && options.ObjectIndex == -1 && meshCount > 1)
|
||||
{
|
||||
// Import the first object within this call
|
||||
options.SplitObjects = false;
|
||||
options.ObjectIndex = 0;
|
||||
|
||||
if (meshCount > 1 && options.OnSplitImport.IsBinded())
|
||||
if (options.OnSplitImport.IsBinded())
|
||||
{
|
||||
// Split all animations into separate assets
|
||||
LOG(Info, "Splitting imported {0} meshes", meshCount);
|
||||
@@ -780,13 +794,13 @@ bool ModelTool::ImportDataAssimp(const char* path, ImportedModelData& data, Opti
|
||||
if (EnumHasAnyFlags(data.Types, ImportDataTypes::Animations) && context->Scene->HasAnimations())
|
||||
{
|
||||
const int32 animCount = (int32)context->Scene->mNumAnimations;
|
||||
if (options.SplitObjects && options.ObjectIndex == -1)
|
||||
if (options.SplitObjects && options.ObjectIndex == -1 && animCount > 1)
|
||||
{
|
||||
// Import the first object within this call
|
||||
options.SplitObjects = false;
|
||||
options.ObjectIndex = 0;
|
||||
|
||||
if (animCount > 1 && options.OnSplitImport.IsBinded())
|
||||
if (options.OnSplitImport.IsBinded())
|
||||
{
|
||||
// Split all animations into separate assets
|
||||
LOG(Info, "Splitting imported {0} animations", animCount);
|
||||
|
||||
@@ -924,8 +924,6 @@ bool ImportMesh(int32 index, ImportedModelData& result, OpenFbxImporterData& dat
|
||||
const auto aMesh = data.Scene->getMesh(index);
|
||||
const auto aGeometry = aMesh->getGeometry();
|
||||
const auto trianglesCount = aGeometry->getVertexCount() / 3;
|
||||
|
||||
// Skip invalid meshes
|
||||
if (IsMeshInvalid(aMesh))
|
||||
return false;
|
||||
|
||||
@@ -1246,13 +1244,13 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
|
||||
if (EnumHasAnyFlags(data.Types, ImportDataTypes::Geometry) && context->Scene->getMeshCount() > 0)
|
||||
{
|
||||
const int meshCount = context->Scene->getMeshCount();
|
||||
if (options.SplitObjects && options.ObjectIndex == -1)
|
||||
if (options.SplitObjects && options.ObjectIndex == -1 && meshCount > 1)
|
||||
{
|
||||
// Import the first object within this call
|
||||
options.SplitObjects = false;
|
||||
options.ObjectIndex = 0;
|
||||
|
||||
if (meshCount > 1 && options.OnSplitImport.IsBinded())
|
||||
if (options.OnSplitImport.IsBinded())
|
||||
{
|
||||
// Split all animations into separate assets
|
||||
LOG(Info, "Splitting imported {0} meshes", meshCount);
|
||||
@@ -1273,6 +1271,22 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
|
||||
const auto meshIndex = Math::Clamp<int32>(options.ObjectIndex, 0, meshCount - 1);
|
||||
if (ImportMesh(meshIndex, data, *context, errorMsg))
|
||||
return true;
|
||||
|
||||
// Let the firstly imported mesh import all materials from all meshes (index 0 is importing all following ones before itself during splitting - see code above)
|
||||
if (options.ObjectIndex == 1)
|
||||
{
|
||||
for (int32 i = 0; i < meshCount; i++)
|
||||
{
|
||||
const auto aMesh = context->Scene->getMesh(i);
|
||||
if (i == 1 || IsMeshInvalid(aMesh))
|
||||
continue;
|
||||
for (int32 j = 0; j < aMesh->getMaterialCount(); j++)
|
||||
{
|
||||
const ofbx::Material* aMaterial = aMesh->getMaterial(j);
|
||||
context->AddMaterial(data, aMaterial);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1329,13 +1343,13 @@ bool ModelTool::ImportDataOpenFBX(const char* path, ImportedModelData& data, Opt
|
||||
if (EnumHasAnyFlags(data.Types, ImportDataTypes::Animations))
|
||||
{
|
||||
const int animCount = context->Scene->getAnimationStackCount();
|
||||
if (options.SplitObjects && options.ObjectIndex == -1)
|
||||
if (options.SplitObjects && options.ObjectIndex == -1 && animCount > 1)
|
||||
{
|
||||
// Import the first object within this call
|
||||
options.SplitObjects = false;
|
||||
options.ObjectIndex = 0;
|
||||
|
||||
if (animCount > 1 && options.OnSplitImport.IsBinded())
|
||||
if (options.OnSplitImport.IsBinded())
|
||||
{
|
||||
// Split all animations into separate assets
|
||||
LOG(Info, "Splitting imported {0} animations", animCount);
|
||||
|
||||
@@ -60,6 +60,7 @@ public class Slider : ContainerControl
|
||||
private float _thumbCenter;
|
||||
private Float2 _thumbSize = new Float2(16, 16);
|
||||
private bool _isSliding;
|
||||
private bool _mouseOverThumb;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value (normalized to range 0-100).
|
||||
@@ -163,21 +164,27 @@ public class Slider : ContainerControl
|
||||
public IBrush FillTrackBrush { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The color of the slider thumb when it's not selected
|
||||
/// The color of the slider thumb when it's not selected.
|
||||
/// </summary>
|
||||
[EditorDisplay("Thumb Style"), EditorOrder(2030), Tooltip("The color of the slider thumb when it's not selected."), ExpandGroups]
|
||||
public Color ThumbColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The color of the slider thumb when it's highlighted.
|
||||
/// </summary>
|
||||
[EditorDisplay("Thumb Style"), EditorOrder(2031), Tooltip("The color of the slider thumb when it's highlighted.")]
|
||||
public Color ThumbColorHighlighted { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The color of the slider thumb when it's selected
|
||||
/// The color of the slider thumb when it's selected.
|
||||
/// </summary>
|
||||
[EditorDisplay("Thumb Style"), EditorOrder(2031), Tooltip("The color of the slider thumb when it's selected.")]
|
||||
[EditorDisplay("Thumb Style"), EditorOrder(2032), Tooltip("The color of the slider thumb when it's selected.")]
|
||||
public Color ThumbColorSelected { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the brush used for slider thumb drawing.
|
||||
/// </summary>
|
||||
[EditorDisplay("Thumb Style"), EditorOrder(2032), Tooltip("The brush of the slider thumb.")]
|
||||
[EditorDisplay("Thumb Style"), EditorOrder(2033), Tooltip("The brush of the slider thumb.")]
|
||||
public IBrush ThumbBrush { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -222,6 +229,7 @@ public class Slider : ContainerControl
|
||||
TrackFillLineColor = style.LightBackground;
|
||||
ThumbColor = style.BackgroundNormal;
|
||||
ThumbColorSelected = style.BackgroundSelected;
|
||||
ThumbColorHighlighted = style.BackgroundHighlighted;
|
||||
UpdateThumb();
|
||||
}
|
||||
|
||||
@@ -270,7 +278,7 @@ public class Slider : ContainerControl
|
||||
}
|
||||
|
||||
// Draw thumb
|
||||
var thumbColor = _isSliding ? ThumbColorSelected : ThumbColor;
|
||||
var thumbColor = _isSliding ? ThumbColorSelected : (_mouseOverThumb ? ThumbColorHighlighted : ThumbColor);
|
||||
if (ThumbBrush != null)
|
||||
ThumbBrush.Draw(_thumbRect, thumbColor);
|
||||
else
|
||||
@@ -317,6 +325,7 @@ public class Slider : ContainerControl
|
||||
/// <inheritdoc />
|
||||
public override void OnMouseMove(Float2 location)
|
||||
{
|
||||
_mouseOverThumb = _thumbRect.Contains(location);
|
||||
if (_isSliding)
|
||||
{
|
||||
// Update sliding
|
||||
|
||||
@@ -11,6 +11,11 @@ namespace FlaxEngine.GUI
|
||||
/// </summary>
|
||||
public abstract class TextBoxBase : ContainerControl
|
||||
{
|
||||
/// <summary>
|
||||
/// The delete control character (used for text filtering).
|
||||
/// </summary>
|
||||
protected const char DelChar = (char)0x7F;
|
||||
|
||||
/// <summary>
|
||||
/// The text separators (used for words skipping).
|
||||
/// </summary>
|
||||
@@ -351,6 +356,10 @@ namespace FlaxEngine.GUI
|
||||
if (value.IndexOf('\r') != -1)
|
||||
value = value.Replace("\r", "");
|
||||
|
||||
// Filter text (handle backspace control character)
|
||||
if (value.IndexOf(DelChar) != -1)
|
||||
value = value.Replace(DelChar.ToString(), "");
|
||||
|
||||
// Clamp length
|
||||
if (value.Length > MaxLength)
|
||||
value = value.Substring(0, MaxLength);
|
||||
@@ -673,6 +682,8 @@ namespace FlaxEngine.GUI
|
||||
// Filter text
|
||||
if (str.IndexOf('\r') != -1)
|
||||
str = str.Replace("\r", "");
|
||||
if (str.IndexOf(DelChar) != -1)
|
||||
str = str.Replace(DelChar.ToString(), "");
|
||||
if (!IsMultiline && str.IndexOf('\n') != -1)
|
||||
str = str.Replace("\n", "");
|
||||
|
||||
@@ -1327,6 +1338,15 @@ namespace FlaxEngine.GUI
|
||||
if (IsReadOnly)
|
||||
return true;
|
||||
|
||||
if (ctrDown)
|
||||
{
|
||||
int prevWordBegin = FindPrevWordBegin();
|
||||
_text = _text.Remove(prevWordBegin, CaretPosition - prevWordBegin);
|
||||
SetSelection(prevWordBegin);
|
||||
OnTextChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
int left = SelectionLeft;
|
||||
if (HasSelection)
|
||||
{
|
||||
|
||||
@@ -360,7 +360,7 @@ namespace FlaxEngine.GUI
|
||||
{
|
||||
var containerControl = child as ContainerControl;
|
||||
var childAtRecursive = containerControl?.GetChildAtRecursive(childLocation);
|
||||
if (childAtRecursive != null)
|
||||
if (childAtRecursive != null && childAtRecursive.Visible)
|
||||
{
|
||||
child = childAtRecursive;
|
||||
}
|
||||
@@ -507,15 +507,19 @@ namespace FlaxEngine.GUI
|
||||
|
||||
// Perform automatic navigation based on the layout
|
||||
var result = NavigationRaycast(direction, location, visited);
|
||||
if (result == null && direction == NavDirection.Next)
|
||||
var rightMostLocation = location;
|
||||
if (result == null && (direction == NavDirection.Next || direction == NavDirection.Previous))
|
||||
{
|
||||
// Try wrap the navigation over the layout based on the direction
|
||||
var visitedWrap = new List<Control>(visited);
|
||||
result = NavigationWrap(direction, location, visitedWrap);
|
||||
result = NavigationWrap(direction, location, visitedWrap, out rightMostLocation);
|
||||
}
|
||||
if (result != null)
|
||||
{
|
||||
result = result.OnNavigate(direction, result.PointFromParent(location), this, visited);
|
||||
// HACK: only the 'previous' direction needs the rightMostLocation so i used a ternary conditional operator.
|
||||
// The rightMostLocation can probably become a 'desired raycast origin' that gets calculated correctly in the NavigationWrap method.
|
||||
var useLocation = direction == NavDirection.Previous ? rightMostLocation : location;
|
||||
result = result.OnNavigate(direction, result.PointFromParent(useLocation), this, visited);
|
||||
if (result != null)
|
||||
return result;
|
||||
}
|
||||
@@ -551,8 +555,9 @@ namespace FlaxEngine.GUI
|
||||
/// <param name="direction">The navigation direction.</param>
|
||||
/// <param name="location">The navigation start location (in the control-space).</param>
|
||||
/// <param name="visited">The list with visited controls. Used to skip recursive navigation calls when doing traversal across the UI hierarchy.</param>
|
||||
/// <param name="rightMostLocation">Returns the rightmost location of the parent container for the raycast used by the child container</param>
|
||||
/// <returns>The target navigation control or null if didn't performed any navigation.</returns>
|
||||
protected virtual Control NavigationWrap(NavDirection direction, Float2 location, List<Control> visited)
|
||||
protected virtual Control NavigationWrap(NavDirection direction, Float2 location, List<Control> visited, out Float2 rightMostLocation)
|
||||
{
|
||||
// This searches form a child that calls this navigation event (see Control.OnNavigate) to determinate the layout wrapping size based on that child size
|
||||
var currentChild = RootWindow?.FocusedControl;
|
||||
@@ -566,15 +571,22 @@ namespace FlaxEngine.GUI
|
||||
case NavDirection.Next:
|
||||
predictedLocation = new Float2(0, location.Y + layoutSize.Y);
|
||||
break;
|
||||
case NavDirection.Previous:
|
||||
predictedLocation = new Float2(Size.X, location.Y - layoutSize.Y);
|
||||
break;
|
||||
}
|
||||
if (new Rectangle(Float2.Zero, Size).Contains(ref predictedLocation))
|
||||
{
|
||||
var result = NavigationRaycast(direction, predictedLocation, visited);
|
||||
if (result != null)
|
||||
return result;
|
||||
{
|
||||
rightMostLocation = predictedLocation;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Parent?.NavigationWrap(direction, PointToParent(ref location), visited);
|
||||
rightMostLocation = location;
|
||||
return Parent?.NavigationWrap(direction, PointToParent(ref location), visited, out rightMostLocation);
|
||||
}
|
||||
|
||||
private static bool CanGetAutoFocus(Control c)
|
||||
@@ -613,6 +625,10 @@ namespace FlaxEngine.GUI
|
||||
uiDir1 = new Float2(1, 0);
|
||||
uiDir2 = new Float2(0, 1);
|
||||
break;
|
||||
case NavDirection.Previous:
|
||||
uiDir1 = new Float2(-1, 0);
|
||||
uiDir2 = new Float2(0, -1);
|
||||
break;
|
||||
}
|
||||
Control result = null;
|
||||
var minDistance = float.MaxValue;
|
||||
|
||||
@@ -634,6 +634,7 @@ namespace FlaxEngine.GUI
|
||||
case NavDirection.Left: return new Float2(0, size.Y * 0.5f);
|
||||
case NavDirection.Right: return new Float2(size.X, size.Y * 0.5f);
|
||||
case NavDirection.Next: return Float2.Zero;
|
||||
case NavDirection.Previous: return size;
|
||||
default: return size * 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,5 +202,10 @@ namespace FlaxEngine.GUI
|
||||
/// The next item (right with layout wrapping).
|
||||
/// </summary>
|
||||
Next,
|
||||
|
||||
/// <summary>
|
||||
/// The previous item (left with layout wrapping).
|
||||
/// </summary>
|
||||
Previous,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,6 +366,7 @@ void TextRender::Draw(RenderContext& renderContext)
|
||||
DrawCall drawCall;
|
||||
drawCall.World = world;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = _sphere.Radius;
|
||||
drawCall.Surface.GeometrySize = _localBox.GetSize();
|
||||
drawCall.Surface.PrevWorld = _drawState.PrevWorld;
|
||||
drawCall.Surface.Lightmap = nullptr;
|
||||
|
||||
@@ -40,11 +40,11 @@ ShaderGraphValue::ShaderGraphValue(const Variant& v)
|
||||
break;
|
||||
case VariantType::Float:
|
||||
Type = VariantType::Types::Float;
|
||||
Value = String::Format(TEXT("{}"), v.AsFloat);
|
||||
Value = String::Format(TEXT("{:.8f}"), v.AsFloat);
|
||||
break;
|
||||
case VariantType::Double:
|
||||
Type = VariantType::Types::Float;
|
||||
Value = String::Format(TEXT("{}"), (float)v.AsDouble);
|
||||
Value = String::Format(TEXT("{:.8f}"), (float)v.AsDouble);
|
||||
break;
|
||||
case VariantType::Float2:
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#ifdef NDEBUG
|
||||
|
||||
// From http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/
|
||||
// From https://web.archive.org/web/20210117002833/http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/
|
||||
# define dtAssert(x) do { (void)sizeof(x); } while((void)(__LINE__==-1),false)
|
||||
|
||||
#else
|
||||
|
||||
@@ -112,7 +112,7 @@ bool dtIntersectSegmentPoly2D(const float* p0, const float* p1,
|
||||
float& tmin, float& tmax,
|
||||
int& segMin, int& segMax)
|
||||
{
|
||||
static const float EPS = 0.00000001f;
|
||||
static const float EPS = 0.000001f;
|
||||
|
||||
tmin = 0;
|
||||
tmax = 1;
|
||||
|
||||
@@ -37,7 +37,6 @@ feature to find minor members.
|
||||
|
||||
/// Used to ignore a function parameter. VS complains about unused parameters
|
||||
/// and this silences the warning.
|
||||
/// @param [in] _ Unused parameter
|
||||
template<class T> void dtIgnoreUnused(const T&) { }
|
||||
|
||||
/// Swaps the values of the two parameters.
|
||||
@@ -319,7 +318,7 @@ inline float dtVdot2D(const float* u, const float* v)
|
||||
/// Derives the xz-plane 2D perp product of the two vectors. (uz*vx - ux*vz)
|
||||
/// @param[in] u The LHV vector [(x, y, z)]
|
||||
/// @param[in] v The RHV vector [(x, y, z)]
|
||||
/// @return The dot product on the xz-plane.
|
||||
/// @return The perp dot product on the xz-plane.
|
||||
///
|
||||
/// The vectors are projected onto the xz-plane, so the y-values are ignored.
|
||||
inline float dtVperp2D(const float* u, const float* v)
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <string.h>
|
||||
#include <float.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -66,7 +66,7 @@ enum CrowdAgentState
|
||||
{
|
||||
DT_CROWDAGENT_STATE_INVALID, ///< The agent is not in a valid state.
|
||||
DT_CROWDAGENT_STATE_WALKING, ///< The agent is traversing a normal navigation mesh polygon.
|
||||
DT_CROWDAGENT_STATE_OFFMESH, ///< The agent is traversing an off-mesh connection.
|
||||
DT_CROWDAGENT_STATE_OFFMESH ///< The agent is traversing an off-mesh connection.
|
||||
};
|
||||
|
||||
/// Configuration parameters for a crowd agent.
|
||||
@@ -108,7 +108,7 @@ enum MoveRequestState
|
||||
DT_CROWDAGENT_TARGET_REQUESTING,
|
||||
DT_CROWDAGENT_TARGET_WAITING_FOR_QUEUE,
|
||||
DT_CROWDAGENT_TARGET_WAITING_FOR_PATH,
|
||||
DT_CROWDAGENT_TARGET_VELOCITY,
|
||||
DT_CROWDAGENT_TARGET_VELOCITY
|
||||
};
|
||||
|
||||
/// Represents an agent managed by a #dtCrowd object.
|
||||
@@ -188,7 +188,7 @@ enum UpdateFlags
|
||||
DT_CROWD_OBSTACLE_AVOIDANCE = 2,
|
||||
DT_CROWD_SEPARATION = 4,
|
||||
DT_CROWD_OPTIMIZE_VIS = 8, ///< Use #dtPathCorridor::optimizePathVisibility() to optimize the agent path.
|
||||
DT_CROWD_OPTIMIZE_TOPO = 16, ///< Use dtPathCorridor::optimizePathTopology() to optimize the agent path.
|
||||
DT_CROWD_OPTIMIZE_TOPO = 16 ///< Use dtPathCorridor::optimizePathTopology() to optimize the agent path.
|
||||
};
|
||||
|
||||
struct dtCrowdAgentDebugInfo
|
||||
|
||||
@@ -433,8 +433,8 @@ void dtNavMesh::connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side)
|
||||
float tmax = (neia[k*2+1]-va[2]) / (vb[2]-va[2]);
|
||||
if (tmin > tmax)
|
||||
dtSwap(tmin,tmax);
|
||||
link->bmin = (unsigned char)(dtClamp(tmin, 0.0f, 1.0f)*255.0f);
|
||||
link->bmax = (unsigned char)(dtClamp(tmax, 0.0f, 1.0f)*255.0f);
|
||||
link->bmin = (unsigned char)roundf(dtClamp(tmin, 0.0f, 1.0f)*255.0f);
|
||||
link->bmax = (unsigned char)roundf(dtClamp(tmax, 0.0f, 1.0f)*255.0f);
|
||||
}
|
||||
else if (dir == 2 || dir == 6)
|
||||
{
|
||||
@@ -442,8 +442,8 @@ void dtNavMesh::connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side)
|
||||
float tmax = (neia[k*2+1]-va[0]) / (vb[0]-va[0]);
|
||||
if (tmin > tmax)
|
||||
dtSwap(tmin,tmax);
|
||||
link->bmin = (unsigned char)(dtClamp(tmin, 0.0f, 1.0f)*255.0f);
|
||||
link->bmax = (unsigned char)(dtClamp(tmax, 0.0f, 1.0f)*255.0f);
|
||||
link->bmin = (unsigned char)roundf(dtClamp(tmin, 0.0f, 1.0f)*255.0f);
|
||||
link->bmax = (unsigned char)roundf(dtClamp(tmax, 0.0f, 1.0f)*255.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ static const int DT_MAX_AREAS = 64;
|
||||
enum dtTileFlags
|
||||
{
|
||||
/// The navigation mesh owns the tile memory and is responsible for freeing it.
|
||||
DT_TILE_FREE_DATA = 0x01,
|
||||
DT_TILE_FREE_DATA = 0x01
|
||||
};
|
||||
|
||||
/// Vertex flags returned by dtNavMeshQuery::findStraightPath.
|
||||
@@ -107,32 +107,32 @@ enum dtStraightPathFlags
|
||||
{
|
||||
DT_STRAIGHTPATH_START = 0x01, ///< The vertex is the start position in the path.
|
||||
DT_STRAIGHTPATH_END = 0x02, ///< The vertex is the end position in the path.
|
||||
DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04, ///< The vertex is the start of an off-mesh connection.
|
||||
DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04 ///< The vertex is the start of an off-mesh connection.
|
||||
};
|
||||
|
||||
/// Options for dtNavMeshQuery::findStraightPath.
|
||||
enum dtStraightPathOptions
|
||||
{
|
||||
DT_STRAIGHTPATH_AREA_CROSSINGS = 0x01, ///< Add a vertex at every polygon edge crossing where area changes.
|
||||
DT_STRAIGHTPATH_ALL_CROSSINGS = 0x02, ///< Add a vertex at every polygon edge crossing.
|
||||
DT_STRAIGHTPATH_ALL_CROSSINGS = 0x02 ///< Add a vertex at every polygon edge crossing.
|
||||
};
|
||||
|
||||
|
||||
/// Options for dtNavMeshQuery::initSlicedFindPath and updateSlicedFindPath
|
||||
enum dtFindPathOptions
|
||||
{
|
||||
DT_FINDPATH_ANY_ANGLE = 0x02, ///< use raycasts during pathfind to "shortcut" (raycast still consider costs)
|
||||
DT_FINDPATH_ANY_ANGLE = 0x02 ///< use raycasts during pathfind to "shortcut" (raycast still consider costs)
|
||||
};
|
||||
|
||||
/// Options for dtNavMeshQuery::raycast
|
||||
enum dtRaycastOptions
|
||||
{
|
||||
DT_RAYCAST_USE_COSTS = 0x01, ///< Raycast should calculate movement cost along the ray and fill RaycastHit::cost
|
||||
DT_RAYCAST_USE_COSTS = 0x01 ///< Raycast should calculate movement cost along the ray and fill RaycastHit::cost
|
||||
};
|
||||
|
||||
enum dtDetailTriEdgeFlags
|
||||
{
|
||||
DT_DETAIL_EDGE_BOUNDARY = 0x01, ///< Detail triangle edge is part of the poly boundary
|
||||
DT_DETAIL_EDGE_BOUNDARY = 0x01 ///< Detail triangle edge is part of the poly boundary
|
||||
};
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ enum dtPolyTypes
|
||||
/// The polygon is a standard convex polygon that is part of the surface of the mesh.
|
||||
DT_POLYTYPE_GROUND = 0,
|
||||
/// The polygon is an off-mesh connection consisting of two vertices.
|
||||
DT_POLYTYPE_OFFMESH_CONNECTION = 1,
|
||||
DT_POLYTYPE_OFFMESH_CONNECTION = 1
|
||||
};
|
||||
|
||||
|
||||
@@ -285,7 +285,7 @@ struct dtMeshTile
|
||||
unsigned int linksFreeList; ///< Index to the next free link.
|
||||
dtMeshHeader* header; ///< The tile header.
|
||||
dtPoly* polys; ///< The tile polygons. [Size: dtMeshHeader::polyCount]
|
||||
float* verts; ///< The tile vertices. [Size: dtMeshHeader::vertCount]
|
||||
float* verts; ///< The tile vertices. [(x, y, z) * dtMeshHeader::vertCount]
|
||||
dtLink* links; ///< The tile links. [Size: dtMeshHeader::maxLinkCount]
|
||||
dtPolyDetail* detailMeshes; ///< The tile's detail sub-meshes. [Size: dtMeshHeader::detailMeshCount]
|
||||
|
||||
@@ -312,8 +312,8 @@ private:
|
||||
};
|
||||
|
||||
/// Get flags for edge in detail triangle.
|
||||
/// @param triFlags[in] The flags for the triangle (last component of detail vertices above).
|
||||
/// @param edgeIndex[in] The index of the first vertex of the edge. For instance, if 0,
|
||||
/// @param[in] triFlags The flags for the triangle (last component of detail vertices above).
|
||||
/// @param[in] edgeIndex The index of the first vertex of the edge. For instance, if 0,
|
||||
/// returns flags for edge AB.
|
||||
inline int dtGetDetailTriEdgeFlags(unsigned char triFlags, int edgeIndex)
|
||||
{
|
||||
|
||||
@@ -117,6 +117,11 @@ void dtFreeNavMeshQuery(dtNavMeshQuery* navmesh)
|
||||
dtFree(navmesh);
|
||||
}
|
||||
|
||||
dtPolyQuery::~dtPolyQuery()
|
||||
{
|
||||
// Defined out of line to fix the weak v-tables warning
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// @class dtNavMeshQuery
|
||||
@@ -301,11 +306,7 @@ dtStatus dtNavMeshQuery::findRandomPoint(const dtQueryFilter* filter, float (*fr
|
||||
float pt[3];
|
||||
dtRandomPointInConvexPoly(verts, poly->vertCount, areas, s, t, pt);
|
||||
|
||||
float h = 0.0f;
|
||||
dtStatus status = getPolyHeight(polyRef, pt, &h);
|
||||
if (dtStatusFailed(status))
|
||||
return status;
|
||||
pt[1] = h;
|
||||
closestPointOnPoly(polyRef, pt, pt, NULL);
|
||||
|
||||
dtVcopy(randomPt, pt);
|
||||
*randomRef = polyRef;
|
||||
@@ -481,26 +482,25 @@ dtStatus dtNavMeshQuery::findRandomPointAroundCircle(dtPolyRef startRef, const f
|
||||
v = &randomTile->verts[randomPoly->verts[j]*3];
|
||||
dtVcopy(&verts[j*3],v);
|
||||
}
|
||||
|
||||
|
||||
float pt[3];
|
||||
int checksLimit = 100;
|
||||
do
|
||||
{
|
||||
const float s = frand();
|
||||
const float t = frand();
|
||||
dtRandomPointInConvexPoly(verts, randomPoly->vertCount, areas, s, t, pt);
|
||||
const float t = frand();
|
||||
dtRandomPointInConvexPoly(verts, randomPoly->vertCount, areas, s, t, pt);
|
||||
}
|
||||
while (dtDistancePtPtSqr2D(centerPos, pt) > radiusSqr);
|
||||
|
||||
float h = 0.0f;
|
||||
dtStatus stat = getPolyHeight(randomPolyRef, pt, &h);
|
||||
if (dtStatusFailed(status))
|
||||
return stat;
|
||||
pt[1] = h;
|
||||
while (dtDistancePtPtSqr2D(centerPos, pt) > radiusSqr && checksLimit-- > 0);
|
||||
if (checksLimit <= 0)
|
||||
return DT_FAILURE;
|
||||
|
||||
closestPointOnPoly(randomPolyRef, pt, pt, NULL);
|
||||
|
||||
dtVcopy(randomPt, pt);
|
||||
*randomRef = randomPolyRef;
|
||||
|
||||
return DT_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -641,6 +641,8 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~dtFindNearestPolyQuery();
|
||||
|
||||
dtPolyRef nearestRef() const { return m_nearestRef; }
|
||||
const float* nearestPoint() const { return m_nearestPoint; }
|
||||
bool isOverPoly() const { return m_overPoly; }
|
||||
@@ -683,6 +685,11 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
dtFindNearestPolyQuery::~dtFindNearestPolyQuery()
|
||||
{
|
||||
// Defined out of line to fix the weak v-tables warning
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// @note If the search box does not intersect any polygons the search will
|
||||
@@ -858,6 +865,8 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~dtCollectPolysQuery();
|
||||
|
||||
int numCollected() const { return m_numCollected; }
|
||||
bool overflowed() const { return m_overflow; }
|
||||
|
||||
@@ -879,6 +888,11 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
dtCollectPolysQuery::~dtCollectPolysQuery()
|
||||
{
|
||||
// Defined out of line to fix the weak v-tables warning
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// If no polygons are found, the function will return #DT_SUCCESS with a
|
||||
|
||||
@@ -153,7 +153,7 @@ struct dtRaycastHit
|
||||
class dtPolyQuery
|
||||
{
|
||||
public:
|
||||
virtual ~dtPolyQuery() { }
|
||||
virtual ~dtPolyQuery();
|
||||
|
||||
/// Called for each batch of unique polygons touched by the search area in dtNavMeshQuery::queryPolygons.
|
||||
/// This can be called multiple times for a single query.
|
||||
@@ -176,7 +176,7 @@ public:
|
||||
dtStatus init(const dtNavMesh* nav, const int maxNodes);
|
||||
|
||||
/// @name Standard Pathfinding Functions
|
||||
// /@{
|
||||
/// @{
|
||||
|
||||
/// Finds a path from the start polygon to the end polygon.
|
||||
/// @param[in] startRef The refrence id of the start polygon.
|
||||
@@ -397,9 +397,9 @@ public:
|
||||
/// @param[in] startPos A position within the start polygon representing
|
||||
/// the start of the ray. [(x, y, z)]
|
||||
/// @param[in] endPos The position to cast the ray toward. [(x, y, z)]
|
||||
/// @param[in] filter The polygon filter to apply to the query.
|
||||
/// @param[out] t The hit parameter. (FLT_MAX if no wall hit.)
|
||||
/// @param[out] hitNormal The normal of the nearest wall hit. [(x, y, z)]
|
||||
/// @param[in] filter The polygon filter to apply to the query.
|
||||
/// @param[out] path The reference ids of the visited polygons. [opt]
|
||||
/// @param[out] pathCount The number of visited polygons. [opt]
|
||||
/// @param[in] maxPath The maximum number of polygons the @p path array can hold.
|
||||
@@ -415,7 +415,7 @@ public:
|
||||
/// the start of the ray. [(x, y, z)]
|
||||
/// @param[in] endPos The position to cast the ray toward. [(x, y, z)]
|
||||
/// @param[in] filter The polygon filter to apply to the query.
|
||||
/// @param[in] flags govern how the raycast behaves. See dtRaycastOptions
|
||||
/// @param[in] options govern how the raycast behaves. See dtRaycastOptions
|
||||
/// @param[out] hit Pointer to a raycast hit structure which will be filled by the results.
|
||||
/// @param[in] prevRef parent of start ref. Used during for cost calculation [opt]
|
||||
/// @returns The status flags for the query.
|
||||
@@ -466,6 +466,7 @@ public:
|
||||
/// The location is not exactly constrained by the circle, but it limits the visited polygons.
|
||||
/// @param[in] startRef The reference id of the polygon where the search starts.
|
||||
/// @param[in] centerPos The center of the search circle. [(x, y, z)]
|
||||
/// @param[in] maxRadius The radius of the search circle. [Units: wu]
|
||||
/// @param[in] filter The polygon filter to apply to the query.
|
||||
/// @param[in] frand Function returning a random number [0..1).
|
||||
/// @param[out] randomRef The reference id of the random location.
|
||||
|
||||
@@ -25,7 +25,7 @@ enum dtNodeFlags
|
||||
{
|
||||
DT_NODE_OPEN = 0x01,
|
||||
DT_NODE_CLOSED = 0x02,
|
||||
DT_NODE_PARENT_DETACHED = 0x04, // parent of the node is not adjacent. Found using raycast.
|
||||
DT_NODE_PARENT_DETACHED = 0x04 // parent of the node is not adjacent. Found using raycast.
|
||||
};
|
||||
|
||||
typedef unsigned short dtNodeIndex;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user