51 Commits

Author SHA1 Message Date
cd2e7140af _windows subwindow popup fix
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2024-12-27 12:58:04 +02:00
d5b64aece4 _sdl binary 2024-12-27 12:22:50 +02:00
146cc13bad Update SDL3 2024-12-27 12:22:45 +02:00
865b430ab0 _sdl3 binary 2024-12-27 00:19:23 +02:00
a5ad7a4398 Update SDL3 2024-12-27 00:19:17 +02:00
89d1cc4270 _borderless maximize workarounds WIP 2024-12-26 22:12:02 +02:00
bd81e3e89e Fix workaround for maximizing Editor window 2024-12-25 19:45:17 +02:00
37acdc29ff _sdl3 binary 2024-12-25 19:44:25 +02:00
ccdc7a5e1d Update SDL3 2024-12-25 19:44:19 +02:00
fe313773d1 Fix casting error in CPU profiler tab
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
2024-12-19 20:09:43 +02:00
34346e4111 Force cursor to center of Game Window when tab handle is clicked 2024-12-19 20:09:43 +02:00
7cbe44c4e5 _update sdl 2024-12-19 20:09:43 +02:00
846f44b882 _sdl binary 2024-12-19 20:09:42 +02:00
68764580f2 Update SDL 2024-12-19 20:09:42 +02:00
Chandler Cox
cdf0e24c12 Fix rotation using SDL 2024-12-19 20:09:42 +02:00
ac7087c4ce Update SDL3 binaries 2024-12-19 20:09:41 +02:00
56e6e53d0c Update SDL to 3.1.3 preview 2024-12-19 20:09:41 +02:00
25b6605027 _window positioning that works on windows 2024-12-19 20:09:41 +02:00
c97f6f3b7e _lfsconfig 2024-12-19 20:09:40 +02:00
bc33d1a0f5 _noprog? 2024-12-19 20:09:40 +02:00
5e950833ff _works 0,0 primary screen, returned positions correct but visually wrong 2024-12-19 20:09:40 +02:00
9a04cee71f _works 2024-12-19 20:09:39 +02:00
b79c9402fd _wip parent-child positioning fixes 2024-12-19 20:09:39 +02:00
b0aed96d18 Fix Linux compilation without SDL 2024-12-19 20:09:39 +02:00
c003506906 Fix compilation 2024-12-19 20:09:38 +02:00
473dc4a1a0 Update SDL3 2024-12-19 20:09:38 +02:00
8d97e21b28 Fix compilation issues 2024-12-19 20:09:38 +02:00
ce932b1739 Fix windows not being hidden initially 2024-12-19 20:09:37 +02:00
506ad85cad Fix parent window position handling with popup/tooltip windows 2024-12-19 20:09:37 +02:00
e86ccefd3c Fix compilation errors in other platforms 2024-12-19 20:09:37 +02:00
71147cd4e9 Fix CI for Linux 2024-12-19 20:09:36 +02:00
d6fe1f0519 Prevent building with SDL in unsupported platforms 2024-12-19 20:09:36 +02:00
ed3d1ce366 Fallback to X11 message box implementation when SDL fails 2024-12-19 20:09:36 +02:00
37177edeaa Fix popup and context menus not working on Wayland 2024-12-19 20:09:35 +02:00
7981483a5b Hide warnings for unsupported SDL operations on Wayland 2024-12-19 20:09:35 +02:00
c3ca359b4b Log a warning for not implemented Wayland functionality 2024-12-19 20:09:35 +02:00
99cf7292aa Fix compilation in Linux 2024-12-19 20:09:34 +02:00
4c6f39d489 Enable warning sound in question dialogs 2024-12-19 20:09:34 +02:00
dcfc265433 Enable modern Windows dialog boxes 2024-12-19 20:09:34 +02:00
4a7f6c34f3 Implement relative mouse mode (raw input) for SDL platform 2024-12-19 20:09:33 +02:00
ba248a61bd Add flag for Window types 2024-12-19 20:09:33 +02:00
eacd23bdbb Enable native windowing system settings with SDL platform 2024-12-19 20:09:33 +02:00
62df728452 Add command-line switches to force X11 and Wayland SDL drivers 2024-12-19 20:09:32 +02:00
fe0d97aad1 Implement SDL platform, windowing and input handling 2024-12-19 20:09:32 +02:00
7f7d839f23 Refactor application window class name 2024-12-19 20:09:32 +02:00
c445bfd5d4 Move Window related enums to separate header file 2024-12-19 20:09:31 +02:00
62843476b7 Refactor Windows drag and drop implementation 2024-12-19 20:09:31 +02:00
7595c572d7 Refactor ScreenUtilities 2024-12-19 20:09:31 +02:00
13ae091273 Add more helper methods for managing Git repos 2024-12-19 20:09:31 +02:00
a9dccd2949 Fix centered window location on X11 2024-12-19 20:09:30 +02:00
f8dd3f23c6 Fix initial position of Tooltips 2024-12-19 20:09:30 +02:00
468 changed files with 7247 additions and 19918 deletions

View File

@@ -1,13 +1,12 @@
name: Continuous Deployment
on:
schedule:
- cron: '15 6 * * *'
- cron: '15 4 * * *'
workflow_dispatch:
env:
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: false
GIT_LFS_PULL_OPTIONS: '-c lfs.concurrenttransfers=1 -c lfs.transfer.maxretries=2 -c http.version="HTTP/1.1" -c lfs.activitytimeout=60'
jobs:
@@ -21,7 +20,7 @@ jobs:
- name: Checkout LFS
run: |
git lfs version
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
git lfs pull
- name: Setup Vulkan
uses: ./.github/actions/vulkan
- name: Setup .NET
@@ -36,12 +35,12 @@ jobs:
run: |
.\PackageEditor.bat -arch=x64 -platform=Windows -deployOutput=Output
- name: Upload
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: Windows-Editor
path: Output/Editor.zip
- name: Upload
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: Windows-EditorDebugSymbols
path: Output/EditorDebugSymbols.zip
@@ -54,7 +53,7 @@ jobs:
- name: Checkout LFS
run: |
git lfs version
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
git lfs pull
- name: Setup Vulkan
uses: ./.github/actions/vulkan
- name: Setup .NET
@@ -69,7 +68,7 @@ jobs:
run: |
.\PackagePlatforms.bat -arch=x64 -platform=Windows -deployOutput=Output
- name: Upload
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: Windows-Game
path: Output/Windows.zip
@@ -84,7 +83,7 @@ jobs:
- name: Checkout LFS
run: |
git lfs version
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
git lfs pull
- name: Install dependencies
run: |
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
@@ -102,7 +101,7 @@ jobs:
run: |
./PackageEditor.sh -arch=x64 -platform=Linux -deployOutput=Output
- name: Upload
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: Linux-Editor
path: Output/FlaxEditorLinux.zip
@@ -115,7 +114,7 @@ jobs:
- name: Checkout LFS
run: |
git lfs version
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
git lfs pull
- name: Install dependencies
run: |
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
@@ -133,7 +132,7 @@ jobs:
run: |
./PackagePlatforms.sh -arch=x64 -platform=Linux -deployOutput=Output
- name: Upload
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: Linux-Game
path: Output/Linux.zip
@@ -148,7 +147,7 @@ jobs:
- name: Checkout LFS
run: |
git lfs version
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
git lfs pull
- name: Setup Vulkan
uses: ./.github/actions/vulkan
- name: Setup .NET
@@ -163,7 +162,7 @@ jobs:
run: |
./PackageEditor.command -arch=ARM64 -platform=Mac -deployOutput=Output
- name: Upload
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: Mac-Editor
path: Output/FlaxEditorMac.zip
@@ -176,7 +175,7 @@ jobs:
- name: Checkout LFS
run: |
git lfs version
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
git lfs pull
- name: Setup Vulkan
uses: ./.github/actions/vulkan
- name: Setup .NET
@@ -191,7 +190,7 @@ jobs:
run: |
./PackagePlatforms.command -arch=ARM64 -platform=Mac -deployOutput=Output
- name: Upload
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: Mac-Game
path: Output/Mac.zip

View File

@@ -1,4 +1,4 @@
# Redirect to our own Git LFS server
[lfs]
#url="https://gitlab.flaxengine.com/flax/flaxengine.git/info/lfs"
locksverify = false
locksverify = false

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,25 +0,0 @@
%copyright%using System;
using System.Collections.Generic;
using FlaxEngine;
namespace %namespace%;
/// <summary>
/// %class% GamePlugin.
/// </summary>
public class %class% : GamePlugin
{
/// <inheritdoc/>
public override void Initialize()
{
base.Initialize();
}
/// <inheritdoc/>
public override void Deinitialize()
{
base.Deinitialize();
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -15,7 +15,7 @@ if errorlevel 1 goto BuildToolFailed
:: Build bindings for all editor configurations
echo Building C# bindings...
Binaries\Tools\Flax.Build.exe -build -BuildBindingsOnly -arch=x64 -platform=Windows --buildTargets=FlaxEditor,FlaxGame
Binaries\Tools\Flax.Build.exe -build -BuildBindingsOnly -arch=x64 -platform=Windows --buildTargets=FlaxEditor
popd
echo Done!

View File

@@ -14,4 +14,4 @@ bash ./Development/Scripts/Mac/CallBuildTool.sh --genproject "$@"
# Build bindings for all editor configurations
echo Building C# bindings...
# TODO: Detect the correct architecture here
Binaries/Tools/Flax.Build -build -BuildBindingsOnly -arch=ARM64 -platform=Mac --buildTargets=FlaxEditor,FlaxGame
Binaries/Tools/Flax.Build -build -BuildBindingsOnly -arch=ARM64 -platform=Mac --buildTargets=FlaxEditor

View File

@@ -14,4 +14,4 @@ bash ./Development/Scripts/Linux/CallBuildTool.sh --genproject "$@"
# Build bindings for all editor configurations
echo Building C# bindings...
# TODO: Detect the correct architecture here
Binaries/Tools/Flax.Build -build -BuildBindingsOnly -arch=x64 -platform=Linux --buildTargets=FlaxEditor,FlaxGame
Binaries/Tools/Flax.Build -build -BuildBindingsOnly -arch=x64 -platform=Linux --buildTargets=FlaxEditor

View File

@@ -31,7 +31,7 @@ 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 8 or 9 SDK for **Windows x64** (via Visual Studio Installer or [from web](https://dotnet.microsoft.com/en-us/download/dotnet/8.0))
* Install .NET 8 SDK for **Windows x64** (via Visual Studio Installer or [from web](https://dotnet.microsoft.com/en-us/download/dotnet/8.0))
* Install Git with LFS
* Clone repo (with LFS)
* Run **GenerateProjectFiles.bat**
@@ -44,9 +44,8 @@ Follow the instructions below to compile and run the engine from source.
## Linux
* Install Visual Studio Code
* Install .NET 8 or 9 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0))
* Install .NET 8 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0))
* Ubuntu: `sudo apt install dotnet-sdk-8.0`
* Arch: `sudo pacman -S dotnet-sdk-8.0 dotnet-runtime-8.0 dotnet-targeting-pack-8.0 dotnet-host`
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
* Ubuntu: `sudo apt install vulkan-sdk`
* Arch: `sudo pacman -S spirv-tools vulkan-headers vulkan-tools vulkan-validation-layers`
@@ -68,12 +67,12 @@ Follow the instructions below to compile and run the engine from source.
## Mac
* Install XCode
* Install .NET 8 or 9 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0))
* Install .NET 8 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0))
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
* Clone repo (with LFS)
* Run `GenerateProjectFiles.command`
* Open workspace with XCode or Visual Studio Code
* Build and run (configuration `Editor.Mac.Development`)
* Build and run (configuration `Editor.Mac.Development`)
#### Troubleshooting

View File

@@ -750,8 +750,7 @@ namespace FlaxEditor.Content
// Draw short name
Render2D.PushClip(ref textRect);
var scale = 0.95f * view.ViewScale;
Render2D.DrawText(style.FontMedium, ShowFileExtension || view.ShowFileExtensions ? FileName : ShortName, textRect, style.Foreground, nameAlignment, TextAlignment.Center, TextWrapping.WrapWords, 1f, scale);
Render2D.DrawText(style.FontMedium, ShowFileExtension || view.ShowFileExtensions ? FileName : ShortName, textRect, style.Foreground, nameAlignment, TextAlignment.Center, TextWrapping.WrapWords, 1f, 0.95f);
Render2D.PopClip();
if (IsBeingCut)

View File

@@ -20,7 +20,7 @@ namespace FlaxEditor.Content
}
/// <inheritdoc />
public override string TypeDescription => Path.EndsWith(".h") || Path.EndsWith(".hpp") ? "C++ Header File" : "C++ Source Code";
public override string TypeDescription => Path.EndsWith(".h") ? "C++ Header File" : "C++ Source Code";
/// <inheritdoc />
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.CPPScript128;

View File

@@ -106,23 +106,6 @@ namespace FlaxEditor.Content
}
}
/// <summary>
/// Context proxy object for C# GamePlugin files.
/// </summary>
/// <seealso cref="FlaxEditor.Content.CSharpProxy" />
[ContentContextMenu("New/C#/C# GamePlugin")]
public class CSharpGamePluginProxy : CSharpProxy
{
/// <inheritdoc />
public override string Name => "C# GamePlugin";
/// <inheritdoc />
protected override void GetTemplatePath(out string path)
{
path = StringUtils.CombinePaths(Globals.EngineContentFolder, "Editor/Scripting/GamePluginTemplate.cs");
}
}
/// <summary>
/// Context proxy object for empty C# files.
/// </summary>

View File

@@ -1,11 +1,9 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using System.Linq;
using FlaxEditor.Content.Create;
using FlaxEditor.CustomEditors;
using FlaxEditor.CustomEditors.Editors;
using FlaxEditor.Scripting;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
@@ -86,67 +84,18 @@ namespace FlaxEditor.Content
if (_element != null)
{
_element.CustomControl.CheckValid += OnCheckValidJsonAssetType;
// Define the rule for the types that can be used to create a json data asset
_element.CustomControl.CheckValid += type =>
type.Type != null &&
type.IsClass &&
type.Type.IsVisible &&
!type.IsAbstract &&
!type.IsGenericType &&
type.Type.GetConstructor(Type.EmptyTypes) != null &&
!typeof(FlaxEngine.GUI.Control).IsAssignableFrom(type.Type) &&
!typeof(FlaxEngine.Object).IsAssignableFrom(type.Type);
}
}
private static Type[] BlacklistedClasses =
[
typeof(System.Attribute),
typeof(FlaxEngine.Object),
typeof(FlaxEngine.GUI.Control),
];
private static Type[] BlacklistedStructs =
[
typeof(Float2),
typeof(Float3),
typeof(Float4),
typeof(Double2),
typeof(Double3),
typeof(Double4),
typeof(Vector2),
typeof(Vector3),
typeof(Vector4),
typeof(Half2),
typeof(Half3),
typeof(Half4),
typeof(Int2),
typeof(Int3),
typeof(Int4),
typeof(Transform),
typeof(Quaternion),
typeof(BoundingBox),
typeof(BoundingSphere),
typeof(BoundingFrustum),
typeof(Ray),
typeof(Plane),
typeof(Matrix),
typeof(Color),
typeof(Color32),
typeof(FloatR11G11B10),
typeof(FloatR10G10B10A2),
typeof(FlaxEngine.Half),
];
private static bool OnCheckValidJsonAssetType(ScriptType type)
{
// Define the rule for the types that can be used to create a json data asset
var mType = type.Type;
if (mType == null ||
type.IsAbstract ||
type.IsStatic ||
type.IsGenericType ||
!mType.IsVisible)
return false;
if (type.IsClass)
return mType.GetConstructor(Type.EmptyTypes) != null && BlacklistedClasses.FirstOrDefault(x => x.IsAssignableFrom(mType)) == null;
if (type.IsStructure)
return !type.IsPrimitive &&
!type.IsVoid &&
!BlacklistedStructs.Contains(mType);
return false;
}
}
}
@@ -226,7 +175,7 @@ namespace FlaxEditor.Content
{
_thumbnail = SpriteHandle.Invalid;
}
/// <summary>
/// Constructor with overriden thumbnail.
/// </summary>
@@ -247,7 +196,7 @@ namespace FlaxEditor.Content
{
Editor.SaveJsonAsset(outputPath, new T());
}
/// <inheritdoc />
public override AssetItem ConstructItem(string path, string typeName, ref Guid id)
{

View File

@@ -496,7 +496,7 @@ namespace FlaxEditor.Content.Thumbnails
// Prepare requests
bool isAnyReady = false;
int checks = Mathf.Min(10, _requests.Count);
for (int i = 0; i < checks && i < _requests.Count; i++)
for (int i = 0; i < checks; i++)
{
var request = _requests[i];
try

View File

@@ -671,14 +671,11 @@ bool GameCookerImpl::Build()
MCore::Thread::Attach();
// Build Started
if (!EnumHasAnyFlags(data.Options, BuildOptions::NoCook))
{
CallEvent(GameCooker::EventType::BuildStarted);
data.Tools->OnBuildStarted(data);
for (int32 stepIndex = 0; stepIndex < Steps.Count(); stepIndex++)
Steps[stepIndex]->OnBuildStarted(data);
data.InitProgress(Steps.Count());
}
CallEvent(GameCooker::EventType::BuildStarted);
data.Tools->OnBuildStarted(data);
for (int32 stepIndex = 0; stepIndex < Steps.Count(); stepIndex++)
Steps[stepIndex]->OnBuildStarted(data);
data.InitProgress(Steps.Count());
// Execute all steps in a sequence
bool failed = false;
@@ -744,13 +741,10 @@ bool GameCookerImpl::Build()
}
IsRunning = false;
CancelFlag = 0;
if (!EnumHasAnyFlags(data.Options, BuildOptions::NoCook))
{
for (int32 stepIndex = 0; stepIndex < Steps.Count(); stepIndex++)
Steps[stepIndex]->OnBuildEnded(data, failed);
data.Tools->OnBuildEnded(data, failed);
CallEvent(failed ? GameCooker::EventType::BuildFailed : GameCooker::EventType::BuildDone);
}
for (int32 stepIndex = 0; stepIndex < Steps.Count(); stepIndex++)
Steps[stepIndex]->OnBuildEnded(data, failed);
data.Tools->OnBuildEnded(data, failed);
CallEvent(failed ? GameCooker::EventType::BuildFailed : GameCooker::EventType::BuildDone);
Delete(Data);
Data = nullptr;

View File

@@ -364,33 +364,6 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
}
#endif
const bool distributionPackage = buildSettings->ForDistribution || data.Configuration == BuildConfiguration::Release;
if (platformSettings->BuildAAB)
{
// .aab
{
CreateProcessSettings procSettings;
procSettings.FileName = String::Format(TEXT("\"{0}\" {1}"), data.OriginalOutputPath / gradlew, distributionPackage ? TEXT(":app:bundle") : TEXT(":app:bundleDebug"));
procSettings.WorkingDirectory = data.OriginalOutputPath;
const int32 result = Platform::CreateProcess(procSettings);
if (result != 0)
{
data.Error(String::Format(TEXT("Failed to build Gradle project into .aab package (result code: {0}). See log for more info."), result));
return true;
}
}
// Copy result package
const String aab = data.OriginalOutputPath / (distributionPackage ? TEXT("app/build/outputs/bundle/release/app-release.aab") : TEXT("app/build/outputs/bundle/debug/app-debug.aab"));
const String outputAab = data.OriginalOutputPath / EditorUtilities::GetOutputName() + TEXT(".aab");
if (FileSystem::CopyFile(outputAab, aab))
{
LOG(Error, "Failed to copy .aab package from {0} to {1}", aab, outputAab);
return true;
}
LOG(Info, "Output Android AAB application package: {0} (size: {1} MB)", outputAab, FileSystem::GetFileSize(outputAab) / 1024 / 1024);
}
// .apk
{
CreateProcessSettings procSettings;
procSettings.FileName = String::Format(TEXT("\"{0}\" {1}"), data.OriginalOutputPath / gradlew, distributionPackage ? TEXT("assemble") : TEXT("assembleDebug"));
@@ -398,20 +371,20 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
const int32 result = Platform::CreateProcess(procSettings);
if (result != 0)
{
data.Error(String::Format(TEXT("Failed to build Gradle project into .apk package (result code: {0}). See log for more info."), result));
data.Error(String::Format(TEXT("Failed to build Gradle project into package (result code: {0}). See log for more info."), result));
return true;
}
}
// Copy result package
const String apk = data.OriginalOutputPath / (distributionPackage ? TEXT("app/build/outputs/apk/release/app-release-unsigned.apk") : TEXT("app/build/outputs/apk/debug/app-debug.apk"));
const String outputApk = data.OriginalOutputPath / EditorUtilities::GetOutputName() + TEXT(".apk");
if (FileSystem::CopyFile(outputApk, apk))
{
LOG(Error, "Failed to copy .apk package from {0} to {1}", apk, outputApk);
LOG(Error, "Failed to copy package from {0} to {1}", apk, outputApk);
return true;
}
LOG(Info, "Output Android APK application package: {0} (size: {1} MB)", outputApk, FileSystem::GetFileSize(outputApk) / 1024 / 1024);
LOG(Info, "Output Android application package: {0} (size: {1} MB)", outputApk, FileSystem::GetFileSize(outputApk) / 1024 / 1024);
return false;
}

View File

@@ -1277,8 +1277,6 @@ bool CookAssetsStep::Perform(CookingData& data)
assetStats.Count++;
assetStats.ContentSize += FileSystem::GetFileSize(cookedFilePath);
LOG(Info, "Cooked size of {0}: {1}KB", assetId, (FileSystem::GetFileSize(cookedFilePath) / (1024)));
if (packageBuilder.Add(data, i->Value, cookedFilePath))
return true;
}

View File

@@ -214,33 +214,6 @@ bool DeployDataStep::Perform(CookingData& data)
FileSystem::NormalizePath(srcDotnet);
LOG(Info, "Using .NET Runtime {} at {}", TEXT("Host"), srcDotnet);
// Get major Version
Array<String> pathParts;
srcDotnet.Split('/', pathParts);
String version;
for (int i = 0; i < pathParts.Count(); i++)
{
if (pathParts[i] == TEXT("runtimes"))
{
Array<String> versionParts;
pathParts[i - 1].Split('.', versionParts);
if (!versionParts.IsEmpty())
{
const String majorVersion = versionParts[0].TrimTrailing();
int32 versionNum;
StringUtils::Parse(*majorVersion, majorVersion.Length(), &versionNum);
if (Math::IsInRange(versionNum, GAME_BUILD_DOTNET_RUNTIME_MIN_VER, GAME_BUILD_DOTNET_RUNTIME_MAX_VER)) // Check for major part
version = majorVersion;
}
}
}
if (version.IsEmpty())
{
data.Error(TEXT("Failed to find supported .NET version for the current host platform."));
return true;
}
// Deploy runtime files
const Char* corlibPrivateName = TEXT("System.Private.CoreLib.dll");
const bool srcDotnetFromEngine = srcDotnet.Contains(TEXT("Source/Platforms"));
@@ -253,14 +226,14 @@ bool DeployDataStep::Perform(CookingData& data)
{
// AOT runtime files inside Engine Platform folder
packFolder /= TEXT("Dotnet");
dstDotnetLibs /= String::Format(TEXT("lib/net{}.0"), version);
srcDotnetLibs = packFolder / String::Format(TEXT("lib/net{}.0"), version);
dstDotnetLibs /= TEXT("lib/net8.0");
srcDotnetLibs = packFolder / TEXT("lib/net8.0");
}
else
{
// Runtime files inside Dotnet SDK folder but placed for AOT
dstDotnetLibs /= String::Format(TEXT("lib/net{}.0"), version);
srcDotnetLibs /= String::Format(TEXT("../lib/net{}.0"), version);
dstDotnetLibs /= TEXT("lib/net8.0");
srcDotnetLibs /= TEXT("../lib/net8.0");
}
}
else
@@ -268,14 +241,14 @@ bool DeployDataStep::Perform(CookingData& data)
if (srcDotnetFromEngine)
{
// Runtime files inside Engine Platform folder
dstDotnetLibs /= String::Format(TEXT("lib/net{}.0"), version);
srcDotnetLibs /= String::Format(TEXT("lib/net{}.0"), version);
dstDotnetLibs /= TEXT("lib/net8.0");
srcDotnetLibs /= TEXT("lib/net8.0");
}
else
{
// Runtime files inside Dotnet SDK folder
dstDotnetLibs /= TEXT("shared/Microsoft.NETCore.App");
srcDotnetLibs /= String::Format(TEXT("../lib/net{}.0"), version);
srcDotnetLibs /= TEXT("../lib/net8.0");
}
}
LOG(Info, "Copying .NET files from {} to {}", packFolder, dstDotnet);
@@ -300,7 +273,6 @@ bool DeployDataStep::Perform(CookingData& data)
DEPLOY_NATIVE_FILE("libmonosgen-2.0.so");
DEPLOY_NATIVE_FILE("libSystem.IO.Compression.Native.so");
DEPLOY_NATIVE_FILE("libSystem.Native.so");
DEPLOY_NATIVE_FILE("libSystem.Globalization.Native.so");
DEPLOY_NATIVE_FILE("libSystem.Security.Cryptography.Native.Android.so");
break;
case BuildPlatform::iOSARM64:
@@ -415,9 +387,9 @@ bool DeployDataStep::Perform(CookingData& data)
data.AddRootEngineAsset(TEXT("Engine/Textures/NormalTexture"));
data.AddRootEngineAsset(TEXT("Engine/Textures/BlackTexture"));
data.AddRootEngineAsset(TEXT("Engine/Textures/WhiteTexture"));
//data.AddRootEngineAsset(TEXT("Engine/Textures/DefaultLensStarburst"));
//data.AddRootEngineAsset(TEXT("Engine/Textures/DefaultLensColor"));
//data.AddRootEngineAsset(TEXT("Engine/Textures/DefaultLensDirt"));
data.AddRootEngineAsset(TEXT("Engine/Textures/DefaultLensStarburst"));
data.AddRootEngineAsset(TEXT("Engine/Textures/DefaultLensColor"));
data.AddRootEngineAsset(TEXT("Engine/Textures/DefaultLensDirt"));
data.AddRootEngineAsset(TEXT("Engine/Textures/Bokeh/Circle"));
data.AddRootEngineAsset(TEXT("Engine/Textures/Bokeh/Hexagon"));
data.AddRootEngineAsset(TEXT("Engine/Textures/Bokeh/Octagon"));

View File

@@ -883,7 +883,7 @@ namespace FlaxEditor.CustomEditors
/// </summary>
protected virtual void ClearToken()
{
ParentEditor?.ClearToken();
ParentEditor.ClearToken();
}
}
}

View File

@@ -195,15 +195,6 @@ namespace FlaxEditor.CustomEditors
Presenter.AfterLayout?.Invoke(layout);
}
/// <inheritdoc />
protected override void Deinitialize()
{
Editor = null;
_overrideEditor = null;
base.Deinitialize();
}
/// <inheritdoc />
protected override void OnModified()
{

View File

@@ -9,7 +9,6 @@ using FlaxEditor.CustomEditors.Elements;
using FlaxEditor.GUI;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.GUI.Tree;
using FlaxEditor.Modules;
using FlaxEditor.Scripting;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
@@ -68,16 +67,12 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Use default prefab instance as a reference for the editor
Values.SetReferenceValue(prefabInstance);
// Display prefab UI (when displaying object inside Prefab Window then display only nested prefabs)
var prefabId = prefab.ID;
Editor.GetPrefabNestedObject(ref prefabId, ref prefabObjectId, out var nestedPrefabId, out var nestedPrefabObjectId);
var nestedPrefab = FlaxEngine.Content.Load<Prefab>(nestedPrefabId);
var panel = layout.CustomContainer<UniformGridPanel>();
panel.CustomControl.Height = 20.0f;
panel.CustomControl.SlotsVertically = 1;
if (Presenter == Editor.Instance.Windows.PropertiesWin.Presenter || nestedPrefab)
if (Presenter == Editor.Instance.Windows.PropertiesWin.Presenter)
{
var targetPrefab = nestedPrefab ?? prefab;
// Add some UI
var panel = layout.CustomContainer<UniformGridPanel>();
panel.CustomControl.Height = 20.0f;
panel.CustomControl.SlotsVertically = 1;
panel.CustomControl.SlotsHorizontally = 3;
// Selecting actor prefab asset
@@ -85,21 +80,22 @@ namespace FlaxEditor.CustomEditors.Dedicated
selectPrefab.Button.Clicked += () =>
{
Editor.Instance.Windows.ContentWin.ClearItemsSearch();
Editor.Instance.Windows.ContentWin.Select(targetPrefab);
Editor.Instance.Windows.ContentWin.Select(prefab);
};
// Edit selected prefab asset
var editPrefab = panel.Button("Edit Prefab");
editPrefab.Button.Clicked += () => Editor.Instance.Windows.ContentWin.Open(Editor.Instance.ContentDatabase.FindAsset(targetPrefab.ID));
}
else
{
panel.CustomControl.SlotsHorizontally = 1;
}
editPrefab.Button.Clicked += () =>
{
Editor.Instance.Windows.ContentWin.ClearItemsSearch();
Editor.Instance.Windows.ContentWin.Select(prefab);
Editor.Instance.Windows.ContentWin.Open(Editor.Instance.Windows.ContentWin.View.Selection[0]);
};
// Viewing changes applied to this actor
var viewChanges = panel.Button("View Changes");
viewChanges.Button.Clicked += () => ViewChanges(viewChanges.Button, new Float2(0.0f, 20.0f));
// Viewing changes applied to this actor
var viewChanges = panel.Button("View Changes");
viewChanges.Button.Clicked += () => ViewChanges(viewChanges.Button, new Float2(0.0f, 20.0f));
}
// Link event to update editor on prefab apply
_linkedPrefabId = prefab.ID;
@@ -206,7 +202,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
if (_linkedPrefabId != Guid.Empty)
{
_linkedPrefabId = Guid.Empty;
Editor.Instance.Prefabs.PrefabApplying -= OnPrefabApplying;
Editor.Instance.Prefabs.PrefabApplied -= OnPrefabApplying;
Editor.Instance.Prefabs.PrefabApplied -= OnPrefabApplied;
}
}

View File

@@ -1,7 +1,6 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using System.Linq;
using FlaxEditor.CustomEditors.Elements;
using FlaxEditor.Surface;
using FlaxEngine;
@@ -36,8 +35,6 @@ namespace FlaxEditor.CustomEditors.Dedicated
(instance, parameter, tag) => ((AnimatedModel)instance).GetParameterValue(parameter.Identifier),
(instance, value, parameter, tag) => ((AnimatedModel)instance).SetParameterValue(parameter.Identifier, value),
Values);
if (!parameters.Any())
group.Label("No parameters", TextAlignment.Center);
_parametersAdded = true;
}
}

View File

@@ -15,23 +15,13 @@ namespace FlaxEditor.CustomEditors.Dedicated
private int _firstTimeShow;
private BezierCurveEditor<T> _curve;
private Splitter _splitter;
private string _heightCachedPath;
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
var item = layout.CustomContainer<BezierCurveEditor<T>>();
_curve = item.CustomControl;
var height = 120.0f;
var presenter = Presenter;
if (presenter != null && (presenter.Features & FeatureFlags.CacheExpandedGroups) != 0)
{
// Try to restore curve height
_heightCachedPath = layout.GetLayoutCachePath("Height");
if (Editor.Instance.ProjectCache.TryGetCustomData(_heightCachedPath, out float cachedHeight) && cachedHeight > 10.0f)
height = cachedHeight;
}
_curve.Height = height;
_curve.Height = 120.0f;
_curve.Edited += OnCurveEdited;
_firstTimeShow = 4; // For some weird reason it needs several frames of warmup (probably due to sliders smoothing)
_splitter = new Splitter
@@ -55,11 +45,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
private void OnSplitterMoved(Float2 location)
{
_curve.Height = Mathf.Clamp(_splitter.PointToParent(location).Y, 50.0f, 1000.0f);
// Cache curve height
if (_heightCachedPath != null)
Editor.Instance.ProjectCache.SetCustomData(_heightCachedPath, _curve.Height);
_curve.Height = Mathf.Clamp(_splitter.PointToParent(location).Y, 50.0f, 1000.0f);
}
/// <inheritdoc />
@@ -147,23 +133,13 @@ namespace FlaxEditor.CustomEditors.Dedicated
private int _firstTimeShow;
private LinearCurveEditor<T> _curve;
private Splitter _splitter;
private string _heightCachedPath;
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
var item = layout.CustomContainer<LinearCurveEditor<T>>();
_curve = item.CustomControl;
var height = 120.0f;
var presenter = Presenter;
if (presenter != null && (presenter.Features & FeatureFlags.CacheExpandedGroups) != 0)
{
// Try to restore curve height
_heightCachedPath = layout.GetLayoutCachePath("Height");
if (Editor.Instance.ProjectCache.TryGetCustomData(_heightCachedPath, out float cachedHeight) && cachedHeight > 10.0f)
height = cachedHeight;
}
_curve.Height = height;
_curve.Height = 120.0f;
_curve.Edited += OnCurveEdited;
_firstTimeShow = 4; // For some weird reason it needs several frames of warmup (probably due to sliders smoothing)
_splitter = new Splitter
@@ -188,10 +164,6 @@ namespace FlaxEditor.CustomEditors.Dedicated
private void OnSplitterMoved(Float2 location)
{
_curve.Height = Mathf.Clamp(_splitter.PointToParent(location).Y, 50.0f, 1000.0f);
// Cache curve height
if (_heightCachedPath != null)
Editor.Instance.ProjectCache.SetCustomData(_heightCachedPath, _curve.Height);
}
/// <inheritdoc />

View File

@@ -186,12 +186,12 @@ namespace FlaxEditor.CustomEditors.Dedicated
foreach (var file in files)
FindNewKeysCSharp(file, newKeys, allKeys);
// C/C++
files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.cpp", SearchOption.AllDirectories).Concat(Directory.GetFiles(Globals.ProjectSourceFolder, "*.c", SearchOption.AllDirectories)).ToArray();
// C++
files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.cpp", SearchOption.AllDirectories);
filesCount += files.Length;
foreach (var file in files)
FindNewKeysCpp(file, newKeys, allKeys);
files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.h", SearchOption.AllDirectories).Concat(Directory.GetFiles(Globals.ProjectSourceFolder, "*.hpp", SearchOption.AllDirectories)).ToArray();;
files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.h", SearchOption.AllDirectories);
filesCount += files.Length;
foreach (var file in files)
FindNewKeysCpp(file, newKeys, allKeys);

View File

@@ -53,9 +53,6 @@ public class ModelPrefabEditor : GenericEditor
}
}
// Creates the import path UI
Utilities.Utils.CreateImportPathUI(layout, modelPrefab.ImportPath, false);
var button = layout.Button("Reimport", "Reimports the source asset as prefab.");
_reimportButton = button.Button;
_reimportButton.Clicked += OnReimport;

View File

@@ -117,9 +117,6 @@ namespace FlaxEditor.CustomEditors.Dedicated
var data = SurfaceUtils.InitGraphParameters(parametersGroup);
SurfaceUtils.DisplayGraphParameters(group, data, ParameterGet, ParameterSet, Values, ParameterDefaultValue);
}
if (!parameters.Any())
groups.Label("No parameters", TextAlignment.Center);
}
/// <inheritdoc />

View File

@@ -1057,7 +1057,6 @@ namespace FlaxEditor.CustomEditors.Dedicated
protected override void Deinitialize()
{
_scriptToggles = null;
_scripts.Clear();
base.Deinitialize();
}

View File

@@ -4,7 +4,6 @@ using System;
using System.Linq;
using FlaxEditor.Content;
using FlaxEditor.GUI;
using FlaxEditor.GUI.Drag;
using FlaxEditor.Scripting;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -123,9 +122,7 @@ namespace FlaxEditor.CustomEditors.Editors
{
base.Refresh();
var differentValues = HasDifferentValues;
Picker.DifferentValues = differentValues;
if (!differentValues)
if (!HasDifferentValues)
{
_isRefreshing = true;
var value = Values[0];
@@ -159,17 +156,6 @@ namespace FlaxEditor.CustomEditors.Editors
private Rectangle DropdownRect => new Rectangle(Width - DropdownIconSize - DropdownIconMargin, DropdownIconMargin, DropdownIconSize, DropdownIconSize);
public Action ShowPicker;
public Action<ContentItem> OnAssetDropped;
private DragItems _dragItems;
private DragHandlers _dragHandlers;
private bool _hasValidDragOver;
private Func<ContentItem, bool> _validate;
public void SetValidationMethod(Func<ContentItem, bool> validate)
{
_validate = validate;
}
public override void Draw()
{
@@ -178,14 +164,6 @@ namespace FlaxEditor.CustomEditors.Editors
var style = FlaxEngine.GUI.Style.Current;
var dropdownRect = DropdownRect;
Render2D.DrawSprite(style.ArrowDown, dropdownRect, Enabled ? (DropdownRect.Contains(PointFromWindow(RootWindow.MousePosition)) ? style.BorderSelected : style.Foreground) : style.ForegroundDisabled);
// Check if drag is over
if (IsDragOver && _hasValidDragOver)
{
var bounds = new Rectangle(Float2.Zero, Size);
Render2D.FillRectangle(bounds, style.Selection);
Render2D.DrawRectangle(bounds, style.SelectionBorder);
}
}
public override bool OnMouseDown(Float2 location, MouseButton button)
@@ -229,68 +207,6 @@ namespace FlaxEditor.CustomEditors.Editors
return result;
}
}
private DragDropEffect DragEffect => _hasValidDragOver ? DragDropEffect.Move : DragDropEffect.None;
/// <inheritdoc />
public override DragDropEffect OnDragEnter(ref Float2 location, DragData data)
{
base.OnDragEnter(ref location, data);
// Ensure to have valid drag helpers (uses lazy init)
if (_dragItems == null)
_dragItems = new DragItems(ValidateDragAsset);
if (_dragHandlers == null)
{
_dragHandlers = new DragHandlers
{
_dragItems,
};
}
_hasValidDragOver = _dragHandlers.OnDragEnter(data) != DragDropEffect.None;
return DragEffect;
}
private bool ValidateDragAsset(ContentItem contentItem)
{
// Load or get asset
return _validate?.Invoke(contentItem) ?? false;
}
/// <inheritdoc />
public override DragDropEffect OnDragMove(ref Float2 location, DragData data)
{
base.OnDragMove(ref location, data);
return DragEffect;
}
/// <inheritdoc />
public override void OnDragLeave()
{
_hasValidDragOver = false;
_dragHandlers.OnDragLeave();
base.OnDragLeave();
}
/// <inheritdoc />
public override DragDropEffect OnDragDrop(ref Float2 location, DragData data)
{
var result = DragEffect;
base.OnDragDrop(ref location, data);
if (_dragItems.HasValidDrag)
{
OnAssetDropped(_dragItems.Objects[0]);
}
return result;
}
}
private TextBoxWithPicker _textBox;
@@ -305,21 +221,13 @@ namespace FlaxEditor.CustomEditors.Editors
{
if (HasDifferentTypes)
return;
_validator = new AssetPickerValidator(ScriptType.Null);
_textBox = layout.Custom<TextBoxWithPicker>().CustomControl;
_textBox.ShowPicker = OnShowPicker;
_textBox.OnAssetDropped = OnItemDropped;
_textBox.EditEnd += OnEditEnd;
_textBox.SetValidationMethod(_validator.IsValid);
_validator = new AssetPickerValidator(ScriptType.Null);
AssetRefEditor.ApplyAssetReferenceAttribute(Values, out _, _validator);
}
private void OnItemDropped(ContentItem item)
{
SetPickerPath(item);
}
private void OnShowPicker()
{
if (_validator.AssetType != ScriptType.Null)
@@ -377,9 +285,12 @@ namespace FlaxEditor.CustomEditors.Editors
{
base.Refresh();
_isRefreshing = true;
_textBox.Text = HasDifferentValues ? "Multiple Values" : GetPath();
_isRefreshing = false;
if (!HasDifferentValues)
{
_isRefreshing = true;
_textBox.Text = GetPath();
_isRefreshing = false;
}
}
/// <inheritdoc />

View File

@@ -26,8 +26,6 @@ namespace FlaxEditor.CustomEditors.Editors
public override void Initialize(LayoutElementsContainer layout)
{
_label = layout.ClickableLabel(Path).CustomControl;
_label.Margin = new Margin(0, 20.0f, 0, 0);
_label.ClipText = true;
_label.RightClick += ShowPicker;
var button = new Button
{

View File

@@ -9,8 +9,6 @@ using FlaxEditor.GUI.Drag;
using FlaxEditor.SceneGraph;
using FlaxEditor.SceneGraph.GUI;
using FlaxEditor.Scripting;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Utilities;
@@ -42,11 +40,6 @@ namespace FlaxEditor.CustomEditors.Editors
private DragScripts _dragScripts;
private DragHandlers _dragHandlers;
/// <summary>
/// The presenter using this control.
/// </summary>
public IPresenterOwner PresenterContext;
/// <summary>
/// Gets or sets the allowed objects type (given type and all sub classes). Must be <see cref="Object"/> type of any subclass.
/// </summary>
@@ -136,11 +129,6 @@ namespace FlaxEditor.CustomEditors.Editors
/// </summary>
public Func<Object, ScriptType, bool> CheckValid;
/// <summary>
/// Utility flag used to indicate that there are different values assigned to this reference editor and user should be informed about it.
/// </summary>
public bool DifferentValues;
/// <summary>
/// Initializes a new instance of the <see cref="FlaxObjectRefPickerControl"/> class.
/// </summary>
@@ -166,7 +154,7 @@ namespace FlaxEditor.CustomEditors.Editors
Value = actor;
RootWindow.Focus();
Focus();
}, PresenterContext);
});
}
else
{
@@ -175,7 +163,7 @@ namespace FlaxEditor.CustomEditors.Editors
Value = script;
RootWindow.Focus();
Focus();
}, PresenterContext);
});
}
}
@@ -209,14 +197,7 @@ namespace FlaxEditor.CustomEditors.Editors
Render2D.DrawRectangle(frameRect, isEnabled && (IsMouseOver || IsNavFocused) ? style.BorderHighlighted : style.BorderNormal);
// Check if has item selected
if (DifferentValues)
{
// Draw info
Render2D.PushClip(nameRect);
Render2D.DrawText(style.FontMedium, Type != null ? $"Multiple Values ({Utilities.Utils.GetPropertyNameUI(Type.ToString())})" : "-", nameRect, isEnabled ? style.ForegroundGrey : style.ForegroundGrey.AlphaMultiplied(0.75f), TextAlignment.Near, TextAlignment.Center);
Render2D.PopClip();
}
else if (isSelected)
if (isSelected)
{
// Draw name
Render2D.PushClip(nameRect);
@@ -345,19 +326,10 @@ namespace FlaxEditor.CustomEditors.Editors
}
else
{
if (PresenterContext is PropertiesWindow)
_linkedTreeNode = Editor.Instance.Scene.GetActorNode(actor).TreeNode;
else if (PresenterContext is PrefabWindow prefabWindow)
_linkedTreeNode = prefabWindow.Graph.Root.Find(actor).TreeNode;
if (_linkedTreeNode != null)
{
_linkedTreeNode.ExpandAllParents();
if (PresenterContext is PropertiesWindow)
Editor.Instance.Windows.SceneWin.SceneTreePanel.ScrollViewTo(_linkedTreeNode, true);
else if (PresenterContext is PrefabWindow prefabWindow)
(prefabWindow.Tree.Parent as Panel).ScrollViewTo(_linkedTreeNode, true);
_linkedTreeNode.StartHighlight();
}
_linkedTreeNode = Editor.Instance.Scene.GetActorNode(actor).TreeNode;
_linkedTreeNode.ExpandAllParents();
Editor.Instance.Windows.SceneWin.SceneTreePanel.ScrollViewTo(_linkedTreeNode, true);
_linkedTreeNode.StartHighlight();
}
return true;
}
@@ -400,20 +372,9 @@ namespace FlaxEditor.CustomEditors.Editors
// Select object
if (_value is Actor actor)
{
if (PresenterContext is PropertiesWindow)
Editor.Instance.SceneEditing.Select(actor);
else if (PresenterContext is PrefabWindow prefabWindow)
prefabWindow.Select(prefabWindow.Graph.Root.Find(actor));
}
Editor.Instance.SceneEditing.Select(actor);
else if (_value is Script script && script.Actor)
{
var a = script.Actor;
if (PresenterContext is PropertiesWindow)
Editor.Instance.SceneEditing.Select(a);
else if (PresenterContext is PrefabWindow prefabWindow)
prefabWindow.Select(prefabWindow.Graph.Root.Find(a));
}
Editor.Instance.SceneEditing.Select(script.Actor);
else if (_value is Asset asset)
Editor.Instance.Windows.ContentWin.Select(asset);
}
@@ -454,13 +415,13 @@ namespace FlaxEditor.CustomEditors.Editors
// Ensure to have valid drag helpers (uses lazy init)
if (_dragActors == null)
_dragActors = new DragActors(ValidateDragActor);
_dragActors = new DragActors(x => IsValid(x.Actor));
if (_dragActorsWithScript == null)
_dragActorsWithScript = new DragActors(ValidateDragActorWithScript);
if (_dragAssets == null)
_dragAssets = new DragAssets(ValidateDragAsset);
if (_dragScripts == null)
_dragScripts = new DragScripts(ValidateDragScript);
_dragScripts = new DragScripts(IsValid);
if (_dragHandlers == null)
{
_dragHandlers = new DragHandlers
@@ -485,43 +446,6 @@ namespace FlaxEditor.CustomEditors.Editors
return DragEffect;
}
private bool ValidateDragActor(ActorNode a)
{
if (!IsValid(a.Actor))
return false;
if (PresenterContext is PrefabWindow prefabWindow)
{
if (prefabWindow.Tree == a.TreeNode.ParentTree)
return true;
}
else if (PresenterContext is PropertiesWindow || PresenterContext == null)
{
if (a.ParentScene != null)
return true;
}
return false;
}
private bool ValidateDragScript(Script script)
{
if (!IsValid(script))
return false;
if (PresenterContext is PrefabWindow prefabWindow)
{
var actorNode = prefabWindow.Graph.Root.Find(script.Actor);
if (actorNode != null)
return true;
}
else if (PresenterContext is PropertiesWindow || PresenterContext == null)
{
if (script.Actor.HasScene)
return true;
}
return false;
}
private bool ValidateDragAsset(AssetItem assetItem)
{
// Check if can accept assets
@@ -540,18 +464,7 @@ namespace FlaxEditor.CustomEditors.Editors
private bool ValidateDragActorWithScript(ActorNode node)
{
bool isCorrectContext = false;
if (PresenterContext is PrefabWindow prefabWindow)
{
if (prefabWindow.Tree == node.TreeNode.ParentTree)
isCorrectContext = true;
}
else if (PresenterContext is PropertiesWindow || PresenterContext == null)
{
if (node.ParentScene != null)
isCorrectContext = true;
}
return node.Actor.Scripts.Any(IsValid) && isCorrectContext;
return node.Actor.Scripts.Any(IsValid);
}
/// <inheritdoc />
@@ -623,7 +536,6 @@ namespace FlaxEditor.CustomEditors.Editors
if (!HasDifferentTypes)
{
_element = layout.Custom<FlaxObjectRefPickerControl>();
_element.CustomControl.PresenterContext = Presenter.Owner;
_element.CustomControl.Type = Values.Type.Type != typeof(object) || Values[0] == null ? Values.Type : TypeUtils.GetObjectType(Values[0]);
_element.CustomControl.ValueChanged += () => SetValue(_element.CustomControl.Value);
}
@@ -634,9 +546,7 @@ namespace FlaxEditor.CustomEditors.Editors
{
base.Refresh();
var differentValues = HasDifferentValues;
_element.CustomControl.DifferentValues = differentValues;
if (!differentValues)
if (!HasDifferentValues)
{
_element.CustomControl.Value = Values[0] as Object;
}

View File

@@ -819,15 +819,6 @@ namespace FlaxEditor.CustomEditors.Editors
OnGroupsEnd();
}
/// <inheritdoc />
protected override void Deinitialize()
{
_visibleIfCaches = null;
_visibleIfPropertiesListsCache = null;
base.Deinitialize();
}
/// <inheritdoc />
public override void Refresh()
{

View File

@@ -228,6 +228,7 @@ namespace FlaxEditor.CustomEditors.Editors
// Handle Sliding
if (AllowSlidingForDifferentValues && (isSliding || _slidingEnded))
{
// TODO: handle linked values
Float3 average = Float3.Zero;
for (int i = 0; i < Values.Count; i++)
{
@@ -250,24 +251,12 @@ namespace FlaxEditor.CustomEditors.Editors
for (int i = 0; i < Values.Count; i++)
{
var v = Values[i];
if (LinkValues)
{
if (v is Vector3 asVector3)
v = asVector3 + new Vector3(newValue.X, newValue.Y, newValue.Z);
else if (v is Float3 asFloat3)
v = asFloat3 + new Float3(newValue.X, newValue.Y, newValue.Z);
else if (v is Double3 asDouble3)
v = asDouble3 + new Double3(newValue.X, newValue.Y, newValue.Z);
}
else
{
if (v is Vector3 asVector3)
v = asVector3 + new Vector3(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0);
else if (v is Float3 asFloat3)
v = asFloat3 + new Float3(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0);
else if (v is Double3 asDouble3)
v = asDouble3 + new Double3(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0);
}
if (v is Vector3 asVector3)
v = asVector3 + new Vector3(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0);
else if (v is Float3 asFloat3)
v = asFloat3 + new Float3(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0);
else if (v is Double3 asDouble3)
v = asDouble3 + new Double3(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0);
newObjects[i] = v;
}
@@ -278,27 +267,16 @@ namespace FlaxEditor.CustomEditors.Editors
}
else
{
// TODO: handle linked values
for (int i = 0; i < Values.Count; i++)
{
object v = Values[i];
if (LinkValues)
{
if (v is Vector3 asVector3)
v = asVector3 + new Vector3(xValue, yValue, zValue);
else if (v is Float3 asFloat3)
v = asFloat3 + new Float3(xValue, yValue, zValue);
else if (v is Double3 asDouble3)
v = asDouble3 + new Double3(xValue, yValue, zValue);
}
else
{
if (v is Vector3 asVector3)
v = new Vector3(_valueChanged == ValueChanged.X ? xValue : asVector3.X, _valueChanged == ValueChanged.Y ? yValue : asVector3.Y, _valueChanged == ValueChanged.Z ? zValue : asVector3.Z);
else if (v is Float3 asFloat3)
v = new Float3(_valueChanged == ValueChanged.X ? xValue : asFloat3.X, _valueChanged == ValueChanged.Y ? yValue : asFloat3.Y, _valueChanged == ValueChanged.Z ? zValue : asFloat3.Z);
else if (v is Double3 asDouble3)
v = new Double3(_valueChanged == ValueChanged.X ? xValue : asDouble3.X, _valueChanged == ValueChanged.Y ? yValue : asDouble3.Y, _valueChanged == ValueChanged.Z ? zValue : asDouble3.Z);
}
if (v is Vector3 asVector3)
v = new Vector3(_valueChanged == ValueChanged.X ? xValue : asVector3.X, _valueChanged == ValueChanged.Y ? yValue : asVector3.Y, _valueChanged == ValueChanged.Z ? zValue : asVector3.Z);
else if (v is Float3 asFloat3)
v = new Float3(_valueChanged == ValueChanged.X ? xValue : asFloat3.X, _valueChanged == ValueChanged.Y ? yValue : asFloat3.Y, _valueChanged == ValueChanged.Z ? zValue : asFloat3.Z);
else if (v is Double3 asDouble3)
v = new Double3(_valueChanged == ValueChanged.X ? xValue : asDouble3.X, _valueChanged == ValueChanged.Y ? yValue : asDouble3.Y, _valueChanged == ValueChanged.Z ? zValue : asDouble3.Z);
newObjects[i] = v;
}

View File

@@ -96,20 +96,6 @@ namespace FlaxEditor.CustomEditors
menu.Show(groupPanel, location);
}
internal string GetLayoutCachePath(string name)
{
// Build group identifier (made of path from group titles)
var expandPath = name;
var container = this;
while (container != null && !(container is CustomEditorPresenter))
{
if (container.ContainerControl is DropPanel dropPanel)
expandPath = dropPanel.HeaderText + "/" + expandPath;
container = container._parent;
}
return expandPath;
}
/// <summary>
/// Adds new group element.
/// </summary>
@@ -126,7 +112,14 @@ namespace FlaxEditor.CustomEditors
if (presenter != null && (presenter.Features & FeatureFlags.CacheExpandedGroups) != 0)
{
// Build group identifier (made of path from group titles)
var expandPath = GetLayoutCachePath(title);
var expandPath = title;
var container = this;
while (container != null && !(container is CustomEditorPresenter))
{
if (container.ContainerControl is DropPanel dropPanel)
expandPath = dropPanel.HeaderText + "/" + expandPath;
container = container._parent;
}
// Caching/restoring expanded groups (non-root groups cache expanded state so invert boolean expression)
if (Editor.Instance.ProjectCache.IsGroupToggled(expandPath) ^ isSubGroup)

View File

@@ -250,7 +250,7 @@ namespace FlaxEditor.CustomEditors
if (objA == null && objB is string objBStr && objBStr.Length == 0)
return true;
return FlaxEngine.Json.JsonSerializer.ValueEquals(objA, objB);
return Newtonsoft.Json.Utilities.MiscellaneousUtils.ValueEquals(objA, objB);
}
/// <summary>

View File

@@ -550,7 +550,7 @@ int32 Editor::LoadProduct()
}
if (!FileSystem::FileExists(files[0]))
{
Platform::Fatal(TEXT("Cannot open selected project file because it doesn't exist."));
Platform::Fatal(TEXT("Cannot opoen selected project file because it doesn't exist."));
return -1;
}
projectPath = StringUtils::GetDirectoryName(files[0]);

View File

@@ -1686,6 +1686,9 @@ namespace FlaxEditor
[return: MarshalAs(UnmanagedType.U1)]
internal static partial bool Internal_CanSetToRoot(IntPtr prefab, IntPtr newRoot);
[LibraryImport("FlaxEngine", EntryPoint = "EditorInternal_GetPrefabNestedObject", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))]
internal static partial void Internal_GetPrefabNestedObject(IntPtr prefabId, IntPtr prefabObjectId, IntPtr outPrefabId, IntPtr outPrefabObjectId);
[LibraryImport("FlaxEngine", EntryPoint = "EditorInternal_GetAnimationTime", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(StringMarshaller))]
internal static partial float Internal_GetAnimationTime(IntPtr animatedModel);

View File

@@ -48,11 +48,6 @@ namespace FlaxEditor.GUI
/// </summary>
public bool CanEdit = true;
/// <summary>
/// Utility flag used to indicate that there are different values assigned to this reference editor and user should be informed about it.
/// </summary>
public bool DifferentValues;
/// <summary>
/// Initializes a new instance of the <see cref="AssetPicker"/> class.
/// </summary>
@@ -126,13 +121,7 @@ namespace FlaxEditor.GUI
if (CanEdit)
Render2D.DrawSprite(style.ArrowDown, button1Rect, button1Rect.Contains(_mousePos) ? style.Foreground : style.ForegroundGrey);
if (DifferentValues)
{
// No element selected
Render2D.FillRectangle(iconRect, style.BackgroundNormal);
Render2D.DrawText(style.FontMedium, "Multiple\nValues", iconRect, style.Foreground, TextAlignment.Center, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, Height / DefaultIconSize);
}
else if (Validator.SelectedItem != null)
if (Validator.SelectedItem != null)
{
// Draw item preview
Validator.SelectedItem.DrawThumbnail(ref iconRect);

View File

@@ -220,7 +220,6 @@ namespace FlaxEditor.GUI.ContextMenu
desc.IsTopmost = true;
desc.Type = WindowType.Popup;
desc.Parent = parentWin.Window;
desc.Title = "ContextMenu";
desc.HasSizingFrame = false;
OnWindowCreating(ref desc);
_window = Platform.CreateWindow(ref desc);

View File

@@ -30,10 +30,8 @@ namespace FlaxEditor.GUI
internal bool _isMovingTangent;
internal bool _movedView;
internal bool _movedKeyframes;
internal bool _toggledSelection;
private TangentPoint _movingTangent;
private Float2 _movingSelectionStart;
private Float2 _movingSelectionStartPosLock;
private Float2[] _movingSelectionOffsets;
private Float2 _cmShowPos;
@@ -58,11 +56,12 @@ namespace FlaxEditor.GUI
internal void UpdateSelection(ref Rectangle selectionRect)
{
// Find controls to select
var children = _children;
for (int i = 0; i < children.Count; i++)
for (int i = 0; i < Children.Count; i++)
{
if (children[i] is KeyframePoint p)
if (Children[i] is KeyframePoint p)
{
p.IsSelected = p.Bounds.Intersects(ref selectionRect);
}
}
_editor.UpdateTangents();
}
@@ -73,7 +72,6 @@ namespace FlaxEditor.GUI
_isMovingSelection = true;
_movedKeyframes = false;
var viewRect = _editor._mainPanel.GetClientArea();
_movingSelectionStartPosLock = location;
_movingSelectionStart = PointToKeyframes(location, ref viewRect);
if (_movingSelectionOffsets == null || _movingSelectionOffsets.Length != _editor._points.Count)
_movingSelectionOffsets = new Float2[_editor._points.Count];
@@ -84,17 +82,10 @@ namespace FlaxEditor.GUI
internal void OnMove(Float2 location)
{
// Skip updating keyframes until move actual starts to be meaningful
if (Float2.Distance(ref _movingSelectionStartPosLock, ref location) < 1.5f)
return;
_movingSelectionStartPosLock = Float2.Minimum;
var viewRect = _editor._mainPanel.GetClientArea();
var locationKeyframes = PointToKeyframes(location, ref viewRect);
var accessor = _editor.Accessor;
var components = accessor.GetCurveComponents();
var snapEnabled = Root.GetKey(KeyboardKeys.Control);
var snapGrid = snapEnabled ? _editor.GetGridSnap() : Float2.One;
for (var i = 0; i < _editor._points.Count; i++)
{
var p = _editor._points[i];
@@ -131,20 +122,7 @@ namespace FlaxEditor.GUI
if (isFirstSelected)
{
time = locationKeyframes.X + offset.X;
}
if (snapEnabled)
{
// Snap to the grid
var key = new Float2(time, value);
key = Float2.SnapToGrid(key, snapGrid);
time = key.X;
value = key.Y;
}
// Clamp and snap time to the valid range
if (isFirstSelected)
{
if (_editor.FPS.HasValue)
{
float fps = _editor.FPS.Value;
@@ -153,6 +131,8 @@ namespace FlaxEditor.GUI
time = Mathf.Clamp(time, minTime, maxTime);
}
// TODO: snapping keyframes to grid when moving
_editor.SetKeyframeInternal(p.Index, time, value, p.Component);
}
_editor.UpdateKeyframes();
@@ -254,11 +234,7 @@ namespace FlaxEditor.GUI
var k = _editor.GetKeyframe(_movingTangent.Index);
var kv = _editor.GetKeyframeValue(k);
var value = _editor.Accessor.GetCurveValue(ref kv, _movingTangent.Component);
var tangent = PointToKeyframes(location, ref viewRect).Y - value;
if (Root.GetKey(KeyboardKeys.Control))
tangent = Float2.SnapToGrid(new Float2(0, tangent), _editor.GetGridSnap()).Y; // Snap tangent over Y axis
tangent = tangent * _editor.ViewScale.X * 2;
_movingTangent.TangentValue = tangent;
_movingTangent.TangentValue = PointToKeyframes(location, ref viewRect).Y - value;
_editor.UpdateTangents();
Cursor = CursorType.SizeNS;
_movedKeyframes = true;
@@ -307,7 +283,6 @@ namespace FlaxEditor.GUI
}
// Cache data
_toggledSelection = false;
_isMovingSelection = false;
_isMovingTangent = false;
_mousePos = location;
@@ -330,7 +305,13 @@ namespace FlaxEditor.GUI
{
if (_leftMouseDown)
{
if (Root.GetKey(KeyboardKeys.Shift))
if (Root.GetKey(KeyboardKeys.Control))
{
// Toggle selection
keyframe.IsSelected = !keyframe.IsSelected;
_editor.UpdateTangents();
}
else if (Root.GetKey(KeyboardKeys.Shift))
{
// Select range
keyframe.IsSelected = true;
@@ -354,14 +335,10 @@ namespace FlaxEditor.GUI
else if (!keyframe.IsSelected)
{
// Select node
if (!Root.GetKey(KeyboardKeys.Control))
{
if (_editor.KeyframesEditorContext != null)
_editor.KeyframesEditorContext.OnKeyframesDeselect(_editor);
else
_editor.ClearSelection();
}
_toggledSelection = true;
if (_editor.KeyframesEditorContext != null)
_editor.KeyframesEditorContext.OnKeyframesDeselect(_editor);
else
_editor.ClearSelection();
keyframe.IsSelected = true;
_editor.UpdateTangents();
}
@@ -452,12 +429,6 @@ namespace FlaxEditor.GUI
else
OnMoveEnd(location);
}
// Toggle selection
else if (!_toggledSelection && Root.GetKey(KeyboardKeys.Control) && GetChildAt(location) is KeyframePoint keyframe)
{
keyframe.IsSelected = !keyframe.IsSelected;
_editor.UpdateTangents();
}
_isMovingSelection = false;
_isMovingTangent = false;
@@ -543,11 +514,11 @@ namespace FlaxEditor.GUI
{
if (base.OnMouseDoubleClick(location, button))
return true;
// Add keyframe on double click
var child = GetChildAt(location);
if (child is not KeyframePoint &&
child is not TangentPoint &&
if (child is not KeyframePoint &&
child is not TangentPoint &&
_editor.KeyframesCount < _editor.MaxKeyframes)
{
var viewRect = _editor._mainPanel.GetClientArea();
@@ -574,7 +545,7 @@ namespace FlaxEditor.GUI
var viewRect = _editor._mainPanel.GetClientArea();
var locationInKeyframes = PointToKeyframes(location, ref viewRect);
var locationInEditorBefore = _editor.PointFromKeyframes(locationInKeyframes, ref viewRect);
// Scale relative to the curve size
var scale = new Float2(delta * 0.1f);
_editor._mainPanel.GetDesireClientArea(out var mainPanelArea);

View File

@@ -163,11 +163,10 @@ namespace FlaxEditor.GUI
/// <inheritdoc />
public override void Draw()
{
var style = Style.Current;
var rect = new Rectangle(Float2.Zero, Size);
var color = Editor.ShowCollapsed ? style.ForegroundDisabled : Editor.Colors[Component];
var color = Editor.ShowCollapsed ? Color.Gray : Editor.Colors[Component];
if (IsSelected)
color = Editor.ContainsFocus ? style.SelectionBorder : Color.Lerp(style.ForegroundDisabled, style.SelectionBorder, 0.4f);
color = Editor.ContainsFocus ? Color.YellowGreen : Color.Lerp(Color.Gray, Color.YellowGreen, 0.4f);
if (IsMouseOver)
color *= 1.1f;
Render2D.FillRectangle(rect, color);
@@ -245,19 +244,14 @@ namespace FlaxEditor.GUI
set => Editor.SetKeyframeTangentInternal(Index, IsIn, Component, value);
}
internal float TangentOffset => 50.0f / Editor.ViewScale.X;
/// <inheritdoc />
public override void Draw()
{
var style = Style.Current;
var thickness = 6.0f / Mathf.Max(Editor.ViewScale.X, 1.0f);
var size = Size;
var pointPos = PointFromParent(Point.Center);
Render2D.DrawLine(size * 0.5f, pointPos, style.ForegroundDisabled, thickness);
Render2D.DrawLine(Size * 0.5f, pointPos, Color.Gray);
var rect = new Rectangle(Float2.Zero, size);
var color = style.BorderSelected;
var rect = new Rectangle(Float2.Zero, Size);
var color = Color.MediumVioletRed;
if (IsMouseOver)
color *= 1.1f;
Render2D.FillRectangle(rect, color);
@@ -295,7 +289,7 @@ namespace FlaxEditor.GUI
/// <summary>
/// The curve time/value axes tick steps.
/// </summary>
protected double[] TickSteps = Utilities.Utils.CurveTickSteps;
protected float[] TickSteps = Utilities.Utils.CurveTickSteps;
/// <summary>
/// The curve contents area.
@@ -448,7 +442,7 @@ namespace FlaxEditor.GUI
_mainPanel = new Panel(ScrollBars.Both)
{
ScrollMargin = new Margin(150.0f),
AlwaysShowScrollbars = false,
AlwaysShowScrollbars = true,
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
Parent = this
@@ -674,82 +668,26 @@ namespace FlaxEditor.GUI
OnEditingEnd();
}
private void ShowCurve(bool selectedOnly)
{
if (_points.Count == 0)
return;
int pass = 1;
REDO:
// Get curve bounds in Keyframes (time and value)
Float2 posMin = Float2.Maximum, posMax = Float2.Minimum;
// TODO: include bezier curve bounds calculation to handle curve outside the bounds made out of points
foreach (var point in _points)
{
if (selectedOnly && !point.IsSelected)
continue;
var pos = point.Point;
Float2.Min(ref posMin, ref pos, out posMin);
Float2.Max(ref posMax, ref pos, out posMax);
}
// Apply margin around the area
var posMargin = (posMax - posMin) * 0.05f;
posMin -= posMargin;
posMax += posMargin;
// Convert from Keyframes to Contents
_mainPanel.GetDesireClientArea(out var viewRect);
PointFromKeyframesToContents(ref posMin, ref viewRect);
PointFromKeyframesToContents(ref posMax, ref viewRect);
var tmp = posMin;
Float2.Min(ref posMin, ref posMax, out posMin);
Float2.Max(ref posMax, ref tmp, out posMax);
var contentsSize = posMax - posMin;
// Convert from Contents to Main Panel
posMin = _contents.PointToParent(posMin);
posMax = _contents.PointToParent(posMax);
tmp = posMin;
Float2.Min(ref posMin, ref posMax, out posMin);
Float2.Max(ref posMax, ref tmp, out posMax);
// Update zoom (leave unchanged when focusing a single point)
var zoomMask = EnableZoom;
if (Mathf.IsZero(posMargin.X))
zoomMask &= ~UseMode.Horizontal;
if (Mathf.IsZero(posMargin.Y))
zoomMask &= ~UseMode.Vertical;
ViewScale = ApplyUseModeMask(zoomMask, viewRect.Size / contentsSize, ViewScale);
// Update scroll (attempt to center the area when it's smaller than the view)
Float2 viewOffset = -posMin;
Float2 viewSize = _mainPanel.Size;
Float2 viewSizeLeft = viewSize - Float2.Clamp(posMax - posMin, Float2.Zero, viewSize);
viewOffset += viewSizeLeft * 0.5f;
viewOffset = ApplyUseModeMask(EnablePanning, viewOffset, _mainPanel.ViewOffset);
_mainPanel.ViewOffset = viewOffset;
// Do it multiple times so the view offset can be properly calculate once the view scale gets changes
if (pass++ <= 2)
goto REDO;
UpdateKeyframes();
}
/// <summary>
/// Focuses the view on the selected keyframes.
/// </summary>
public void FocusSelection()
{
// Fallback to showing whole curve if nothing is selected
ShowCurve(SelectionCount != 0);
}
/// <inheritdoc />
public override void ShowWholeCurve()
{
ShowCurve(false);
_mainPanel.GetDesireClientArea(out var mainPanelArea);
ViewScale = ApplyUseModeMask(EnableZoom, mainPanelArea.Size / _contents.Size, ViewScale);
Float2 minPos = Float2.Maximum;
foreach (var point in _points)
{
var pos = point.PointToParent(point.Location);
Float2.Min(ref minPos, ref pos, out minPos);
}
var minPosPoint = _contents.PointToParent(ref minPos);
var scroll = new Float2(_mainPanel.HScrollBar?.TargetValue ?? 0, _mainPanel.VScrollBar?.TargetValue ?? 0);
scroll = ApplyUseModeMask(EnablePanning, minPosPoint, scroll);
if (_mainPanel.HScrollBar != null)
_mainPanel.HScrollBar.TargetValue = scroll.X;
if (_mainPanel.VScrollBar != null)
_mainPanel.VScrollBar.TargetValue = scroll.Y;
UpdateKeyframes();
}
/// <inheritdoc />
@@ -828,7 +766,10 @@ namespace FlaxEditor.GUI
point = _contents.PointFromParent(point);
// Contents -> Keyframes
return PointFromContentsToKeyframes(ref point, ref curveContentAreaBounds);
return new Float2(
(point.X + _contents.Location.X) / UnitsPerSecond,
(point.Y + _contents.Location.Y - curveContentAreaBounds.Height) / -UnitsPerSecond
);
}
/// <summary>
@@ -840,7 +781,10 @@ namespace FlaxEditor.GUI
protected Float2 PointFromKeyframes(Float2 point, ref Rectangle curveContentAreaBounds)
{
// Keyframes -> Contents
PointFromKeyframesToContents(ref point, ref curveContentAreaBounds);
point = new Float2(
point.X * UnitsPerSecond - _contents.Location.X,
point.Y * -UnitsPerSecond + curveContentAreaBounds.Height - _contents.Location.Y
);
// Contents -> Main Panel
point = _contents.PointToParent(point);
@@ -849,27 +793,11 @@ namespace FlaxEditor.GUI
return _mainPanel.PointToParent(point);
}
internal Float2 PointFromContentsToKeyframes(ref Float2 point, ref Rectangle curveContentAreaBounds)
{
return new Float2(
(point.X + _contents.Location.X) / UnitsPerSecond,
(point.Y + _contents.Location.Y - curveContentAreaBounds.Height) / -UnitsPerSecond
);
}
internal void PointFromKeyframesToContents(ref Float2 point, ref Rectangle curveContentAreaBounds)
{
point = new Float2(
point.X * UnitsPerSecond - _contents.Location.X,
point.Y * -UnitsPerSecond + curveContentAreaBounds.Height - _contents.Location.Y
);
}
private void DrawAxis(Float2 axis, Rectangle viewRect, float min, float max, float pixelRange)
{
Utilities.Utils.DrawCurveTicks((decimal tick, double step, float strength) =>
Utilities.Utils.DrawCurveTicks((float tick, float strength) =>
{
var p = PointFromKeyframes(axis * (float)tick, ref viewRect);
var p = PointFromKeyframes(axis * tick, ref viewRect);
// Draw line
var lineRect = new Rectangle
@@ -892,24 +820,6 @@ namespace FlaxEditor.GUI
}, TickSteps, ref _tickStrengths, min, max, pixelRange);
}
private void SetupGrid(out Float2 min, out Float2 max, out Float2 pixelRange)
{
var viewRect = _mainPanel.GetClientArea();
var upperLeft = PointToKeyframes(viewRect.Location, ref viewRect);
var bottomRight = PointToKeyframes(viewRect.Size, ref viewRect);
min = Float2.Min(upperLeft, bottomRight);
max = Float2.Max(upperLeft, bottomRight);
pixelRange = (max - min) * ViewScale * UnitsPerSecond;
}
private Float2 GetGridSnap()
{
SetupGrid(out var min, out var max, out var pixelRange);
return new Float2(Utilities.Utils.GetCurveGridSnap(TickSteps, ref _tickStrengths, min.X, max.X, pixelRange.X),
Utilities.Utils.GetCurveGridSnap(TickSteps, ref _tickStrengths, min.Y, max.Y, pixelRange.Y));
}
/// <summary>
/// Draws the curve.
/// </summary>
@@ -939,7 +849,12 @@ namespace FlaxEditor.GUI
// Draw time and values axes
if (ShowAxes != UseMode.Off)
{
SetupGrid(out var min, out var max, out var pixelRange);
var upperLeft = PointToKeyframes(viewRect.Location, ref viewRect);
var bottomRight = PointToKeyframes(viewRect.Size, ref viewRect);
var min = Float2.Min(upperLeft, bottomRight);
var max = Float2.Max(upperLeft, bottomRight);
var pixelRange = (max - min) * ViewScale * UnitsPerSecond;
Render2D.PushClip(ref viewRect);
@@ -1024,7 +939,7 @@ namespace FlaxEditor.GUI
}
else if (options.FocusSelection.Process(this))
{
FocusSelection();
ShowWholeCurve();
return true;
}
@@ -2285,7 +2200,7 @@ namespace FlaxEditor.GUI
var tangent = t.TangentValue;
var direction = t.IsIn ? -1.0f : 1.0f;
var offset = t.TangentOffset;
var offset = 30.0f;
var location = GetKeyframePoint(ref k, selectedComponent);
t.Size = KeyframesSize / ViewScale;
t.Location = new Float2
@@ -2312,18 +2227,6 @@ namespace FlaxEditor.GUI
}
}
/// <inheritdoc />
protected override void SetScaleInternal(ref Float2 scale)
{
base.SetScaleInternal(ref scale);
if (!_showCollapsed)
{
// Refresh keyframes when zooming (their size depends on the scale)
UpdateKeyframes();
}
}
/// <inheritdoc />
protected override void OnShowContextMenu(ContextMenu.ContextMenu cm, int selectionCount)
{

View File

@@ -0,0 +1,532 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.GUI.Docking
{
/// <summary>
/// Helper class used to handle docking windows dragging and docking.
/// </summary>
public class DockHintWindow
{
private FloatWindowDockPanel _toMove;
private Float2 _dragOffset;
private Float2 _defaultWindowSize;
private Rectangle _rectDock;
private Rectangle _rectWindow;
private Float2 _mouse;
private DockState _toSet;
private DockPanel _toDock;
private bool _lateDragOffsetUpdate;
private Rectangle _rLeft, _rRight, _rBottom, _rUpper, _rCenter;
private DockHintWindow(FloatWindowDockPanel toMove)
{
_toMove = toMove;
_toSet = DockState.Float;
var window = toMove.Window.Window;
// Remove focus from drag target
_toMove.Focus();
_toMove.Defocus();
// Focus window
window.Focus();
// Check if window is maximized and restore window.
if (window.IsMaximized)
{
// Restore window and set position to mouse.
var mousePos = window.MousePosition;
var previousSize = window.Size;
window.Restore();
window.Position = Platform.MousePosition - mousePos * window.Size / previousSize;
}
// Calculate dragging offset and move window to the destination position
var mouseScreenPosition = Platform.MousePosition;
// If the _toMove window was not focused when initializing this window, the result vector only contains zeros
// and to prevent a failure, we need to perform an update for the drag offset at later time which will be done in the OnMouseMove event handler.
if (mouseScreenPosition != Float2.Zero)
CalculateDragOffset(mouseScreenPosition);
else
_lateDragOffsetUpdate = true;
// Get initial size
_defaultWindowSize = window.Size;
// Init proxy window
Proxy.Init(ref _defaultWindowSize);
// Bind events
Proxy.Window.MouseUp += OnMouseUp;
Proxy.Window.MouseMove += OnMouseMove;
Proxy.Window.LostFocus += OnLostFocus;
_toMove.Window.Window.MouseUp += OnMouseUp; // Intercept the drag release mouse event from source window
// Update window GUI
Proxy.Window.GUI.PerformLayout();
// Update rectangles
UpdateRects();
// Enable hit window presentation
Proxy.Window.RenderingEnabled = true;
Proxy.Window.Show();
Proxy.Window.Focus();
// Hide base window
window.Hide();
// Start tracking mouse
Proxy.Window.StartTrackingMouse(false);
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
public void Dispose()
{
// End tracking mouse
Proxy.Window.EndTrackingMouse();
// Disable rendering
Proxy.Window.RenderingEnabled = false;
// Unbind events
Proxy.Window.MouseUp -= OnMouseUp;
Proxy.Window.MouseMove -= OnMouseMove;
Proxy.Window.LostFocus -= OnLostFocus;
if (_toMove?.Window?.Window)
_toMove.Window.Window.MouseUp -= OnMouseUp;
// Hide the proxy
Proxy.Hide();
if (_toMove == null)
return;
// Check if window won't be docked
if (_toSet == DockState.Float)
{
var window = _toMove.Window?.Window;
if (window == null)
return;
var mouse = Platform.MousePosition;
// Move base window
window.Position = mouse - _dragOffset;
// Show base window
window.Show();
}
else
{
bool hasNoChildPanels = _toMove.ChildPanelsCount == 0;
// Check if window has only single tab
if (hasNoChildPanels && _toMove.TabsCount == 1)
{
// Dock window
_toMove.GetTab(0).Show(_toSet, _toDock);
}
// Check if dock as tab and has no child panels
else if (hasNoChildPanels && _toSet == DockState.DockFill)
{
// Dock all tabs
while (_toMove.TabsCount > 0)
{
_toMove.GetTab(0).Show(DockState.DockFill, _toDock);
}
}
else
{
var selectedTab = _toMove.SelectedTab;
// Dock the first tab into the target location
var firstTab = _toMove.GetTab(0);
firstTab.Show(_toSet, _toDock);
// Dock rest of the tabs
while (_toMove.TabsCount > 0)
{
_toMove.GetTab(0).Show(DockState.DockFill, firstTab);
}
// Keep selected tab being selected
selectedTab?.SelectTab();
}
// Focus target window
_toDock.Root.Focus();
}
_toMove = null;
}
/// <summary>
/// Creates the new dragging hit window.
/// </summary>
/// <param name="toMove">Floating dock panel to move.</param>
/// <returns>The dock hint window object.</returns>
public static DockHintWindow Create(FloatWindowDockPanel toMove)
{
if (toMove == null)
throw new ArgumentNullException();
return new DockHintWindow(toMove);
}
/// <summary>
/// Creates the new dragging hit window.
/// </summary>
/// <param name="toMove">Dock window to move.</param>
/// <returns>The dock hint window object.</returns>
public static DockHintWindow Create(DockWindow toMove)
{
if (toMove == null)
throw new ArgumentNullException();
// Show floating
toMove.ShowFloating();
// Move window to the mouse position (with some offset for caption bar)
var window = (WindowRootControl)toMove.Root;
var mouse = Platform.MousePosition;
window.Window.Position = mouse - new Float2(8, 8);
// Get floating panel
var floatingPanelToMove = window.GetChild(0) as FloatWindowDockPanel;
return new DockHintWindow(floatingPanelToMove);
}
/// <summary>
/// Calculates window rectangle in the dock window.
/// </summary>
/// <param name="state">Window dock state.</param>
/// <param name="rect">Dock panel rectangle.</param>
/// <returns>Calculated window rectangle.</returns>
public static Rectangle CalculateDockRect(DockState state, ref Rectangle rect)
{
Rectangle result = rect;
switch (state)
{
case DockState.DockFill:
result.Location.Y += DockPanel.DefaultHeaderHeight;
result.Size.Y -= DockPanel.DefaultHeaderHeight;
break;
case DockState.DockTop:
result.Size.Y *= DockPanel.DefaultSplitterValue;
break;
case DockState.DockLeft:
result.Size.X *= DockPanel.DefaultSplitterValue;
break;
case DockState.DockBottom:
result.Location.Y += result.Size.Y * (1 - DockPanel.DefaultSplitterValue);
result.Size.Y *= DockPanel.DefaultSplitterValue;
break;
case DockState.DockRight:
result.Location.X += result.Size.X * (1 - DockPanel.DefaultSplitterValue);
result.Size.X *= DockPanel.DefaultSplitterValue;
break;
}
return result;
}
private void CalculateDragOffset(Float2 mouseScreenPosition)
{
var baseWinPos = _toMove.Window.Window.Position;
_dragOffset = mouseScreenPosition - baseWinPos;
}
private void UpdateRects()
{
// Cache mouse position
_mouse = Platform.MousePosition;
// Check intersection with any dock panel
var uiMouse = _mouse;
_toDock = _toMove.MasterPanel.HitTest(ref uiMouse, _toMove);
// Check dock state to use
bool showProxyHints = _toDock != null;
bool showBorderHints = showProxyHints;
bool showCenterHint = showProxyHints;
if (showProxyHints)
{
// If moved window has not only tabs but also child panels disable docking as tab
if (_toMove.ChildPanelsCount > 0)
showCenterHint = false;
// Disable docking windows with one or more dock panels inside
if (_toMove.ChildPanelsCount > 0)
showBorderHints = false;
// Get dock area
_rectDock = _toDock.DockAreaBounds;
// Cache dock rectangles
var size = _rectDock.Size;
var offset = _rectDock.Location;
var borderMargin = 4.0f;
var hintWindowsSize = Proxy.HintWindowsSize * Platform.DpiScale;
var hintWindowsSize2 = hintWindowsSize * 0.5f;
var centerX = size.X * 0.5f;
var centerY = size.Y * 0.5f;
_rUpper = new Rectangle(centerX - hintWindowsSize2, borderMargin, hintWindowsSize, hintWindowsSize) + offset;
_rBottom = new Rectangle(centerX - hintWindowsSize2, size.Y - hintWindowsSize - borderMargin, hintWindowsSize, hintWindowsSize) + offset;
_rLeft = new Rectangle(borderMargin, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
_rRight = new Rectangle(size.X - hintWindowsSize - borderMargin, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
_rCenter = new Rectangle(centerX - hintWindowsSize2, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
// Hit test
DockState toSet = DockState.Float;
if (showBorderHints)
{
if (_rUpper.Contains(_mouse))
toSet = DockState.DockTop;
else if (_rBottom.Contains(_mouse))
toSet = DockState.DockBottom;
else if (_rLeft.Contains(_mouse))
toSet = DockState.DockLeft;
else if (_rRight.Contains(_mouse))
toSet = DockState.DockRight;
}
if (showCenterHint && _rCenter.Contains(_mouse))
toSet = DockState.DockFill;
_toSet = toSet;
// Show proxy hint windows
Proxy.Down.Position = _rBottom.Location;
Proxy.Left.Position = _rLeft.Location;
Proxy.Right.Position = _rRight.Location;
Proxy.Up.Position = _rUpper.Location;
Proxy.Center.Position = _rCenter.Location;
}
else
{
_toSet = DockState.Float;
}
// Update proxy hint windows visibility
Proxy.Down.IsVisible = showProxyHints & showBorderHints;
Proxy.Left.IsVisible = showProxyHints & showBorderHints;
Proxy.Right.IsVisible = showProxyHints & showBorderHints;
Proxy.Up.IsVisible = showProxyHints & showBorderHints;
Proxy.Center.IsVisible = showProxyHints & showCenterHint;
// Calculate proxy/dock/window rectangles
if (_toDock == null)
{
// Floating window over nothing
_rectWindow = new Rectangle(_mouse - _dragOffset, _defaultWindowSize);
}
else
{
if (_toSet == DockState.Float)
{
// Floating window over dock panel
_rectWindow = new Rectangle(_mouse - _dragOffset, _defaultWindowSize);
}
else
{
// Use only part of the dock panel to show hint
_rectWindow = CalculateDockRect(_toSet, ref _rectDock);
}
}
// Update proxy window
Proxy.Window.ClientBounds = _rectWindow;
}
private void OnMouseUp(ref Float2 location, MouseButton button, ref bool handled)
{
if (button == MouseButton.Left)
{
Dispose();
}
}
private void OnMouseMove(ref Float2 mousePos)
{
// Recalculate the drag offset because the current mouse screen position was invalid when we initialized the window
if (_lateDragOffsetUpdate)
{
// Calculate dragging offset and move window to the destination position
CalculateDragOffset(mousePos);
// Reset state
_lateDragOffsetUpdate = false;
}
UpdateRects();
}
private void OnLostFocus()
{
Dispose();
}
/// <summary>
/// Contains helper proxy windows shared across docking panels. They are used to visualize docking window locations.
/// </summary>
public static class Proxy
{
/// <summary>
/// The drag proxy window.
/// </summary>
public static Window Window;
/// <summary>
/// The left hint proxy window.
/// </summary>
public static Window Left;
/// <summary>
/// The right hint proxy window.
/// </summary>
public static Window Right;
/// <summary>
/// The up hint proxy window.
/// </summary>
public static Window Up;
/// <summary>
/// The down hint proxy window.
/// </summary>
public static Window Down;
/// <summary>
/// The center hint proxy window.
/// </summary>
public static Window Center;
/// <summary>
/// The hint windows size.
/// </summary>
public const float HintWindowsSize = 32.0f;
/// <summary>
/// Initializes the hit proxy windows. Those windows are used to indicate drag target areas (left, right, top, bottom, etc.).
/// </summary>
public static void InitHitProxy()
{
CreateProxy(ref Left, "DockHint.Left");
CreateProxy(ref Right, "DockHint.Right");
CreateProxy(ref Up, "DockHint.Up");
CreateProxy(ref Down, "DockHint.Down");
CreateProxy(ref Center, "DockHint.Center");
}
/// <summary>
/// Initializes the hint window.
/// </summary>
/// <param name="initSize">Initial size of the proxy window.</param>
public static void Init(ref Float2 initSize)
{
if (Window == null)
{
var settings = CreateWindowSettings.Default;
settings.Title = "DockHint.Window";
settings.Size = initSize;
settings.AllowInput = true;
settings.AllowMaximize = false;
settings.AllowMinimize = false;
settings.HasBorder = false;
settings.HasSizingFrame = false;
settings.Type = WindowType.Utility;
settings.SupportsTransparency = true;
settings.ShowInTaskbar = false;
settings.ShowAfterFirstPaint = false;
settings.IsTopmost = true;
Window = Platform.CreateWindow(ref settings);
Window.Opacity = 0.6f;
Window.GUI.BackgroundColor = Style.Current.DragWindow;
}
else
{
// Resize proxy
Window.ClientSize = initSize;
}
InitHitProxy();
}
private static void CreateProxy(ref Window win, string name)
{
if (win != null)
return;
var settings = CreateWindowSettings.Default;
settings.Title = name;
settings.Size = new Float2(HintWindowsSize * Platform.DpiScale);
settings.AllowInput = false;
settings.AllowMaximize = false;
settings.AllowMinimize = false;
settings.HasBorder = false;
settings.HasSizingFrame = false;
settings.Type = WindowType.Utility;
settings.SupportsTransparency = true;
settings.ShowInTaskbar = false;
settings.ActivateWhenFirstShown = false;
settings.IsTopmost = true;
settings.ShowAfterFirstPaint = false;
win = Platform.CreateWindow(ref settings);
win.Opacity = 0.6f;
win.GUI.BackgroundColor = Style.Current.DragWindow;
}
/// <summary>
/// Hides proxy windows.
/// </summary>
public static void Hide()
{
HideProxy(ref Window);
HideProxy(ref Left);
HideProxy(ref Right);
HideProxy(ref Up);
HideProxy(ref Down);
HideProxy(ref Center);
}
private static void HideProxy(ref Window win)
{
if (win)
{
win.Hide();
}
}
/// <summary>
/// Releases proxy data and windows.
/// </summary>
public static void Dispose()
{
DisposeProxy(ref Window);
DisposeProxy(ref Left);
DisposeProxy(ref Right);
DisposeProxy(ref Up);
DisposeProxy(ref Down);
DisposeProxy(ref Center);
}
private static void DisposeProxy(ref Window win)
{
if (win)
{
win.Close(ClosingReason.User);
win = null;
}
}
}
}
}

View File

@@ -49,11 +49,6 @@ namespace FlaxEditor.GUI.Docking
/// The mouse position.
/// </summary>
public Float2 MousePosition = Float2.Minimum;
/// <summary>
/// The mouse position.
/// </summary>
public Float2 MouseStartPosition = Float2.Minimum;
/// <summary>
/// The start drag asynchronous window.
@@ -170,7 +165,7 @@ namespace FlaxEditor.GUI.Docking
if (_panel.ChildPanelsCount == 0 && _panel.TabsCount == 1 && _panel.IsFloating)
{
// Create docking hint window but in an async manner
WindowDragHelper.StartDragging(_panel as FloatWindowDockPanel);
DockHintWindow.Create(_panel as FloatWindowDockPanel);
}
else
{
@@ -181,7 +176,7 @@ namespace FlaxEditor.GUI.Docking
_panel.SelectTab(index - 1);
// Create docking hint window
WindowDragHelper.StartDragging(win, _panel.RootWindow.Window);
DockHintWindow.Create(win);
}
}
}
@@ -360,7 +355,6 @@ namespace FlaxEditor.GUI.Docking
if (IsSingleFloatingWindow)
return base.OnMouseDown(location, button);
MouseDownWindow = GetTabAtPos(location, out IsMouseDownOverCross);
MouseStartPosition = location;
// Check buttons
if (button == MouseButton.Left)
@@ -447,20 +441,6 @@ namespace FlaxEditor.GUI.Docking
StartDrag(MouseDownWindow);
MouseDownWindow = null;
}
// Check if single tab is tried to be moved
else if (MouseDownWindow != null && _panel.TabsCount <= 1)
{
if ((MousePosition - MouseStartPosition).Length > 3)
{
// Clear flag
IsMouseLeftButtonDown = false;
// Check tab under the mouse
if (!IsMouseDownOverCross && MouseDownWindow != null)
StartDrag(MouseDownWindow);
MouseDownWindow = null;
}
}
// Check if has more than one tab to change order
else if (MouseDownWindow != null && _panel.TabsCount > 1)
{

View File

@@ -182,25 +182,6 @@ namespace FlaxEditor.GUI.Docking
/// <param name="size">Window size, set <see cref="Float2.Zero"/> to use default.</param>
/// <param name="position">Window location.</param>
public void ShowFloating(Float2 location, Float2 size, WindowStartPosition position = WindowStartPosition.CenterParent)
{
CreateFloating(location, size, position, true);
}
/// <summary>
/// Creates the window in a floating state.
/// </summary>
public void CreateFloating()
{
CreateFloating(Float2.Zero, Float2.Zero);
}
/// <summary>
/// Creates the window in a floating state.
/// </summary>
/// <param name="location">Window location.</param>
/// <param name="size">Window size, set <see cref="Float2.Zero"/> to use default.</param>
/// <param name="position">Window location.</param>
/// <param name="showWindow">Window visibility.</param>
public void CreateFloating(Float2 location, Float2 size, WindowStartPosition position = WindowStartPosition.CenterParent, bool showWindow = false)
{
Undock();
@@ -218,17 +199,14 @@ namespace FlaxEditor.GUI.Docking
windowGUI.UnlockChildrenRecursive();
windowGUI.PerformLayout();
if (showWindow)
{
// Show
window.Show();
window.BringToFront();
window.Focus();
OnShow();
// Show
window.Show();
window.BringToFront();
window.Focus();
OnShow();
// Perform layout again
windowGUI.PerformLayout();
}
// Perform layout again
windowGUI.PerformLayout();
}
/// <summary>
@@ -486,7 +464,7 @@ namespace FlaxEditor.GUI.Docking
{
base.Focus();
SelectTab(false);
SelectTab();
BringToFront();
}

View File

@@ -52,7 +52,7 @@ namespace FlaxEditor.GUI.Docking
return;
// Create docking hint window
WindowDragHelper.StartDragging(this);
DockHintWindow.Create(this);
}
/// <summary>
@@ -75,7 +75,7 @@ namespace FlaxEditor.GUI.Docking
settings.MaximumSize = Float2.Zero; // Unlimited size
settings.Fullscreen = false;
settings.HasBorder = true;
settings.SupportsTransparency = true;
settings.SupportsTransparency = false;
settings.ActivateWhenFirstShown = true;
settings.AllowInput = true;
settings.AllowMinimize = true;

View File

@@ -81,6 +81,7 @@ namespace FlaxEditor.GUI.Docking
public DockPanel HitTest(ref Float2 position, FloatWindowDockPanel excluded)
{
// Check all floating windows
// TODO: gather windows order and take it into account when performing test
for (int i = 0; i < FloatingPanels.Count; i++)
{
var win = FloatingPanels[i];
@@ -93,44 +94,9 @@ namespace FlaxEditor.GUI.Docking
}
// Base
//if (!Root?.RootWindow.Window.IsFocused ?? false)
// return null;
return base.HitTest(ref position);
}
/// <summary>
/// Performs hit test over dock panel.
/// </summary>
/// <param name="position">Window space position to test.</param>
/// <param name="excluded">Floating window to omit during searching (and all docked to that one).</param>
/// <param name="hitResults">Results of the hit test</param>
/// <returns>True if any dock panels were hit, otherwise false.</returns>
public bool HitTest(ref Float2 position, FloatWindowDockPanel excluded, out DockPanel[] hitResults)
{
// Check all floating windows
List<DockPanel> results = new(FloatingPanels.Count);
for (int i = 0; i < FloatingPanels.Count; i++)
{
var win = FloatingPanels[i];
if (win.Visible && win != excluded)
{
var result = win.HitTest(ref position);
if (result != null)
results.Add(result);
}
}
// Base
//if (!Root?.RootWindow.Window.IsFocused ?? false)
// return null;
var baseResult = base.HitTest(ref position);
if (baseResult != null)
results.Add(baseResult);
hitResults = results.ToArray();
return hitResults.Length > 0;
}
internal void LinkWindow(DockWindow window)
{
// Add to the windows list

View File

@@ -1,448 +0,0 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.GUI.Docking
{
/// <summary>
/// Helper class used to handle docking windows dragging and docking.
/// </summary>
public class WindowDragHelper
{
private FloatWindowDockPanel _toMove;
private Float2 _dragOffset;
private Rectangle _rectDock;
private Float2 _mouse;
private DockState _toSet;
private DockPanel _toDock;
private Window _dragSourceWindow;
private Rectangle _rLeft, _rRight, _rBottom, _rUpper, _rCenter;
private Control _dockHintDown, _dockHintUp, _dockHintLeft, _dockHintRight, _dockHintCenter;
/// <summary>
/// The hint control size.
/// </summary>
public const float HintControlSize = 32.0f;
/// <summary>
/// The opacity of the dragged window when hint controls are shown.
/// </summary>
public const float DragWindowOpacity = 0.4f;
private WindowDragHelper(FloatWindowDockPanel toMove, Window dragSourceWindow)
{
_toMove = toMove;
_toSet = DockState.Float;
var window = toMove.Window.Window;
// Check if window is maximized and restore window.
if (window.IsMaximized)
{
// Restore window and set position to mouse.
var mousePos = window.MousePosition;
var previousSize = window.Size;
window.Restore();
window.Position = Platform.MousePosition - mousePos * window.Size / previousSize;
}
// Bind events
FlaxEngine.Scripting.Update += OnUpdate;
window.MouseUp += OnMouseUp;
// Update rectangles
UpdateRects(Platform.MousePosition);
_dragSourceWindow = dragSourceWindow;
if (_dragSourceWindow != null) // Detaching a tab from existing window
{
_dragOffset = new Float2(window.Size.X / 2, 10.0f);
// TODO: when detaching tab in floating window (not main window), the drag source window is still main window?
var dragSourceWindowWayland = toMove.MasterPanel?.RootWindow.Window ?? Editor.Instance.Windows.MainWindow;
window.DoDragDrop(window.Title, _dragOffset, dragSourceWindowWayland);
_dragSourceWindow.MouseUp += OnMouseUp; // The mouse up event is sent to the source window on Windows
}
else
{
_dragOffset = window.MousePosition;
window.DoDragDrop(window.Title, _dragOffset, window);
}
// Ensure the dragged window stays on top of every other window
window.IsAlwaysOnTop = true;
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
public void Dispose()
{
var window = _toMove?.Window?.Window;
// Unbind events
FlaxEngine.Scripting.Update -= OnUpdate;
if (window != null)
window.MouseUp -= OnMouseUp;
if (_dragSourceWindow != null)
_dragSourceWindow.MouseUp -= OnMouseUp;
RemoveDockHints();
if (_toMove == null)
return;
if (window != null)
{
window.Opacity = 1.0f;
window.IsAlwaysOnTop = false;
window.BringToFront();
}
// Check if window won't be docked
if (_toSet == DockState.Float)
{
if (window == null)
return;
// Show base window
window.Show();
}
else
{
bool hasNoChildPanels = _toMove.ChildPanelsCount == 0;
// Check if window has only single tab
if (hasNoChildPanels && _toMove.TabsCount == 1)
{
// Dock window
_toMove.GetTab(0).Show(_toSet, _toDock);
}
// Check if dock as tab and has no child panels
else if (hasNoChildPanels && _toSet == DockState.DockFill)
{
// Dock all tabs
while (_toMove.TabsCount > 0)
{
_toMove.GetTab(0).Show(DockState.DockFill, _toDock);
}
}
else
{
var selectedTab = _toMove.SelectedTab;
// Dock the first tab into the target location
if (_toMove.TabsCount > 0)
{
var firstTab = _toMove.GetTab(0);
firstTab.Show(_toSet, _toDock);
// Dock rest of the tabs
while (_toMove.TabsCount > 0)
{
_toMove.GetTab(0).Show(DockState.DockFill, firstTab);
}
}
// Keep selected tab being selected
selectedTab?.SelectTab();
}
// Focus target window
_toDock.Root.Focus();
}
_toMove = null;
}
/// <summary>
/// Start dragging a floating dock panel.
/// </summary>
/// <param name="toMove">Floating dock panel to move.</param>
/// <returns>The window drag helper object.</returns>
public static WindowDragHelper StartDragging(FloatWindowDockPanel toMove)
{
if (toMove == null)
throw new ArgumentNullException();
return new WindowDragHelper(toMove, null);
}
/// <summary>
/// Start dragging a docked panel into a floating window.
/// </summary>
/// <param name="toMove">Dock window to move.</param>
/// <param name="dragSourceWindow">The window where dragging started from.</param>
/// <returns>The window drag helper object.</returns>
public static WindowDragHelper StartDragging(DockWindow toMove, Window dragSourceWindow)
{
if (toMove == null)
throw new ArgumentNullException();
// Create floating window
toMove.CreateFloating();
// Get floating panel
var window = (WindowRootControl)toMove.Root;
var floatingPanelToMove = window.GetChild(0) as FloatWindowDockPanel;
return new WindowDragHelper(floatingPanelToMove, dragSourceWindow);
}
private void AddDockHints()
{
if (_toDock == null)
return;
if (_toDock.RootWindow.Window != _dragSourceWindow)
_toDock.RootWindow.Window.MouseUp += OnMouseUp;
_dockHintDown = AddHintControl(new Float2(0.5f, 1));
_dockHintUp = AddHintControl(new Float2(0.5f, 0));
_dockHintLeft = AddHintControl(new Float2(0, 0.5f));
_dockHintRight = AddHintControl(new Float2(1, 0.5f));
_dockHintCenter = AddHintControl(new Float2(0.5f, 0.5f));
Control AddHintControl(Float2 pivot)
{
Control hintControl = _toDock.AddChild<Control>();
hintControl.AnchorPreset = AnchorPresets.StretchAll;
hintControl.Offsets = Margin.Zero;
hintControl.Size = new Float2(HintControlSize);
hintControl.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
hintControl.Pivot = pivot;
hintControl.PivotRelative = true;
return hintControl;
}
}
private void RemoveDockHints()
{
if (_toDock == null)
return;
if (_toDock.RootWindow.Window != _dragSourceWindow)
_toDock.RootWindow.Window.MouseUp -= OnMouseUp;
_dockHintDown?.Parent.RemoveChild(_dockHintDown);
_dockHintUp?.Parent.RemoveChild(_dockHintUp);
_dockHintLeft?.Parent.RemoveChild(_dockHintLeft);
_dockHintRight?.Parent.RemoveChild(_dockHintRight);
_dockHintCenter?.Parent.RemoveChild(_dockHintCenter);
_dockHintDown = _dockHintUp = _dockHintLeft = _dockHintRight = _dockHintCenter = null;
}
private void UpdateRects(Float2 mousePos)
{
// Cache mouse position
_mouse = mousePos;
// Check intersection with any dock panel
DockPanel dockPanel = null;
if (_toMove.MasterPanel.HitTest(ref _mouse, _toMove, out var hitResults))
{
dockPanel = hitResults[0];
// Prefer panel which currently has focus
foreach (var hit in hitResults)
{
if (hit.RootWindow.Window.IsFocused)
{
dockPanel = hit;
break;
}
}
// Prefer panel in the same window we hit earlier
if (dockPanel?.RootWindow != _toDock?.RootWindow)
{
foreach (var hit in hitResults)
{
if (hit.RootWindow == _toDock?.RootWindow)
{
dockPanel = _toDock;
break;
}
}
}
}
if (dockPanel != _toDock)
{
RemoveDockHints();
_toDock = dockPanel;
AddDockHints();
// Make sure the all the dock hint areas are not under other windows
_toDock?.RootWindow.Window.BringToFront();
//_toDock?.RootWindow.Window.Focus();
// Make the dragged window transparent when dock hints are visible
_toMove.Window.Window.Opacity = _toDock == null ? 1.0f : DragWindowOpacity;
}
// Check dock state to use
bool showProxyHints = _toDock != null;
bool showBorderHints = showProxyHints;
bool showCenterHint = showProxyHints;
Control hoveredHintControl = null;
Float2 hoveredSizeOverride = Float2.Zero;
if (showProxyHints)
{
// If moved window has not only tabs but also child panels disable docking as tab
if (_toMove.ChildPanelsCount > 0)
showCenterHint = false;
// Disable docking windows with one or more dock panels inside
if (_toMove.ChildPanelsCount > 0)
showBorderHints = false;
// Get dock area
_rectDock = _toDock.DockAreaBounds;
// Cache dock rectangles
var size = _rectDock.Size / Platform.DpiScale;
var offset = _toDock.PointFromScreen(_rectDock.Location);
var borderMargin = 4.0f;
var hintWindowsSize = HintControlSize;
var hintWindowsSize2 = hintWindowsSize * 0.5f;
var hintPreviewSize = new Float2(Math.Max(HintControlSize * 2, size.X * 0.5f), Math.Max(HintControlSize * 2, size.Y * 0.5f));
var centerX = size.X * 0.5f;
var centerY = size.Y * 0.5f;
_rUpper = new Rectangle(centerX - hintWindowsSize2, borderMargin, hintWindowsSize, hintWindowsSize) + offset;
_rBottom = new Rectangle(centerX - hintWindowsSize2, size.Y - hintWindowsSize - borderMargin, hintWindowsSize, hintWindowsSize) + offset;
_rLeft = new Rectangle(borderMargin, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
_rRight = new Rectangle(size.X - hintWindowsSize - borderMargin, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
_rCenter = new Rectangle(centerX - hintWindowsSize2, centerY - hintWindowsSize2, hintWindowsSize, hintWindowsSize) + offset;
// Hit test, and calculate the approximation for filled area when hovered over the hint
DockState toSet = DockState.Float;
if (showBorderHints)
{
if (_rUpper.Contains(_toDock.PointFromScreen(_mouse)))
{
toSet = DockState.DockTop;
hoveredHintControl = _dockHintUp;
hoveredSizeOverride = new Float2(size.X, hintPreviewSize.Y);
}
else if (_rBottom.Contains(_toDock.PointFromScreen(_mouse)))
{
toSet = DockState.DockBottom;
hoveredHintControl = _dockHintDown;
hoveredSizeOverride = new Float2(size.X, hintPreviewSize.Y);
}
else if (_rLeft.Contains(_toDock.PointFromScreen(_mouse)))
{
toSet = DockState.DockLeft;
hoveredHintControl = _dockHintLeft;
hoveredSizeOverride = new Float2(hintPreviewSize.X, size.Y);
}
else if (_rRight.Contains(_toDock.PointFromScreen(_mouse)))
{
toSet = DockState.DockRight;
hoveredHintControl = _dockHintRight;
hoveredSizeOverride = new Float2(hintPreviewSize.X, size.Y);
}
}
if (showCenterHint && _rCenter.Contains(_toDock.PointFromScreen(_mouse)))
{
toSet = DockState.DockFill;
hoveredHintControl = _dockHintCenter;
hoveredSizeOverride = new Float2(size.X, size.Y);
}
_toSet = toSet;
}
else
{
_toSet = DockState.Float;
}
// Update sizes and opacity of hint controls
if (_toDock != null)
{
if (hoveredHintControl != _dockHintDown)
{
_dockHintDown.Size = new Float2(HintControlSize);
_dockHintDown.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
}
if (hoveredHintControl != _dockHintLeft)
{
_dockHintLeft.Size = new Float2(HintControlSize);
_dockHintLeft.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
}
if (hoveredHintControl != _dockHintRight)
{
_dockHintRight.Size = new Float2(HintControlSize);
_dockHintRight.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
}
if (hoveredHintControl != _dockHintUp)
{
_dockHintUp.Size = new Float2(HintControlSize);
_dockHintUp.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
}
if (hoveredHintControl != _dockHintCenter)
{
_dockHintCenter.Size = new Float2(HintControlSize);
_dockHintCenter.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(0.6f);
}
if (_toSet != DockState.Float)
{
if (hoveredHintControl != null)
{
hoveredHintControl.BackgroundColor = Style.Current.DragWindow.AlphaMultiplied(1.0f);
hoveredHintControl.Size = hoveredSizeOverride;
}
}
}
// Update hint controls visibility and location
if (showProxyHints)
{
if (hoveredHintControl != _dockHintDown)
_dockHintDown.Location = _rBottom.Location;
if (hoveredHintControl != _dockHintLeft)
_dockHintLeft.Location = _rLeft.Location;
if (hoveredHintControl != _dockHintRight)
_dockHintRight.Location = _rRight.Location;
if (hoveredHintControl != _dockHintUp)
_dockHintUp.Location = _rUpper.Location;
if (hoveredHintControl != _dockHintCenter)
_dockHintCenter.Location = _rCenter.Location;
_dockHintDown.Visible = showProxyHints & showBorderHints;
_dockHintLeft.Visible = showProxyHints & showBorderHints;
_dockHintRight.Visible = showProxyHints & showBorderHints;
_dockHintUp.Visible = showProxyHints & showBorderHints;
_dockHintCenter.Visible = showProxyHints & showCenterHint;
}
}
private void OnMouseUp(ref Float2 location, MouseButton button, ref bool handled)
{
if (button == MouseButton.Left)
Dispose();
}
private void OnUpdate()
{
var mousePos = Platform.MousePosition;
if (_mouse != mousePos)
OnMouseMove(mousePos);
}
private void OnMouseMove(Float2 mousePos)
{
if (_dragSourceWindow != null)
_toMove.Window.Window.Position = mousePos - _dragOffset;
UpdateRects(mousePos);
}
}
}

View File

@@ -328,10 +328,8 @@ namespace FlaxEditor.GUI.Input
{
if (button == MouseButton.Left && _isSliding)
{
#if !PLATFORM_SDL
// End sliding and return mouse to original location
RootWindow.MousePosition = _mouseClickedPosition;
#endif
EndSliding();
return true;
}

View File

@@ -84,15 +84,13 @@ namespace FlaxEditor.GUI
ScriptsBuilder.GetBinariesConfiguration(out _, out _, out _, out var configuration);
var driver = Platform.DisplayServer;
_icon = new Image
{
Margin = new Margin(6, 6, 6, 6),
Brush = new TextureBrush(windowIcon),
Color = Style.Current.Foreground,
KeepAspectRatio = false,
TooltipText = string.Format("{0}\nVersion {1}\nConfiguration {3}\nGraphics {2} {4}", _window.Title, Globals.EngineVersion, GPUDevice.Instance.RendererType, configuration, driver),
TooltipText = string.Format("{0}\nVersion {1}\nConfiguration {3}\nGraphics {2}", _window.Title, Globals.EngineVersion, GPUDevice.Instance.RendererType, configuration),
Parent = this,
};

View File

@@ -1,8 +1,6 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -57,26 +55,18 @@ namespace FlaxEditor.GUI
private IsValidDelegate _isValid;
private Action<Actor> _selected;
private ActorSearchPopup(IsValidDelegate isValid, Action<Actor> selected, CustomEditors.IPresenterOwner context)
private ActorSearchPopup(IsValidDelegate isValid, Action<Actor> selected)
{
_isValid = isValid;
_selected = selected;
ItemClicked += OnItemClicked;
if (context is PropertiesWindow propertiesWindow || context == null)
// TODO: use async thread to search scenes
for (int i = 0; i < Level.ScenesCount; i++)
{
// TODO: use async thread to search scenes
for (int i = 0; i < Level.ScenesCount; i++)
{
Find(Level.GetScene(i));
}
Find(Level.GetScene(i));
}
else if (context is PrefabWindow prefabWindow)
{
Find(prefabWindow.Graph.MainActor);
}
SortItems();
}
@@ -108,11 +98,10 @@ namespace FlaxEditor.GUI
/// <param name="showTargetLocation">The show target location.</param>
/// <param name="isValid">Event called to check if a given actor item is valid to be used.</param>
/// <param name="selected">Event called on actor item pick.</param>
/// <param name="context">The presenter owner context (i.e. PrefabWindow, PropertiesWindow).</param>
/// <returns>The dialog.</returns>
public static ActorSearchPopup Show(Control showTarget, Float2 showTargetLocation, IsValidDelegate isValid, Action<Actor> selected, CustomEditors.IPresenterOwner context)
public static ActorSearchPopup Show(Control showTarget, Float2 showTargetLocation, IsValidDelegate isValid, Action<Actor> selected)
{
var popup = new ActorSearchPopup(isValid, selected, context);
var popup = new ActorSearchPopup(isValid, selected);
popup.Show(showTarget, showTargetLocation);
return popup;
}

View File

@@ -1,8 +1,6 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Utilities;
@@ -68,26 +66,18 @@ namespace FlaxEditor.GUI
private IsValidDelegate _isValid;
private Action<Script> _selected;
private ScriptSearchPopup(IsValidDelegate isValid, Action<Script> selected, CustomEditors.IPresenterOwner context)
private ScriptSearchPopup(IsValidDelegate isValid, Action<Script> selected)
{
_isValid = isValid;
_selected = selected;
ItemClicked += OnItemClicked;
if (context is PropertiesWindow propertiesWindow || context == null)
// TODO: use async thread to search scenes
for (int i = 0; i < Level.ScenesCount; i++)
{
// TODO: use async thread to search scenes
for (int i = 0; i < Level.ScenesCount; i++)
{
Find(Level.GetScene(i));
}
Find(Level.GetScene(i));
}
else if (context is PrefabWindow prefabWindow)
{
Find(prefabWindow.Graph.MainActor);
}
SortItems();
}
@@ -123,11 +113,10 @@ namespace FlaxEditor.GUI
/// <param name="showTargetLocation">The show target location.</param>
/// <param name="isValid">Event called to check if a given script item is valid to be used.</param>
/// <param name="selected">Event called on script item pick.</param>
/// <param name="context">The presenter owner context (i.e. PrefabWindow, PropertiesWindow).</param>
/// <returns>The dialog.</returns>
public static ScriptSearchPopup Show(Control showTarget, Float2 showTargetLocation, IsValidDelegate isValid, Action<Script> selected, CustomEditors.IPresenterOwner context)
public static ScriptSearchPopup Show(Control showTarget, Float2 showTargetLocation, IsValidDelegate isValid, Action<Script> selected)
{
var popup = new ScriptSearchPopup(isValid, selected, context);
var popup = new ScriptSearchPopup(isValid, selected);
popup.Show(showTarget, showTargetLocation);
return popup;
}

View File

@@ -1,13 +1,10 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using System.ComponentModel;
using System.Linq;
using FlaxEditor.History;
using FlaxEditor.Scripting;
using FlaxEngine;
using FlaxEngine.GUI;
using CategoryAttribute = FlaxEngine.CategoryAttribute;
namespace FlaxEditor.GUI
{
@@ -104,26 +101,11 @@ namespace FlaxEditor.GUI
if (_isValid(type))
{
var attributes = type.GetAttributes(true);
if (IsHideAttributes(attributes))
if (attributes.FirstOrDefault(x => x is HideInEditorAttribute || x is System.Runtime.CompilerServices.CompilerGeneratedAttribute) == null)
{
var mType = type.Type;
if (mType != null)
{
// Skip if type is compiler-generated
if (mType.IsValueType && mType.ReflectedType != null && string.Equals(mType.ReflectedType.Name, "<PrivateImplementationDetails>", StringComparison.Ordinal))
continue;
// Skip if outer type is hidden
if (mType.DeclaringType != null && IsHideAttributes(mType.DeclaringType.GetCustomAttributes(true)))
continue;
// Blacklist some types
if (typeof(TypeConverter).IsAssignableFrom(mType) ||
typeof(IHistoryAction).IsAssignableFrom(mType) ||
(mType.Namespace != null && mType.Namespace.StartsWith("Newtonsoft.Json")))
continue;
}
if (mType != null && mType.IsValueType && mType.ReflectedType != null && string.Equals(mType.ReflectedType.Name, "<PrivateImplementationDetails>", StringComparison.Ordinal))
continue;
AddItem(new TypeItemView(type, attributes));
}
}
@@ -131,17 +113,6 @@ namespace FlaxEditor.GUI
SortItems();
}
private bool IsHideAttributes(object[] attributes)
{
return attributes.FirstOrDefault(IsHideAttribute) == null;
}
private bool IsHideAttribute(object attr)
{
return attr is HideInEditorAttribute ||
attr is System.Runtime.CompilerServices.CompilerGeneratedAttribute;
}
private void OnItemClicked(Item item)
{
_selected(((TypeItemView)item).Type);

View File

@@ -14,7 +14,7 @@ namespace FlaxEditor.GUI.Timeline.GUI
class Background : ContainerControl
{
private readonly Timeline _timeline;
private double[] _tickSteps;
private float[] _tickSteps;
private float[] _tickStrengths;
private bool _isSelecting;
private Float2 _selectingStartPos = Float2.Minimum;
@@ -176,9 +176,9 @@ namespace FlaxEditor.GUI.Timeline.GUI
// Draw vertical lines for time axis
var pixelsInRange = _timeline.Zoom;
var pixelRange = pixelsInRange * (max - min);
var tickRange = Utilities.Utils.DrawCurveTicks((decimal tick, double step, float strength) =>
var tickRange = Utilities.Utils.DrawCurveTicks((float tick, float strength) =>
{
var time = (float)tick / _timeline.FramesPerSecond;
var time = tick / _timeline.FramesPerSecond;
var x = time * zoom + Timeline.StartOffset;
var lineColor = style.ForegroundDisabled.RGBMultiplied(0.7f).AlphaMultiplied(strength);
Render2D.FillRectangle(new Rectangle(x - 0.5f, 0, 1.0f, height), lineColor);
@@ -233,20 +233,20 @@ namespace FlaxEditor.GUI.Timeline.GUI
int l = Mathf.Clamp(smallestTick + level, 0, _tickSteps.Length - 2);
var lStep = _tickSteps[l];
var lNextStep = _tickSteps[l + 1];
var startTick = Mathd.FloorToInt(min / lStep);
var endTick = Mathd.CeilToInt(max / lStep);
int startTick = Mathf.FloorToInt(min / lStep);
int endTick = Mathf.CeilToInt(max / lStep);
Color lineColor = style.Foreground.RGBMultiplied(0.8f).AlphaMultiplied(strength);
Color labelColor = style.ForegroundDisabled.AlphaMultiplied(strength);
for (var i = startTick; i <= endTick; i++)
for (int i = startTick; i <= endTick; i++)
{
if (l < biggestTick && (i % Mathd.RoundToInt(lNextStep / lStep) == 0))
if (l < biggestTick && (i % Mathf.RoundToInt(lNextStep / lStep) == 0))
continue;
var tick = (decimal)lStep * i;
var time = (double)tick / _timeline.FramesPerSecond;
var x = (float)time * zoom + Timeline.StartOffset;
var tick = i * lStep;
var time = tick / _timeline.FramesPerSecond;
var x = time * zoom + Timeline.StartOffset;
// Header line
var lineRect = new Rectangle((float)x - 0.5f, -verticalLinesHeaderExtend * 0.6f + timeAxisHeaderOffset, 1.0f, verticalLinesHeaderExtend * 0.6f);
var lineRect = new Rectangle(x - 0.5f, -verticalLinesHeaderExtend * 0.6f + timeAxisHeaderOffset, 1.0f, verticalLinesHeaderExtend * 0.6f);
Render2D.FillRectangle(lineRect, lineColor);
// Time label

View File

@@ -8,6 +8,7 @@ using System.Text;
using FlaxEditor.CustomEditors;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.Options;
using FlaxEditor.Scripting;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Json;

View File

@@ -264,7 +264,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
private void OnClickedSelect()
{
ActorSearchPopup.Show(this, PointFromScreen(FlaxEngine.Input.MouseScreenPosition), IsActorValid, SetActor, null);
ActorSearchPopup.Show(this, PointFromScreen(FlaxEngine.Input.MouseScreenPosition), IsActorValid, SetActor);
}
private void OnClickedSelectActor(Image image, MouseButton button)

View File

@@ -19,11 +19,12 @@ namespace FlaxEditor.Gizmo
[StructLayout(LayoutKind.Sequential)]
private struct Data
{
public Matrix WorldMatrix;
public Matrix ViewProjectionMatrix;
public Float4 GridColor;
public Float3 ViewPos;
public float Far;
public Float3 ViewOrigin;
public Float3 Padding;
public float GridSize;
}
@@ -43,7 +44,6 @@ namespace FlaxEditor.Gizmo
{
UseSingleTarget = true;
Location = PostProcessEffectLocation.Default;
Order = -100000; // Draw before any other editor shapes
_shader = FlaxEngine.Content.LoadAsyncInternal<Shader>("Shaders/Editor/Grid");
}
@@ -62,6 +62,7 @@ namespace FlaxEditor.Gizmo
Profiler.BeginEventGPU("Editor Grid");
var options = Editor.Instance.Options.Options;
Float3 camPos = renderContext.View.WorldPosition;
float gridSize = renderContext.View.Far + 20000;
// Lazy-init resources
@@ -96,10 +97,10 @@ namespace FlaxEditor.Gizmo
float y = 1.5f; // Add small bias to reduce Z-fighting with geometry at scene origin
var vertices = new Float3[]
{
new Float3(-gridSize, y, -gridSize),
new Float3(gridSize, y, gridSize),
new Float3(-gridSize, y, gridSize),
new Float3(gridSize, y, -gridSize),
new Float3(-gridSize + camPos.X, y, -gridSize + camPos.Z),
new Float3(gridSize + camPos.X, y, gridSize + camPos.Z),
new Float3(-gridSize + camPos.X, y, gridSize + camPos.Z),
new Float3(gridSize + camPos.X, y, -gridSize + camPos.Z),
};
fixed (Float3* ptr = vertices)
{
@@ -112,12 +113,12 @@ namespace FlaxEditor.Gizmo
{
var data = new Data();
Matrix.Multiply(ref renderContext.View.View, ref renderContext.View.Projection, out var viewProjection);
data.WorldMatrix = Matrix.Identity;
Matrix.Transpose(ref viewProjection, out data.ViewProjectionMatrix);
data.ViewPos = renderContext.View.WorldPosition;
data.GridColor = options.Viewport.ViewportGridColor;
data.Far = renderContext.View.Far;
data.GridSize = options.Viewport.ViewportGridViewDistance;
data.ViewOrigin = renderContext.View.Origin;
context.UpdateCB(cb, new IntPtr(&data));
}

View File

@@ -85,8 +85,6 @@ namespace FlaxEditor.Gizmo
/// </summary>
public SelectionOutline()
{
Order = -90000; // Draw before any other editor shapes (except grid gizmo)
_outlineMaterial = FlaxEngine.Content.LoadAsyncInternal<Material>("Editor/Gizmo/SelectionOutlineMaterial");
if (_outlineMaterial)
{

View File

@@ -115,7 +115,6 @@ namespace FlaxEditor.Gizmo
bool isCenter = _activeAxis == Axis.Center;
renderContext.View.GetWorldMatrix(ref _gizmoWorld, out Matrix world);
const sbyte sortOrder = 100; // Draw after any other editor shapes
const float gizmoModelsScale2RealGizmoSize = 0.075f;
Mesh cubeMesh = _modelCube.LODs[0].Meshes[0];
Mesh sphereMesh = _modelSphere.LODs[0].Meshes[0];
@@ -137,42 +136,42 @@ namespace FlaxEditor.Gizmo
Matrix.RotationY(-Mathf.PiOverTwo, out m2);
Matrix.Multiply(ref m2, ref m1, out m3);
MaterialInstance xAxisMaterialTransform = gizmoLocked ? _materialAxisLocked : (isXAxis ? _materialAxisFocus : _materialAxisX);
transAxisMesh.Draw(ref renderContext, xAxisMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
transAxisMesh.Draw(ref renderContext, xAxisMaterialTransform, ref m3);
// Y axis
Matrix.RotationX(Mathf.PiOverTwo, out m2);
Matrix.Multiply(ref m2, ref m1, out m3);
MaterialInstance yAxisMaterialTransform = gizmoLocked ? _materialAxisLocked : (isYAxis ? _materialAxisFocus : _materialAxisY);
transAxisMesh.Draw(ref renderContext, yAxisMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
transAxisMesh.Draw(ref renderContext, yAxisMaterialTransform, ref m3);
// Z axis
Matrix.RotationX(Mathf.Pi, out m2);
Matrix.Multiply(ref m2, ref m1, out m3);
MaterialInstance zAxisMaterialTransform = gizmoLocked ? _materialAxisLocked : (isZAxis ? _materialAxisFocus : _materialAxisZ);
transAxisMesh.Draw(ref renderContext, zAxisMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
transAxisMesh.Draw(ref renderContext, zAxisMaterialTransform, ref m3);
// XY plane
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
Matrix.Multiply(ref m2, ref m1, out m3);
MaterialInstance xyPlaneMaterialTransform = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX);
cubeMesh.Draw(ref renderContext, xyPlaneMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
cubeMesh.Draw(ref renderContext, xyPlaneMaterialTransform, ref m3);
// ZX plane
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
Matrix.Multiply(ref m2, ref m1, out m3);
MaterialInstance zxPlaneMaterialTransform = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisY);
cubeMesh.Draw(ref renderContext, zxPlaneMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
cubeMesh.Draw(ref renderContext, zxPlaneMaterialTransform, ref m3);
// YZ plane
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
Matrix.Multiply(ref m2, ref m1, out m3);
MaterialInstance yzPlaneMaterialTransform = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisZ);
cubeMesh.Draw(ref renderContext, yzPlaneMaterialTransform, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
cubeMesh.Draw(ref renderContext, yzPlaneMaterialTransform, ref m3);
// Center sphere
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
Matrix.Multiply(ref m2, ref m1, out m3);
sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
break;
}
@@ -187,22 +186,22 @@ namespace FlaxEditor.Gizmo
Matrix.RotationZ(Mathf.PiOverTwo, out m2);
Matrix.Multiply(ref m2, ref m1, out m3);
MaterialInstance xAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isXAxis ? _materialAxisFocus : _materialAxisX);
rotationAxisMesh.Draw(ref renderContext, xAxisMaterialRotate, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
rotationAxisMesh.Draw(ref renderContext, xAxisMaterialRotate, ref m3);
// Y axis
MaterialInstance yAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isYAxis ? _materialAxisFocus : _materialAxisY);
rotationAxisMesh.Draw(ref renderContext, yAxisMaterialRotate, ref m1, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
rotationAxisMesh.Draw(ref renderContext, yAxisMaterialRotate, ref m1);
// Z axis
Matrix.RotationX(-Mathf.PiOverTwo, out m2);
Matrix.Multiply(ref m2, ref m1, out m3);
MaterialInstance zAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isZAxis ? _materialAxisFocus : _materialAxisZ);
rotationAxisMesh.Draw(ref renderContext, zAxisMaterialRotate, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
rotationAxisMesh.Draw(ref renderContext, zAxisMaterialRotate, ref m3);
// Center box
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
Matrix.Multiply(ref m2, ref m1, out m3);
sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
break;
}
@@ -217,42 +216,42 @@ namespace FlaxEditor.Gizmo
Matrix.RotationY(-Mathf.PiOverTwo, out m2);
Matrix.Multiply(ref m2, ref mx1, out m3);
MaterialInstance xAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isXAxis ? _materialAxisFocus : _materialAxisX);
scaleAxisMesh.Draw(ref renderContext, xAxisMaterialRotate, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
scaleAxisMesh.Draw(ref renderContext, xAxisMaterialRotate, ref m3);
// Y axis
Matrix.RotationX(Mathf.PiOverTwo, out m2);
Matrix.Multiply(ref m2, ref m1, out m3);
MaterialInstance yAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isYAxis ? _materialAxisFocus : _materialAxisY);
scaleAxisMesh.Draw(ref renderContext, yAxisMaterialRotate, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
scaleAxisMesh.Draw(ref renderContext, yAxisMaterialRotate, ref m3);
// Z axis
Matrix.RotationX(Mathf.Pi, out m2);
Matrix.Multiply(ref m2, ref m1, out m3);
MaterialInstance zAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isZAxis ? _materialAxisFocus : _materialAxisZ);
scaleAxisMesh.Draw(ref renderContext, zAxisMaterialRotate, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
scaleAxisMesh.Draw(ref renderContext, zAxisMaterialRotate, ref m3);
// XY plane
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
Matrix.Multiply(ref m2, ref m1, out m3);
MaterialInstance xyPlaneMaterialScale = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX);
cubeMesh.Draw(ref renderContext, xyPlaneMaterialScale, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
cubeMesh.Draw(ref renderContext, xyPlaneMaterialScale, ref m3);
// ZX plane
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
Matrix.Multiply(ref m2, ref m1, out m3);
MaterialInstance zxPlaneMaterialScale = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisZ);
cubeMesh.Draw(ref renderContext, zxPlaneMaterialScale, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
cubeMesh.Draw(ref renderContext, zxPlaneMaterialScale, ref m3);
// YZ plane
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
Matrix.Multiply(ref m2, ref m1, out m3);
MaterialInstance yzPlaneMaterialScale = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisY);
cubeMesh.Draw(ref renderContext, yzPlaneMaterialScale, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
cubeMesh.Draw(ref renderContext, yzPlaneMaterialScale, ref m3);
// Center box
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
Matrix.Multiply(ref m2, ref m1, out m3);
sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
sphereMesh.Draw(ref renderContext, isCenter ? _materialAxisFocus : _materialSphere, ref m3);
break;
}
@@ -264,7 +263,7 @@ namespace FlaxEditor.Gizmo
Transform t = _vertexSnapObject?.Transform ?? _vertexSnapObjectTo.Transform;
Vector3 p = t.LocalToWorld(_vertexSnapObject != null ? _vertexSnapPoint : _vertexSnapPointTo);
Matrix matrix = new Transform(p, t.Orientation, new Float3(gizmoModelsScale2RealGizmoSize)).GetWorld();
cubeMesh.Draw(ref renderContext, _materialSphere, ref matrix, StaticFlags.None, true, DrawPass.Default, 0.0f, sortOrder);
cubeMesh.Draw(ref renderContext, _materialSphere, ref matrix);
}
}
}

View File

@@ -169,12 +169,12 @@ namespace FlaxEditor.Gizmo
closestIntersection = intersection;
}
// Center
if (CenterBoxRaw.Intersects(ref localRay, out intersection) && intersection > closestIntersection)
/*// Center
if (CenterBoxRaw.Intersects(ref localRay, out intersection) && intersection < closestIntersection)
{
_activeAxis = Axis.Center;
closestIntersection = intersection;
}
}*/
break;
}

View File

@@ -20,7 +20,7 @@ namespace FlaxEditor.Gizmo
/// <summary>
/// Offset to move axis away from center
/// </summary>
private const float AxisOffset = 1.2f;
private const float AxisOffset = 0.8f;
/// <summary>
/// How thick the axis should be

View File

@@ -501,7 +501,7 @@ namespace FlaxEditor.Gizmo
_scaleDelta = Vector3.Zero;
if (ActiveAxis == Axis.Center)
scaleDelta = new Vector3(scaleDelta.ValuesSum);
scaleDelta = new Vector3(scaleDelta.AvgValue);
}
// Apply transformation (but to the parents, not whole selection pool)

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using System.Linq;
using FlaxEditor.Gizmo;
@@ -150,8 +149,7 @@ namespace FlaxEditor
private float _mouseMoveSum;
private UndoMultiBlock _undoBlock;
private View _view;
private double[] _gridTickSteps = Utilities.Utils.CurveTickSteps;
private float[] _gridTickStrengths;
private float[] _gridTickSteps = Utilities.Utils.CurveTickSteps, _gridTickStrengths;
private List<Widget> _widgets;
private Widget _activeWidget;
@@ -565,9 +563,9 @@ namespace FlaxEditor
var linesColor = style.ForegroundDisabled.RGBMultiplied(0.5f);
var labelsColor = style.ForegroundDisabled;
var labelsSize = 10.0f;
Utilities.Utils.DrawCurveTicks((decimal tick, double step, float strength) =>
Utilities.Utils.DrawCurveTicks((float tick, float strength) =>
{
var p = _view.PointToParent(axis * (float)tick);
var p = _view.PointToParent(axis * tick);
// Draw line
var lineRect = new Rectangle
@@ -642,103 +640,14 @@ namespace FlaxEditor
DrawControlWidget(uiControl, ref eu, ref mousePos, ref widgetHandleSize, viewScale, new Float2(0, -1), CursorType.SizeNS);
DrawControlWidget(uiControl, ref eb, ref mousePos, ref widgetHandleSize, viewScale, new Float2(0, 1), CursorType.SizeNS);
// Draw pivot
var pivotSize = 8.0f;
if (viewScale < 0.7f)
pivotSize *= viewScale;
var pivotX = Mathf.Remap(control.Pivot.X, 0, 1, bounds.Location.X, bounds.Location.X + bounds.Width);
var pivotY = Mathf.Remap(control.Pivot.Y, 0, 1, bounds.Location.Y, bounds.Location.Y + bounds.Height);
var pivotLoc = control.PointToParent(this, new Float2(pivotX, pivotY));
var pivotRect = new Rectangle(pivotLoc - pivotSize * 0.5f, new Float2(pivotSize));
var pivotColor = options.UIPivotColor;
Render2D.FillRectangle(pivotRect, pivotColor);
// Draw anchors
var controlParent = control.Parent;
if (controlParent != null)
{
var parentBounds = controlParent.EditorBounds;
var anchorMin = control.AnchorMin;
var anchorMax = control.AnchorMax;
var newMinX = Mathf.Remap(anchorMin.X, 0, 1, parentBounds.UpperLeft.X, parentBounds.UpperRight.X);
var newMinY = Mathf.Remap(anchorMin.Y, 0, 1, parentBounds.UpperLeft.Y, parentBounds.LowerLeft.Y);
var newMaxX = Mathf.Remap(anchorMax.X, 0, 1, parentBounds.UpperLeft.X, parentBounds.UpperRight.X);
var newMaxY = Mathf.Remap(anchorMax.Y, 0, 1, parentBounds.UpperLeft.Y, parentBounds.LowerLeft.Y);
var anchorUpperLeft = controlParent.PointToParent(this, new Float2(newMinX, newMinY));
var anchorUpperRight = controlParent.PointToParent(this, new Float2(newMaxX, newMinY));
var anchorLowerLeft = controlParent.PointToParent(this, new Float2(newMinX, newMaxY));
var anchorLowerRight = controlParent.PointToParent(this, new Float2(newMaxX, newMaxY));
var anchorRectSize = 8.0f;
if (viewScale < 0.7f)
anchorRectSize *= viewScale;
// Make anchor rects and rotate if parent is rotated.
var parentRotation = controlParent.Rotation * Mathf.DegreesToRadians;
var rect1Axis = new Float2(-1, -1);
var rect1 = new Rectangle(anchorUpperLeft +
new Float2(anchorRectSize * rect1Axis.X * Mathf.Cos(parentRotation) - anchorRectSize * rect1Axis.Y * Mathf.Sin(parentRotation),
anchorRectSize * rect1Axis.Y * Mathf.Cos(parentRotation) + anchorRectSize * rect1Axis.X * Mathf.Sin(parentRotation)) - anchorRectSize * 0.5f, new Float2(anchorRectSize));
var rect2Axis = new Float2(1, -1);
var rect2 = new Rectangle(anchorUpperRight +
new Float2(anchorRectSize * rect2Axis.X * Mathf.Cos(parentRotation) - anchorRectSize * rect2Axis.Y * Mathf.Sin(parentRotation),
anchorRectSize * rect2Axis.Y * Mathf.Cos(parentRotation) + anchorRectSize * rect2Axis.X * Mathf.Sin(parentRotation)) - anchorRectSize * 0.5f, new Float2(anchorRectSize));
var rect3Axis = new Float2(-1, 1);
var rect3 = new Rectangle(anchorLowerLeft +
new Float2(anchorRectSize * rect3Axis.X * Mathf.Cos(parentRotation) - anchorRectSize * rect3Axis.Y * Mathf.Sin(parentRotation),
anchorRectSize * rect3Axis.Y * Mathf.Cos(parentRotation) + anchorRectSize * rect3Axis.X * Mathf.Sin(parentRotation)) - anchorRectSize * 0.5f, new Float2(anchorRectSize));
var rect4Axis = new Float2(1, 1);
var rect4 = new Rectangle(anchorLowerRight +
new Float2(anchorRectSize * rect4Axis.X * Mathf.Cos(parentRotation) - anchorRectSize * rect4Axis.Y * Mathf.Sin(parentRotation),
anchorRectSize * rect4Axis.Y * Mathf.Cos(parentRotation) + anchorRectSize * rect4Axis.X * Mathf.Sin(parentRotation)) - anchorRectSize * 0.5f, new Float2(anchorRectSize));
var rectColor = options.UIAnchorColor;
Render2D.DrawLine(anchorUpperLeft, anchorUpperRight, rectColor);
Render2D.DrawLine(anchorUpperRight, anchorLowerRight, rectColor);
Render2D.DrawLine(anchorLowerRight, anchorLowerLeft, rectColor);
Render2D.DrawLine(anchorLowerLeft, anchorUpperLeft, rectColor);
Render2D.FillRectangle(rect1, rectColor);
Render2D.FillRectangle(rect2, rectColor);
Render2D.FillRectangle(rect3, rectColor);
Render2D.FillRectangle(rect4, rectColor);
}
// TODO: draw anchors
}
}
private void DrawControlWidget(UIControl uiControl, ref Float2 pos, ref Float2 mousePos, ref Float2 size, float scale, Float2 resizeAxis, CursorType cursor)
{
var style = Style.Current;
var control = uiControl.Control;
var rotation = control.Rotation;
var rotationInRadians = rotation * Mathf.DegreesToRadians;
var rect = new Rectangle((pos +
new Float2(resizeAxis.X * Mathf.Cos(rotationInRadians) - resizeAxis.Y * Mathf.Sin(rotationInRadians),
resizeAxis.Y * Mathf.Cos(rotationInRadians) + resizeAxis.X * Mathf.Sin(rotationInRadians)) * 10 * scale) - size * 0.5f,
size);
// Find more correct cursor at different angles
var unwindRotation = Mathf.UnwindDegrees(rotation);
if (unwindRotation is (>= 45 and < 135) or (> -135 and <= -45) )
{
switch (cursor)
{
case CursorType.SizeNESW:
cursor = CursorType.SizeNWSE;
break;
case CursorType.SizeNS:
cursor = CursorType.SizeWE;
break;
case CursorType.SizeNWSE:
cursor = CursorType.SizeNESW;
break;
case CursorType.SizeWE:
cursor = CursorType.SizeNS;
break;
default: break;
}
}
var rect = new Rectangle((pos + resizeAxis * 10 * scale) - size * 0.5f, size);
if (rect.Contains(ref mousePos))
{
Render2D.FillRectangle(rect, style.Foreground);
@@ -775,15 +684,16 @@ namespace FlaxEditor
private bool RayCastControl(ref Float2 location, out Control hit)
{
// First, raycast only controls with content (eg. skips transparent panels)
RayCastChildren(ref location, out hit);
// If raycast failed, then find any control under mouse (hierarchical)
hit = hit ?? GetChildAtRecursive(location);
#if false
// Raycast only controls with content (eg. skips transparent panels)
return RayCastChildren(ref location, out hit);
#else
// Find any control under mouse (hierarchical)
hit = GetChildAtRecursive(location);
if (hit is View || hit is CanvasContainer)
hit = null;
return hit != null;
#endif
}
private UIControlNode FindUIControlNode(Control control)

View File

@@ -504,8 +504,7 @@ DEFINE_INTERNAL_CALL(bool) EditorInternal_CanSetToRoot(Prefab* prefab, Actor* ta
return false;
const ISerializable::DeserializeStream& newRootData = **newRootDataPtr;
Guid prefabId, prefabObjectID;
if (JsonTools::GetGuidIfValid(prefabId, newRootData, "PrefabID") &&
JsonTools::GetGuidIfValid(prefabObjectID, newRootData, "PrefabObjectID"))
if (JsonTools::GetGuidIfValid(prefabId, newRootData, "PrefabID") && JsonTools::GetGuidIfValid(prefabObjectID, newRootData, "PrefabObjectID"))
{
const auto nestedPrefab = Content::Load<Prefab>(prefabId);
if (nestedPrefab && nestedPrefab->GetRootObjectId() != prefabObjectID)
@@ -515,6 +514,21 @@ DEFINE_INTERNAL_CALL(bool) EditorInternal_CanSetToRoot(Prefab* prefab, Actor* ta
return true;
}
DEFINE_INTERNAL_CALL(void) EditorInternal_GetPrefabNestedObject(Guid* prefabId, Guid* prefabObjectId, Guid* outPrefabId, Guid* outPrefabObjectId)
{
*outPrefabId = Guid::Empty;
*outPrefabObjectId = Guid::Empty;
const auto prefab = Content::Load<Prefab>(*prefabId);
if (!prefab)
return;
const ISerializable::DeserializeStream** prefabObjectDataPtr = prefab->ObjectsDataCache.TryGet(*prefabObjectId);
if (!prefabObjectDataPtr)
return;
const ISerializable::DeserializeStream& prefabObjectData = **prefabObjectDataPtr;
JsonTools::GetGuidIfValid(*outPrefabId, prefabObjectData, "PrefabID");
JsonTools::GetGuidIfValid(*outPrefabObjectId, prefabObjectData, "PrefabObjectID");
}
DEFINE_INTERNAL_CALL(float) EditorInternal_GetAnimationTime(AnimatedModel* animatedModel)
{
return animatedModel && animatedModel->GraphInstance.State.Count() == 1 ? animatedModel->GraphInstance.State[0].Animation.TimePosition : 0.0f;

View File

@@ -12,14 +12,11 @@
#include "Engine/Scripting/ManagedCLR/MException.h"
#include "Engine/Scripting/Internal/MainThreadManagedInvokeAction.h"
#include "Engine/Content/Assets/VisualScript.h"
#include "Engine/Content/Content.h"
#include "Engine/CSG/CSGBuilder.h"
#include "Engine/Engine/CommandLine.h"
#include "Engine/Renderer/ProbesRenderer.h"
#include "Engine/Animations/Graph/AnimGraph.h"
#include "Engine/Core/ObjectsRemovalService.h"
#include "Engine/Level/Prefabs/Prefab.h"
#include "Engine/Serialization/JsonTools.h"
ManagedEditor::InternalOptions ManagedEditor::ManagedEditorOptions;
@@ -595,7 +592,6 @@ bool ManagedEditor::EvaluateVisualScriptLocal(VisualScript* script, VisualScript
void ManagedEditor::WipeOutLeftoverSceneObjects()
{
PROFILE_CPU();
Array<ScriptingObject*> objects = Scripting::GetObjects();
bool removedAny = false;
for (ScriptingObject* object : objects)
@@ -617,21 +613,6 @@ void ManagedEditor::WipeOutLeftoverSceneObjects()
ObjectsRemovalService::Flush();
}
void ManagedEditor::GetPrefabNestedObject(const Guid& prefabId, const Guid& prefabObjectId, Guid& outPrefabId, Guid& outPrefabObjectId)
{
outPrefabId = Guid::Empty;
outPrefabObjectId = Guid::Empty;
const auto prefab = Content::Load<Prefab>(prefabId);
if (!prefab)
return;
const ISerializable::DeserializeStream** prefabObjectDataPtr = prefab->ObjectsDataCache.TryGet(prefabObjectId);
if (!prefabObjectDataPtr)
return;
const ISerializable::DeserializeStream& prefabObjectData = **prefabObjectDataPtr;
JsonTools::GetGuidIfValid(outPrefabId, prefabObjectData, "PrefabID");
JsonTools::GetGuidIfValid(outPrefabObjectId, prefabObjectData, "PrefabObjectID");
}
void ManagedEditor::OnEditorAssemblyLoaded(MAssembly* assembly)
{
ASSERT(!HasManagedInstance());

View File

@@ -259,7 +259,6 @@ public:
API_FUNCTION(Internal) static Array<VisualScriptLocal> GetVisualScriptLocals();
API_FUNCTION(Internal) static bool EvaluateVisualScriptLocal(VisualScript* script, API_PARAM(Ref) VisualScriptLocal& local);
API_FUNCTION(Internal) static void WipeOutLeftoverSceneObjects();
API_FUNCTION(Internal) static void GetPrefabNestedObject(API_PARAM(Ref) const Guid& prefabId, API_PARAM(Ref) const Guid& prefabObjectId, API_PARAM(Out) Guid& outPrefabId, API_PARAM(Out) Guid& outPrefabObjectId);
private:
void OnEditorAssemblyLoaded(MAssembly* assembly);

View File

@@ -21,7 +21,6 @@ namespace FlaxEditor.Modules
private bool _enableEvents;
private bool _isDuringFastSetup;
private bool _rebuildFlag;
private bool _rebuildInitFlag;
private int _itemsCreated;
private int _itemsDeleted;
private readonly HashSet<MainContentTreeNode> _dirtyNodes = new HashSet<MainContentTreeNode>();
@@ -62,7 +61,7 @@ namespace FlaxEditor.Modules
public event Action WorkspaceModified;
/// <summary>
/// Occurs when workspace will be rebuilt.
/// Occurs when workspace has will be rebuilt.
/// </summary>
public event Action WorkspaceRebuilding;
@@ -89,9 +88,6 @@ namespace FlaxEditor.Modules
// Register AssetItems serialization helper (serialize ref ID only)
FlaxEngine.Json.JsonSerializer.Settings.Converters.Add(new AssetItemConverter());
ScriptsBuilder.ScriptsReload += OnScriptsReload;
ScriptsBuilder.ScriptsReloadEnd += OnScriptsReloadEnd;
}
private void OnContentAssetDisposing(Asset asset)
@@ -821,7 +817,6 @@ namespace FlaxEditor.Modules
Profiler.BeginEvent("ContentDatabase.Rebuild");
var startTime = Platform.TimeSeconds;
_rebuildFlag = false;
_rebuildInitFlag = false;
_enableEvents = false;
// Load all folders
@@ -1013,7 +1008,7 @@ namespace FlaxEditor.Modules
ContentItem item;
if (path.EndsWith(".cs"))
item = new CSharpScriptItem(path);
else if (path.EndsWith(".cpp") || path.EndsWith(".h") || path.EndsWith(".c") || path.EndsWith(".hpp"))
else if (path.EndsWith(".cpp") || path.EndsWith(".h"))
item = new CppScriptItem(path);
else if (path.EndsWith(".shader") || path.EndsWith(".hlsl"))
item = new ShaderSourceItem(path);
@@ -1145,7 +1140,6 @@ namespace FlaxEditor.Modules
Proxy.Add(new CSharpEmptyStructProxy());
Proxy.Add(new CSharpEmptyInterfaceProxy());
Proxy.Add(new CSharpActorProxy());
Proxy.Add(new CSharpGamePluginProxy());
Proxy.Add(new CppAssetProxy());
Proxy.Add(new CppStaticClassProxy());
Proxy.Add(new CppScriptProxy());
@@ -1235,6 +1229,8 @@ namespace FlaxEditor.Modules
LoadProjects(Game.Project);
}
RebuildInternal();
Editor.ContentImporting.ImportFileEnd += (obj, failed) =>
{
var path = obj.ResultUrl;
@@ -1242,15 +1238,6 @@ namespace FlaxEditor.Modules
FlaxEngine.Scripting.InvokeOnUpdate(() => OnImportFileDone(path));
};
_enableEvents = true;
_rebuildInitFlag = true;
}
/// <inheritdoc />
public override void OnEndInit()
{
// Handle init when project was loaded without scripts loading ()
if (_rebuildInitFlag)
RebuildInternal();
}
private void OnImportFileDone(string path)
@@ -1325,52 +1312,6 @@ namespace FlaxEditor.Modules
}
}
private void OnScriptsReload()
{
var enabledEvents = _enableEvents;
_enableEvents = false;
_isDuringFastSetup = true;
var startItems = _itemsCreated;
foreach (var project in Projects)
{
if (project.Content != null)
{
//Dispose(project.Content.Folder);
for (int i = 0; i < project.Content.Folder.Children.Count; i++)
{
Dispose(project.Content.Folder.Children[i]);
i--;
}
}
if (project.Source != null)
{
//Dispose(project.Source.Folder);
for (int i = 0; i < project.Source.Folder.Children.Count; i++)
{
Dispose(project.Source.Folder.Children[i]);
i--;
}
}
}
List<ContentProxy> removeProxies = new List<ContentProxy>();
foreach (var proxy in Editor.Instance.ContentDatabase.Proxy)
{
if (proxy.GetType().IsCollectible)
removeProxies.Add(proxy);
}
foreach (var proxy in removeProxies)
RemoveProxy(proxy, false);
_isDuringFastSetup = false;
_enableEvents = enabledEvents;
}
private void OnScriptsReloadEnd()
{
RebuildInternal();
}
/// <inheritdoc />
public override void OnUpdate()
{
@@ -1398,8 +1339,6 @@ namespace FlaxEditor.Modules
public override void OnExit()
{
FlaxEngine.Content.AssetDisposing -= OnContentAssetDisposing;
ScriptsBuilder.ScriptsReload -= OnScriptsReload;
ScriptsBuilder.ScriptsReloadEnd -= OnScriptsReloadEnd;
// Disable events
_enableEvents = false;

View File

@@ -222,7 +222,7 @@ namespace FlaxEditor.Modules
outputExtension = extension;
// Check if can place source files here
if (!targetLocation.CanHaveScripts && (extension == ".cs" || extension == ".cpp" || extension == ".h" || extension == ".c" || extension == ".hpp"))
if (!targetLocation.CanHaveScripts && (extension == ".cs" || extension == ".cpp" || extension == ".h"))
{
// Error
Editor.LogWarning(string.Format("Cannot import \'{0}\' to \'{1}\'. The target directory cannot have scripts.", inputPath, targetLocation.Node.Path));
@@ -391,20 +391,6 @@ namespace FlaxEditor.Modules
public override void OnInit()
{
ImportFileEntry.RegisterDefaultTypes();
ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin;
}
private void OnScriptsReloadBegin()
{
// Remove import file types from scripting assemblies
List<string> removeFileTypes = new List<string>();
foreach (var pair in ImportFileEntry.FileTypes)
{
if (pair.Value.Method.IsCollectible || (pair.Value.Target != null && pair.Value.Target.GetType().IsCollectible))
removeFileTypes.Add(pair.Key);
}
foreach (var fileType in removeFileTypes)
ImportFileEntry.FileTypes.Remove(fileType);
}
/// <inheritdoc />
@@ -465,7 +451,6 @@ namespace FlaxEditor.Modules
/// <inheritdoc />
public override void OnExit()
{
ScriptsBuilder.ScriptsReloadBegin -= OnScriptsReloadBegin;
EndWorker();
}
}

View File

@@ -105,33 +105,6 @@ namespace FlaxEditor.Modules
Editor.Windows.ContentWin.NewItem(proxy, actor, contentItem => OnPrefabCreated(contentItem, actor, prefabWindow), actor.Name, rename);
}
/// <summary>
/// Opens a prefab editor window.
/// </summary>
public void OpenPrefab(ActorNode actorNode)
{
if (actorNode != null)
OpenPrefab(actorNode.Actor.PrefabID);
}
/// <summary>
/// Opens a prefab editor window.
/// </summary>
public void OpenPrefab(Guid prefabID = default)
{
if (prefabID == Guid.Empty)
{
var selection = Editor.SceneEditing.Selection.Where(x => x is ActorNode actorNode && actorNode.HasPrefabLink).ToList().BuildNodesParents();
if (selection.Count == 0 || !((ActorNode)selection[0]).Actor.HasPrefabLink)
return;
prefabID = ((ActorNode)selection[0]).Actor.PrefabID;
}
var item = Editor.ContentDatabase.Find(prefabID);
if (item != null)
Editor.ContentEditing.Open(item);
}
private void OnPrefabCreated(ContentItem contentItem, Actor actor, Windows.Assets.PrefabWindow prefabWindow)
{
if (contentItem is PrefabItem prefabItem)

View File

@@ -58,7 +58,7 @@ namespace FlaxEditor.Modules
: base(editor)
{
// After editor cache but before the windows
InitOrder = -800;
InitOrder = -900;
}
/// <summary>

View File

@@ -16,7 +16,7 @@ using FlaxEditor.Windows;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Json;
using WindowDragHelper = FlaxEditor.GUI.Docking.WindowDragHelper;
using DockHintWindow = FlaxEditor.GUI.Docking.DockHintWindow;
using MasterDockPanel = FlaxEditor.GUI.Docking.MasterDockPanel;
using FlaxEditor.Content.Settings;
using FlaxEditor.Options;
@@ -160,7 +160,7 @@ namespace FlaxEditor.Modules
internal UIModule(Editor editor)
: base(editor)
{
InitOrder = -70;
InitOrder = -90;
VisjectSurfaceBackground = FlaxEngine.Content.LoadAsyncInternal<Texture>("Editor/VisjectSurface");
ColorValueBox.ShowPickColorDialog += ShowPickColorDialog;
}
@@ -456,6 +456,13 @@ namespace FlaxEditor.Modules
UpdateToolstrip();
}
/// <inheritdoc />
public override void OnExit()
{
// Cleanup dock panel hint proxy windows (Flax will destroy them by var but it's better to clear them earlier)
DockHintWindow.Proxy.Dispose();
}
private IColorPickerDialog ShowPickColorDialog(Control targetControl, Color initialValue, ColorValueBox.ColorPickerEvent colorChanged, ColorValueBox.ColorPickerClosedEvent pickerClosed, bool useDynamicEditing)
{
var dialog = new ColorPickerDialog(initialValue, colorChanged, pickerClosed, useDynamicEditing);

View File

@@ -5,12 +5,10 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml;
using FlaxEditor.Content;
using FlaxEditor.GUI.Dialogs;
using FlaxEditor.GUI.Docking;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEditor.Windows.Profiler;
@@ -41,7 +39,6 @@ namespace FlaxEditor.Modules
public DockState DockState;
public DockPanel DockedTo;
public int DockedTabIndex;
public float? SplitterValue = null;
public bool SelectOnShow = false;
@@ -51,8 +48,6 @@ namespace FlaxEditor.Modules
public Float2 FloatSize;
public Float2 FloatPosition;
public Guid AssetItemID;
// Constructor, to allow for default values
public WindowRestoreData()
{
@@ -810,64 +805,43 @@ namespace FlaxEditor.Modules
Level.SceneSaving += OnSceneSaving;
Level.SceneUnloaded += OnSceneUnloaded;
Level.SceneUnloading += OnSceneUnloading;
Editor.ContentDatabase.WorkspaceRebuilt += OnWorkspaceRebuilt;
ScriptsBuilder.ScriptsReloadEnd += OnScriptsReloadEnd;
Editor.StateMachine.StateChanged += OnEditorStateChanged;
}
internal void AddToRestore(AssetEditorWindow win)
{
AddToRestore(win, win.GetType(), new WindowRestoreData
{
AssetItemID = win.Item.ID,
});
}
internal void AddToRestore(CustomEditorWindow win)
{
AddToRestore(win.Window, win.GetType(), new WindowRestoreData());
}
var type = win.GetType();
private void AddToRestore(EditorWindow win, Type type, WindowRestoreData winData)
{
// Validate if can restore type
var constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
if (constructor == null || type.IsGenericType)
return;
var panel = win.ParentDockPanel;
var winData = new WindowRestoreData();
var panel = win.Window.ParentDockPanel;
// Ensure that this window is only selected following recompilation
// if it was the active tab in its dock panel. Otherwise, there is a
// risk of interrupting the user's workflow by potentially selecting
// background tabs.
var window = win.RootWindow.Window;
winData.SelectOnShow = panel.SelectedTab == win;
winData.DockedTabIndex = 0;
if (panel is FloatWindowDockPanel && window != null && panel.TabsCount == 1)
winData.SelectOnShow = panel.SelectedTab == win.Window;
if (panel is FloatWindowDockPanel)
{
winData.DockState = DockState.Float;
var window = win.Window.RootWindow.Window;
winData.FloatPosition = window.Position;
winData.FloatSize = window.ClientSize;
winData.Maximize = window.IsMaximized;
winData.Minimize = window.IsMinimized;
winData.DockedTo = panel;
}
else
{
for (int i = 0; i < panel.Tabs.Count; i++)
{
if (panel.Tabs[i] == win)
{
winData.DockedTabIndex = i;
break;
}
}
if (panel.TabsCount > 1)
{
winData.DockState = DockState.DockFill;
winData.DockedTo = panel;
}
else
}else
{
winData.DockState = panel.TryGetDockState(out var splitterValue);
winData.DockedTo = panel.ParentDockPanel;
@@ -879,93 +853,38 @@ namespace FlaxEditor.Modules
_restoreWindows.Add(winData);
}
private void OnWorkspaceRebuilt()
private void OnScriptsReloadEnd()
{
// Go in reverse order to create floating Prefab windows first before docked windows
for (int i = _restoreWindows.Count - 1; i >= 0; i--)
for (int i = 0; i < _restoreWindows.Count; i++)
{
var winData = _restoreWindows[i];
try
{
var assembly = Utils.GetAssemblyByName(winData.AssemblyName);
if (assembly == null)
continue;
var type = assembly.GetType(winData.TypeName);
if (type == null)
continue;
if (type.IsAssignableTo(typeof(AssetEditorWindow)))
if (assembly != null)
{
var ctor = type.GetConstructor(new Type[] { typeof(Editor), typeof(AssetItem) });
var assetItem = Editor.ContentDatabase.FindAsset(winData.AssetItemID);
var win = (AssetEditorWindow)ctor.Invoke(new object[] { Editor.Instance, assetItem });
win.Show(winData.DockState, winData.DockState != DockState.Float ? winData.DockedTo : null, winData.SelectOnShow, winData.SplitterValue);
if (winData.DockState == DockState.Float)
var type = assembly.GetType(winData.TypeName);
if (type != null)
{
var window = win.RootWindow.Window;
window.Position = winData.FloatPosition;
if (winData.Maximize)
var win = (CustomEditorWindow)Activator.CreateInstance(type);
win.Show(winData.DockState, winData.DockedTo, winData.SelectOnShow, winData.SplitterValue);
if (winData.DockState == DockState.Float)
{
window.Maximize();
}
else if (winData.Minimize)
{
window.Minimize();
}
else
{
window.ClientSize = winData.FloatSize;
}
// Update panel reference in other windows docked to this panel
foreach (ref var otherData in CollectionsMarshal.AsSpan(_restoreWindows))
{
if (otherData.DockedTo == winData.DockedTo)
otherData.DockedTo = win.ParentDockPanel;
}
}
var panel = win.ParentDockPanel;
int currentTabIndex = 0;
for (int pi = 0; pi < panel.TabsCount; pi++)
{
if (panel.Tabs[pi] == win)
{
currentTabIndex = pi;
break;
}
}
while (currentTabIndex > winData.DockedTabIndex)
{
win.ParentDockPanel.MoveTabLeft(currentTabIndex);
currentTabIndex--;
}
while (currentTabIndex < winData.DockedTabIndex)
{
win.ParentDockPanel.MoveTabRight(currentTabIndex);
currentTabIndex++;
}
}
else
{
var win = (CustomEditorWindow)Activator.CreateInstance(type);
win.Show(winData.DockState, winData.DockedTo, winData.SelectOnShow, winData.SplitterValue);
if (winData.DockState == DockState.Float)
{
var window = win.Window.RootWindow.Window;
window.Position = winData.FloatPosition;
if (winData.Maximize)
{
window.Maximize();
}
else if (winData.Minimize)
{
window.Minimize();
}
else
{
window.ClientSize = winData.FloatSize;
var window = win.Window.RootWindow.Window;
window.Position = winData.FloatPosition;
if (winData.Maximize)
{
window.Maximize();
}
else if (winData.Minimize)
{
window.Minimize();
}
else
{
window.ClientSize = winData.FloatSize;
}
}
}
}
@@ -976,11 +895,6 @@ namespace FlaxEditor.Modules
Editor.LogWarning(string.Format("Failed to restore window {0} (assembly: {1})", winData.TypeName, winData.AssemblyName));
}
}
// Restored windows stole the focus from Editor
if (_restoreWindows.Count > 0)
Editor.Instance.Windows.MainWindow.Focus();
_restoreWindows.Clear();
}
@@ -1136,7 +1050,7 @@ namespace FlaxEditor.Modules
Level.SceneSaving -= OnSceneSaving;
Level.SceneUnloaded -= OnSceneUnloaded;
Level.SceneUnloading -= OnSceneUnloading;
Editor.ContentDatabase.WorkspaceRebuilt -= OnWorkspaceRebuilt;
ScriptsBuilder.ScriptsReloadEnd -= OnScriptsReloadEnd;
Editor.StateMachine.StateChanged -= OnEditorStateChanged;
// Close main window

View File

@@ -1,9 +1,7 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System.Text;
using FlaxEditor.CustomEditors;
using FlaxEditor.CustomEditors.Editors;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Json;
@@ -33,33 +31,11 @@ namespace FlaxEditor.Options
private void OnResetButtonClicked()
{
var editorClassName = typeof(T).Name;
var editorName = new StringBuilder();
editorName.Append(editorClassName[0]);
for (var i = 1; i < editorClassName.Length; i++)
{
// Whenever there is an uppercase letter, add a space to make it more pretty for the end user
if (char.IsUpper(editorClassName[i]))
{
editorName.Append(' ');
}
editorName.Append(editorClassName[i]);
}
var result = MessageBox.Show($"Are you sure you want to reset \"{editorName}\" to default values?",
"Reset values?",
MessageBoxButtons.YesNo
);
if (result == DialogResult.Yes || result == DialogResult.OK)
{
var obj = new T();
var str = JsonSerializer.Serialize(obj);
JsonSerializer.Deserialize(Values[0], str);
SetValue(Values[0]);
Refresh();
}
var obj = new T();
var str = JsonSerializer.Serialize(obj);
JsonSerializer.Deserialize(Values[0], str);
SetValue(Values[0]);
Refresh();
}
}
}

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