5 Commits

Author SHA1 Message Date
c1f6bcb83f some linux work from summer
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
2025-10-12 18:06:23 +03:00
eca4f6d9bc Merge remote-tracking branch 'origin/1.11' into work
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
2025-07-05 14:19:52 +03:00
802074fca3 Update package requirements for Wayland 2025-07-05 12:55:25 +03:00
0bb13e1d91 Add overloads for physics queries with user-provided buffers 2025-07-05 12:36:11 +03:00
db47531a6d Support marshalling Arrays as dynamic arrays in scripting API 2025-07-05 12:36:11 +03:00
499 changed files with 6134 additions and 52639 deletions

BIN
Content/Editor/Camera/M_Camera.flax (Stored with Git LFS)

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.

BIN
Content/Editor/DefaultFontMaterial.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/Gizmo/Material.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Gizmo/MaterialWire.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/Highlight Material.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Icons/IconsMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/IconsAtlas.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

View File

@@ -13,7 +13,7 @@
META_CB_BEGIN(0, Data)
float4x4 WorldMatrix;
float4x4 InvWorld;
float4x4 SvPositionToWorld;
float4x4 SVPositionToWorld;
@1META_CB_END
// Use depth buffer for per-pixel decal layering
@@ -27,63 +27,12 @@ struct MaterialInput
float3 WorldPosition;
float TwoSidedSign;
float2 TexCoord;
float4 TexCoord_DDX_DDY;
float3x3 TBN;
float4 SvPosition;
float3 PreSkinnedPosition;
float3 PreSkinnedNormal;
};
// Calculates decal texcoords for a given pixel position (sampels depth buffer and projects value to decal space).
float2 SvPositionToDecalUV(float4 svPosition)
{
float2 screenUV = svPosition.xy * ScreenSize.zw;
svPosition.z = SAMPLE_RT(DepthBuffer, screenUV).r;
float4 positionHS = mul(float4(svPosition.xyz, 1), SvPositionToWorld);
float3 positionWS = positionHS.xyz / positionHS.w;
float3 positionOS = mul(float4(positionWS, 1), InvWorld).xyz;
return positionOS.xz + 0.5f;
}
// Manually compute ddx/ddy for decal texture cooordinates to avoid the 2x2 pixels artifacts on the edges of geometry under decal
// [Reference: https://www.humus.name/index.php?page=3D&ID=84]
float4 CalculateTextureDerivatives(float4 svPosition, float2 texCoord)
{
float4 svDiffX = float4(1, 0, 0, 0);
float2 uvDiffX0 = texCoord - SvPositionToDecalUV(svPosition - svDiffX);
float2 uvDiffX1 = SvPositionToDecalUV(svPosition + svDiffX) - texCoord;
float2 dx = dot(uvDiffX0, uvDiffX0) < dot(uvDiffX1, uvDiffX1) ? uvDiffX0 : uvDiffX1;
float4 svDiffY = float4(0, 1, 0, 0);
float2 uvDiffY0 = texCoord - SvPositionToDecalUV(svPosition - svDiffY);
float2 uvDiffY1 = SvPositionToDecalUV(svPosition + svDiffY) - texCoord;
float2 dy = dot(uvDiffY0, uvDiffY0) < dot(uvDiffY1, uvDiffY1) ? uvDiffY0 : uvDiffY1;
return float4(dx, dy);
}
// Computes the mipmap level for a specific texture dimensions to be sampled at decal texture cooordinates.
// [Reference: https://hugi.scene.org/online/coding/hugi%2014%20-%20comipmap.htm]
float CalculateTextureMipmap(MaterialInput input, float2 textureSize)
{
float2 dx = input.TexCoord_DDX_DDY.xy * textureSize;
float2 dy = input.TexCoord_DDX_DDY.zw * textureSize;
float d = max(dot(dx, dx), dot(dy, dy));
return (0.5 * 0.5) * log2(d); // Hardcoded half-mip rate reduction to avoid artifacts when decal is moved over dither texture
}
float CalculateTextureMipmap(MaterialInput input, Texture2D t)
{
float2 textureSize;
t.GetDimensions(textureSize.x, textureSize.y);
return CalculateTextureMipmap(input, textureSize);
}
float CalculateTextureMipmap(MaterialInput input, TextureCube t)
{
float2 textureSize;
t.GetDimensions(textureSize.x, textureSize.y);
return CalculateTextureMipmap(input, textureSize);
}
// Transforms a vector from tangent space to world space
float3 TransformTangentVectorToWorld(MaterialInput input, float3 tangentVector)
{
@@ -167,6 +116,7 @@ Material GetMaterialPS(MaterialInput input)
}
// Input macro specified by the material: DECAL_BLEND_MODE
#define DECAL_BLEND_MODE_TRANSLUCENT 0
#define DECAL_BLEND_MODE_STAIN 1
#define DECAL_BLEND_MODE_NORMAL 2
@@ -203,7 +153,7 @@ void PS_Decal(
float2 screenUV = SvPosition.xy * ScreenSize.zw;
SvPosition.z = SAMPLE_RT(DepthBuffer, screenUV).r;
float4 positionHS = mul(float4(SvPosition.xyz, 1), SvPositionToWorld);
float4 positionHS = mul(float4(SvPosition.xyz, 1), SVPositionToWorld);
float3 positionWS = positionHS.xyz / positionHS.w;
float3 positionOS = mul(float4(positionWS, 1), InvWorld).xyz;
@@ -216,9 +166,8 @@ void PS_Decal(
materialInput.TexCoord = decalUVs;
materialInput.TwoSidedSign = 1;
materialInput.SvPosition = SvPosition;
materialInput.TexCoord_DDX_DDY = CalculateTextureDerivatives(materialInput.SvPosition, materialInput.TexCoord);
// Calculate tangent-space
// Build tangent to world transformation matrix
float3 ddxWp = ddx(positionWS);
float3 ddyWp = ddy(positionWS);
materialInput.TBN[0] = normalize(ddyWp);

View File

@@ -20,8 +20,6 @@ float TimeParam;
float4 ViewInfo;
float4 ScreenSize;
float4 ViewSize;
float3 ViewPadding0;
float UnscaledTimeParam;
@1META_CB_END
// Shader resources

View File

@@ -19,8 +19,6 @@ float4 ViewInfo;
float4 ScreenSize;
float4 TemporalAAJitter;
float4x4 InverseViewProjectionMatrix;
float3 ViewPadding0;
float UnscaledTimeParam;
@1META_CB_END
// Shader resources

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/SpriteMaterial.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/TexturePreviewMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Wires Debug Material.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Content/Engine/DefaultMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/DefaultRadialMenu.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/DefaultTerrainMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/SingleColorMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/SkyboxMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Shaders/BitonicSort.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Shaders/GPUParticlesSorting.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Shaders/PostProcessing.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Shaders/SSAO.flax (Stored with Git LFS)

Binary file not shown.

View File

@@ -73,24 +73,6 @@
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=TYPEDEF/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=UNION/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=UNION_005FMEMBER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Abbreviations/=CCD/@EntryIndexedValue">CCD</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Abbreviations/=GPU/@EntryIndexedValue">GPU</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=175CE9C669E52F4D92FD2C07848740BD/@EntryIndexedValue">&lt;NamingElement Priority="11" Title="Class and struct public fields"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="PUBLIC"&gt;&lt;type Name="class field" /&gt;&lt;type Name="struct field" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=32EB6D69783B3E4481A733193E338089/@EntryIndexedValue">&lt;NamingElement Priority="9" Title="Class and struct methods"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="member function" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=3C4E0D59F298854F9608A9B454E8FF5E/@EntryIndexedValue">&lt;NamingElement Priority="17" Title="Typedefs"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="type alias" /&gt;&lt;type Name="typedef" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=499C9026DADA2B448BCD0B2C54746A59/@EntryIndexedValue">&lt;NamingElement Priority="14" Title="Other constants"&gt;&lt;Descriptor Static="True" Constexpr="Indeterminate" Const="True" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="class field" /&gt;&lt;type Name="local variable" /&gt;&lt;type Name="struct field" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=50D2535711CE1A43A3B06EF841C36CFD/@EntryIndexedValue">&lt;NamingElement Priority="13" Title="Enum members"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="scoped enumerator" /&gt;&lt;type Name="unscoped enumerator" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=6AD3BADA1260CC4D840AB26323C51827/@EntryIndexedValue">&lt;NamingElement Priority="15" Title="Global constants"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="True" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="global variable" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=904CDCA174AACE4AA52660A247CDF9A0/@EntryIndexedValue">&lt;NamingElement Priority="7" Title="Global variables"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="global variable" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=95BCDE767C97B64DB3DAE800DBBBC758/@EntryIndexedValue">&lt;NamingElement Priority="5" Title="Parameters"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="function parameter" /&gt;&lt;type Name="lambda parameter" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=C03AE454FC2CBA43819AC75E4D6C9C8C/@EntryIndexedValue">&lt;NamingElement Priority="1" Title="Classes and structs"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="__interface" /&gt;&lt;type Name="class" /&gt;&lt;type Name="struct" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=D49E31C610641E4CAD0407DB79ACC851/@EntryIndexedValue">&lt;NamingElement Priority="8" Title="Global functions"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="global function" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=D73FBB3529BC5449B6C85BB37B26A8D4/@EntryIndexedValue">&lt;NamingElement Priority="16" Title="Namespaces"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="namespace" /&gt;&lt;type Name="namespace alias" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=DA41807CE47AEB4CBE1724C44D0B786E/@EntryIndexedValue">&lt;NamingElement Priority="6" Title="Local variables"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="local variable" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=DDF30C9A1DA74B4DBBC56D25FDF886AA/@EntryIndexedValue">&lt;NamingElement Priority="10" Title="Class and struct fields"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="class field" /&gt;&lt;type Name="struct field" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="_" Suffix="" Style="aaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=EF70A6BF54ACE446971DDB32344C25A3/@EntryIndexedValue">&lt;NamingElement Priority="12" Title="Union members"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="union member" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNamingOptions/Rules/=F37818C54C323A4A80B1A478629985AE/@EntryIndexedValue">&lt;NamingElement Priority="2" Title="Enums"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="enum" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AI/@EntryIndexedValue">AI</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ARGB/@EntryIndexedValue">ARGB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LO/@EntryIndexedValue">LO</s:String>
@@ -231,7 +213,6 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=YZ/@EntryIndexedValue">YZ</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PublicFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="_" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/Environment/Hierarchy/PsiConfigurationSettingsKey/CustomLocation/@EntryValue">C:\Users\Wojtek\AppData\Local\JetBrains\Transient\ReSharperPlatformVs15\v08_f9eacea9\SolutionCaches</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EFeature_002EServices_002ECpp_002ECodeStyle_002ENaming_002ECppNamingOptionsMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EFeature_002EServices_002ECpp_002ECodeStyle_002ESettingsUpgrade_002EFunctionReturnStyleSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EFeature_002EServices_002ECpp_002ECodeStyle_002ESettingsUpgrade_002ENamespaceIndentationSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean>

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
#Binaries/Tools/Flax.Build -build -BuildBindingsOnly -arch=x64 -platform=Linux --buildTargets=FlaxEditor

View File

@@ -57,9 +57,9 @@ Follow the instructions below to compile and run the engine from source.
* Arch: `sudo pacman -S git git-lfs`
* `git-lfs install`
* Install the required packages:
* Ubuntu: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev zlib1g-dev`
* Fedora: `sudo dnf install libX11-devel libXcursor-devel libXinerama-devel ghc-zlib-devel`
* Arch: `sudo pacman -S base-devel libx11 libxcursor libxinerama zlib`
* Ubuntu: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev zlib1g-dev zenity wayland-protocols libportal-dev`
* Fedora: `sudo dnf install libX11-devel libXcursor-devel libXinerama-devel ghc-zlib-devel zenity wayland-protocols-devel libportal`
* Arch: `sudo pacman -S base-devel libx11 libxcursor libxinerama zlib zenity wayland-protocols libportal`
* Install Clang compiler (version 6 or later):
* Ubuntu: `sudo apt-get install clang lldb lld`
* Fedora: `sudo dnf install clang llvm lldb lld`

View File

@@ -20,6 +20,13 @@ class PlatformTools;
#define GAME_BUILD_DOTNET_RUNTIME_MAX_VER 9
#endif
#if OFFICIAL_BUILD
// Use the fixed .NET SDK version in packaged builds for compatibility (FlaxGame is precompiled with it)
#define GAME_BUILD_DOTNET_VER TEXT("-dotnet=" MACRO_TO_STR(GAME_BUILD_DOTNET_RUNTIME_MIN_VER))
#else
#define GAME_BUILD_DOTNET_VER TEXT("")
#endif
/// <summary>
/// Game building options. Used as flags.
/// </summary>
@@ -367,8 +374,6 @@ public:
/// </summary>
void GetBuildPlatformName(const Char*& platform, const Char*& architecture) const;
String GetDotnetCommandArg() const;
public:
/// <summary>

View File

@@ -312,14 +312,6 @@ void CookingData::GetBuildPlatformName(const Char*& platform, const Char*& archi
}
}
String CookingData::GetDotnetCommandArg() const
{
int32 version = Tools->GetDotnetVersion();
if (version == 0)
return String::Empty;
return String::Format(TEXT("-dotnet={}"), version);
}
void CookingData::StepProgress(const String& info, const float stepProgress) const
{
const float singleStepProgress = 1.0f / (StepsCount + 1);
@@ -683,7 +675,8 @@ bool GameCookerImpl::Build()
MCore::Thread::Attach();
// Build start
// Build Started
if (!EnumHasAnyFlags(data.Options, BuildOptions::NoCook))
{
CallEvent(GameCooker::EventType::BuildStarted);
data.Tools->OnBuildStarted(data);
@@ -756,8 +749,8 @@ bool GameCookerImpl::Build()
}
IsRunning = false;
CancelFlag = 0;
if (!EnumHasAnyFlags(data.Options, BuildOptions::NoCook))
{
// Build end
for (int32 stepIndex = 0; stepIndex < Steps.Count(); stepIndex++)
Steps[stepIndex]->OnBuildEnded(data, failed);
data.Tools->OnBuildEnded(data, failed);

View File

@@ -195,9 +195,4 @@ bool GDKPlatformTools::OnPostProcess(CookingData& data, GDKPlatformSettings* pla
return false;
}
int32 GDKPlatformTools::GetDotnetVersion() const
{
return GAME_BUILD_DOTNET_RUNTIME_MIN_VER;
}
#endif

View File

@@ -26,7 +26,6 @@ public:
public:
// [PlatformTools]
int32 GetDotnetVersion() const override;
DotNetAOTModes UseAOT() const override;
bool OnDeployBinaries(CookingData& data) override;
};

View File

@@ -231,8 +231,6 @@ bool MacPlatformTools::OnPostProcess(CookingData& data)
LOG(Info, "Building app package...");
{
const String dmgPath = data.OriginalOutputPath / appName + TEXT(".dmg");
if (FileSystem::FileExists(dmgPath))
FileSystem::DeleteFile(dmgPath);
CreateProcessSettings procSettings;
procSettings.HiddenWindow = true;
procSettings.WorkingDirectory = data.OriginalOutputPath;

View File

@@ -528,9 +528,6 @@ bool WindowsPlatformTools::OnDeployBinaries(CookingData& data)
void WindowsPlatformTools::OnBuildStarted(CookingData& data)
{
if (EnumHasAllFlags(data.Options, BuildOptions::NoCook))
return;
// Remove old executable
Array<String> files;
FileSystem::DirectoryGetFiles(files, data.NativeCodeOutputPath, TEXT("*.exe"), DirectorySearchOption::TopDirectoryOnly);

View File

@@ -70,20 +70,6 @@ public:
/// </summary>
virtual ArchitectureType GetArchitecture() const = 0;
/// <summary>
/// Gets the .Net version to use for the cooked game.
/// </summary>
virtual int32 GetDotnetVersion() const
{
#if OFFICIAL_BUILD
// Use the fixed .NET SDK version in packaged builds for compatibility (FlaxGame is precompiled with it)
return GAME_BUILD_DOTNET_RUNTIME_MIN_VER;
#else
// Use the highest version found on a system (Flax.Build will decide)
return 0;
#endif
}
/// <summary>
/// Gets the value indicating whenever platform requires AOT (needs C# assemblies to be precompiled).
/// </summary>

View File

@@ -189,7 +189,7 @@ bool CompileScriptsStep::Perform(CookingData& data)
const String logFile = data.CacheDirectory / TEXT("CompileLog.txt");
auto args = String::Format(
TEXT("-log -logfile=\"{4}\" -build -mutex -buildtargets={0} -platform={1} -arch={2} -configuration={3} -aotMode={5} {6}"),
target, platform, architecture, configuration, logFile, ToString(data.Tools->UseAOT()), data.GetDotnetCommandArg());
target, platform, architecture, configuration, logFile, ToString(data.Tools->UseAOT()), GAME_BUILD_DOTNET_VER);
#if PLATFORM_WINDOWS
if (data.Platform == BuildPlatform::LinuxX64)
#elif PLATFORM_LINUX

View File

@@ -88,7 +88,7 @@ bool DeployDataStep::Perform(CookingData& data)
{
// Ask Flax.Build to provide .NET SDK location for the current platform
String sdks;
bool failed = ScriptsBuilder::RunBuildTool(String::Format(TEXT("-log -logMessagesOnly -logFileWithConsole -logfile=SDKs.txt -printSDKs {}"), data.GetDotnetCommandArg()), data.CacheDirectory);
bool failed = ScriptsBuilder::RunBuildTool(String::Format(TEXT("-log -logMessagesOnly -logFileWithConsole -logfile=SDKs.txt -printSDKs {}"), GAME_BUILD_DOTNET_VER), data.CacheDirectory);
failed |= File::ReadAllText(data.CacheDirectory / TEXT("SDKs.txt"), sdks);
int32 idx = sdks.Find(TEXT("DotNetSdk, "), StringSearchCase::CaseSensitive);
if (idx != -1)
@@ -200,7 +200,7 @@ bool DeployDataStep::Perform(CookingData& data)
String sdks;
const Char *platformName, *archName;
data.GetBuildPlatformName(platformName, archName);
String args = String::Format(TEXT("-log -logMessagesOnly -logFileWithConsole -logfile=SDKs.txt -printDotNetRuntime -platform={} -arch={} {}"), platformName, archName, data.GetDotnetCommandArg());
String args = String::Format(TEXT("-log -logMessagesOnly -logFileWithConsole -logfile=SDKs.txt -printDotNetRuntime -platform={} -arch={} {}"), platformName, archName, GAME_BUILD_DOTNET_VER);
bool failed = ScriptsBuilder::RunBuildTool(args, data.CacheDirectory);
failed |= File::ReadAllText(data.CacheDirectory / TEXT("SDKs.txt"), sdks);
Array<String> parts;
@@ -244,13 +244,10 @@ bool DeployDataStep::Perform(CookingData& data)
}
if (version.IsEmpty())
{
int32 minVer = GAME_BUILD_DOTNET_RUNTIME_MIN_VER, maxVer = GAME_BUILD_DOTNET_RUNTIME_MAX_VER;
if (srcDotnetFromEngine)
{
// Detect version from runtime files inside Engine Platform folder
if (data.Tools->GetDotnetVersion() != 0)
minVer = maxVer = data.Tools->GetDotnetVersion();
for (int32 i = maxVer; i >= minVer; i--)
for (int32 i = GAME_BUILD_DOTNET_RUNTIME_MAX_VER; i >= GAME_BUILD_DOTNET_RUNTIME_MIN_VER; i--)
{
// Check runtime files inside Engine Platform folder
String testPath1 = srcDotnet / String::Format(TEXT("lib/net{}.0"), i);
@@ -265,7 +262,7 @@ bool DeployDataStep::Perform(CookingData& data)
}
if (version.IsEmpty())
{
data.Error(String::Format(TEXT("Failed to find supported .NET {} version (min {}) for the current host platform."), maxVer, minVer));
data.Error(String::Format(TEXT("Failed to find supported .NET {} version for the current host platform."), GAME_BUILD_DOTNET_RUNTIME_MIN_VER));
return true;
}
}
@@ -367,7 +364,7 @@ bool DeployDataStep::Perform(CookingData& data)
const String logFile = data.CacheDirectory / TEXT("StripDotnetLibs.txt");
String args = String::Format(
TEXT("-log -logfile=\"{}\" -runDotNetClassLibStripping -mutex -binaries=\"{}\" {}"),
logFile, data.DataOutputPath, data.GetDotnetCommandArg());
logFile, data.DataOutputPath, GAME_BUILD_DOTNET_VER);
for (const String& define : data.CustomDefines)
{
args += TEXT(" -D");

View File

@@ -12,7 +12,7 @@
void PrecompileAssembliesStep::OnBuildStarted(CookingData& data)
{
const DotNetAOTModes aotMode = data.Tools->UseAOT();
if (aotMode == DotNetAOTModes::None || EnumHasAllFlags(data.Options, BuildOptions::NoCook))
if (aotMode == DotNetAOTModes::None)
return;
const auto& buildSettings = *BuildSettings::Get();
@@ -69,7 +69,7 @@ bool PrecompileAssembliesStep::Perform(CookingData& data)
const String logFile = data.CacheDirectory / TEXT("AOTLog.txt");
String args = String::Format(
TEXT("-log -logfile=\"{}\" -runDotNetAOT -mutex -platform={} -arch={} -configuration={} -aotMode={} -binaries=\"{}\" -intermediate=\"{}\" {}"),
logFile, platform, architecture, configuration, ToString(aotMode), data.DataOutputPath, data.ManagedCodeOutputPath, data.GetDotnetCommandArg());
logFile, platform, architecture, configuration, ToString(aotMode), data.DataOutputPath, data.ManagedCodeOutputPath, GAME_BUILD_DOTNET_VER);
if (!buildSettings.SkipUnusedDotnetLibsPackaging)
args += TEXT(" -skipUnusedDotnetLibs=false"); // Run AOT on whole class library (not just used libs)
for (const String& define : data.CustomDefines)

View File

@@ -18,8 +18,8 @@ namespace FlaxEditor
private readonly CustomEditorPresenter _presenter;
private CustomEditorWindow _customEditor;
public Win(CustomEditorWindow customEditor, bool hideOnClose, ScrollBars scrollBars)
: base(Editor.Instance, hideOnClose, scrollBars)
public Win(CustomEditorWindow customEditor)
: base(Editor.Instance, false, ScrollBars.Vertical)
{
Title = customEditor.GetType().Name;
_customEditor = customEditor;
@@ -64,9 +64,9 @@ namespace FlaxEditor
/// <summary>
/// Initializes a new instance of the <see cref="CustomEditorWindow"/> class.
/// </summary>
protected CustomEditorWindow(bool hideOnClose = false, ScrollBars scrollBars = ScrollBars.Vertical)
protected CustomEditorWindow()
{
_win = new Win(this, hideOnClose, scrollBars);
_win = new Win(this);
ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin;
}

View File

@@ -749,15 +749,6 @@ namespace FlaxEditor.CustomEditors
}
}
private Actor FindActor(CustomEditor editor)
{
if (editor.Values[0] is Actor actor)
return actor;
if (editor.ParentEditor != null)
return FindActor(editor.ParentEditor);
return null;
}
private Actor FindPrefabRoot(CustomEditor editor)
{
if (editor.Values[0] is Actor actor)
@@ -776,35 +767,32 @@ namespace FlaxEditor.CustomEditors
return FindPrefabRoot(actor.Parent);
}
private SceneObject FindObjectWithPrefabObjectId(Actor actor, ref Guid prefabObjectId, Actor endPoint)
private SceneObject FindObjectWithPrefabObjectId(Actor actor, ref Guid prefabObjectId)
{
var visited = new HashSet<Actor>();
return FindObjectWithPrefabObjectId(actor, ref prefabObjectId, endPoint, visited);
}
private SceneObject FindObjectWithPrefabObjectId(Actor actor, ref Guid prefabObjectId, Actor endPoint, HashSet<Actor> visited)
{
if (visited.Contains(actor) || actor is Scene || actor == endPoint)
return null;
if (actor.PrefabObjectID == prefabObjectId)
return actor;
for (int i = 0; i < actor.ScriptsCount; i++)
{
var script = actor.GetScript(i);
if (script != null && script.PrefabObjectID == prefabObjectId)
return script;
if (actor.GetScript(i).PrefabObjectID == prefabObjectId)
{
var a = actor.GetScript(i);
if (a != null)
return a;
}
}
for (int i = 0; i < actor.ChildrenCount; i++)
{
var child = actor.GetChild(i);
if (child != null && child.PrefabObjectID == prefabObjectId)
return child;
if (actor.GetChild(i).PrefabObjectID == prefabObjectId)
{
var a = actor.GetChild(i);
if (a != null)
return a;
}
}
// Go up in the hierarchy
return FindObjectWithPrefabObjectId(actor.Parent, ref prefabObjectId, endPoint, visited);
return null;
}
/// <summary>
@@ -838,7 +826,7 @@ namespace FlaxEditor.CustomEditors
}
var prefabObjectId = referenceSceneObject.PrefabObjectID;
var prefabInstanceRef = FindObjectWithPrefabObjectId(FindActor(this), ref prefabObjectId, prefabInstanceRoot);
var prefabInstanceRef = FindObjectWithPrefabObjectId(prefabInstanceRoot, ref prefabObjectId);
if (prefabInstanceRef == null)
{
Editor.LogWarning("Missing prefab instance reference in the prefab instance. Cannot revert to it.");

View File

@@ -63,11 +63,6 @@ namespace FlaxEditor.CustomEditors
/// Indication of if the properties window is locked on specific objects.
/// </summary>
public bool LockSelection { get; set; }
/// <summary>
/// Gets the scene editing context.
/// </summary>
public ISceneEditingContext SceneContext { get; }
}
/// <summary>

View File

@@ -1,5 +1,8 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using System.Linq;
using FlaxEditor.Actions;
using FlaxEditor.CustomEditors.Editors;
using FlaxEditor.CustomEditors.Elements;
@@ -7,14 +10,12 @@ using FlaxEditor.GUI;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.GUI.Tree;
using FlaxEditor.Scripting;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Json;
using FlaxEngine.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
namespace FlaxEditor.CustomEditors.Dedicated
{
@@ -239,12 +240,6 @@ namespace FlaxEditor.CustomEditors.Dedicated
node.TextColor = Color.OrangeRed;
node.Text = Utilities.Utils.GetPropertyNameUI(removed.PrefabObject.GetType().Name);
}
// Removed Actor
else if (editor is RemovedActorDummy removedActor)
{
node.TextColor = Color.OrangeRed;
node.Text = $"{removedActor.PrefabObject.Name} ({Utilities.Utils.GetPropertyNameUI(removedActor.PrefabObject.GetType().Name)})";
}
// Actor or Script
else if (editor.Values[0] is SceneObject sceneObject)
{
@@ -300,40 +295,16 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Not used
}
}
private class RemovedActorDummy : CustomEditor
{
/// <summary>
/// The removed prefab object (from the prefab default instance).
/// </summary>
public Actor PrefabObject;
/// <summary>
/// The prefab instance's parent.
/// </summary>
public Actor ParentActor;
/// <summary>
/// The order of the removed actor in the parent.
/// </summary>
public int OrderInParent;
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
// Not used
}
}
private TreeNode ProcessDiff(CustomEditor editor, bool skipIfNotModified = true)
{
// Special case for new Script or child actor added to actor
if ((editor.Values[0] is Script script && !script.HasPrefabLink) || (editor.Values[0] is Actor a && !a.HasPrefabLink))
// Special case for new Script added to actor
if (editor.Values[0] is Script script && !script.HasPrefabLink)
return CreateDiffNode(editor);
// Skip if no change detected
var isRefEdited = editor.Values.IsReferenceValueModified;
if (!isRefEdited && skipIfNotModified && editor is not ScriptsEditor)
if (!isRefEdited && skipIfNotModified)
return null;
TreeNode result = null;
@@ -388,44 +359,6 @@ namespace FlaxEditor.CustomEditors.Dedicated
}
}
// Compare child actors for removed actors.
if (editor is ActorEditor && editor.Values.HasReferenceValue && editor.Values.ReferenceValue is Actor prefabObjectActor)
{
var thisActor = editor.Values[0] as Actor;
for (int i = 0; i < prefabObjectActor.ChildrenCount; i++)
{
var prefabActorChild = prefabObjectActor.Children[i];
if (thisActor == null)
continue;
bool isRemoved = true;
for (int j = 0; j < thisActor.ChildrenCount; j++)
{
var actorChild = thisActor.Children[j];
if (actorChild.PrefabObjectID == prefabActorChild.PrefabObjectID)
{
isRemoved = false;
break;
}
}
if (isRemoved)
{
var dummy = new RemovedActorDummy
{
PrefabObject = prefabActorChild,
ParentActor = thisActor,
OrderInParent = prefabActorChild.OrderInParent,
};
var child = CreateDiffNode(dummy);
if (result == null)
result = CreateDiffNode(editor);
result.AddChild(child);
}
}
}
if (editor is ScriptsEditor && result != null && result.ChildrenCount == 0)
return null;
return result;
}
@@ -505,15 +438,6 @@ namespace FlaxEditor.CustomEditors.Dedicated
Presenter.BuildLayoutOnUpdate();
}
private static void GetAllPrefabObjects(List<object> objects, Actor actor)
{
objects.Add(actor);
objects.AddRange(actor.Scripts);
var children = actor.Children;
foreach (var child in children)
GetAllPrefabObjects(objects, child);
}
private void OnDiffRevert(CustomEditor editor)
{
// Special case for removed Script from actor
@@ -535,22 +459,6 @@ namespace FlaxEditor.CustomEditors.Dedicated
return;
}
// Special case for reverting removed Actors
if (editor is RemovedActorDummy removedActor)
{
Editor.Log("Reverting removed actor changes to prefab (adding it)");
var parentActor = removedActor.ParentActor;
var restored = parentActor.AddChild(removedActor.PrefabObject.GetType());
var prefabId = parentActor.PrefabID;
var prefabObjectId = removedActor.PrefabObject.PrefabObjectID;
string data = JsonSerializer.Serialize(removedActor.PrefabObject);
JsonSerializer.Deserialize(restored, data);
Presenter.Owner.SceneContext.Spawn(restored, parentActor, removedActor.OrderInParent);
Actor.Internal_LinkPrefab(FlaxEngine.Object.GetUnmanagedPtr(restored), ref prefabId, ref prefabObjectId);
return;
}
// Special case for new Script added to actor
if (editor.Values[0] is Script script && !script.HasPrefabLink)
{
@@ -562,37 +470,8 @@ namespace FlaxEditor.CustomEditors.Dedicated
return;
}
// Special case for new Actor added to actor
if (editor.Values[0] is Actor a && !a.HasPrefabLink)
{
Editor.Log("Reverting added actor changes to prefab (removing it)");
// TODO: Keep previous selection.
var context = Presenter.Owner.SceneContext;
context.Select(SceneGraph.SceneGraphFactory.FindNode(a.ID));
context.DeleteSelection();
return;
}
if (Presenter.Undo != null && Presenter.Undo.Enabled)
{
var thisActor = (Actor)Values[0];
var rootActor = thisActor.IsPrefabRoot ? thisActor : thisActor.GetPrefabRoot();
var prefabObjects = new List<object>();
GetAllPrefabObjects(prefabObjects, rootActor);
using (new UndoMultiBlock(Presenter.Undo, prefabObjects, "Revert to Prefab"))
{
editor.RevertToReferenceValue();
editor.RefreshInternal();
}
}
else
{
editor.RevertToReferenceValue();
editor.RefreshInternal();
}
editor.RevertToReferenceValue();
}
}
}

View File

@@ -106,6 +106,7 @@ namespace FlaxEditor.CustomEditors.Editors
_linkButton = new Button
{
BackgroundBrush = new SpriteBrush(Editor.Instance.Icons.Link32),
Parent = LinkedLabel,
Width = 18,
Height = 18,
@@ -188,7 +189,6 @@ namespace FlaxEditor.CustomEditors.Editors
_linkButton.SetColors(backgroundColor);
_linkButton.BorderColor = _linkButton.BorderColorSelected = _linkButton.BorderColorHighlighted = Color.Transparent;
_linkButton.TooltipText = LinkValues ? "Unlinks scale components from uniform scaling" : "Links scale components for uniform scaling";
_linkButton.BackgroundBrush = new SpriteBrush(LinkValues ? Editor.Instance.Icons.Link32 : Editor.Instance.Icons.BrokenLink32);
}
}

View File

@@ -70,9 +70,7 @@ namespace FlaxEditor.CustomEditors.Editors
menu.ItemsContainer.RemoveChildren();
menu.AddButton("Copy", linkedEditor.Copy);
var b = menu.AddButton("Duplicate", () => Editor.Duplicate(Index));
b.Enabled = linkedEditor.CanPaste && !Editor._readOnly;
b = menu.AddButton("Paste", linkedEditor.Paste);
var b = menu.AddButton("Paste", linkedEditor.Paste);
b.Enabled = linkedEditor.CanPaste && !Editor._readOnly;
menu.AddSeparator();
@@ -406,10 +404,8 @@ namespace FlaxEditor.CustomEditors.Editors
var menu = new ContextMenu();
menu.AddButton("Copy", linkedEditor.Copy);
var b = menu.AddButton("Duplicate", () => Editor.Duplicate(Index));
b.Enabled = linkedEditor.CanPaste && !Editor._readOnly;
var paste = menu.AddButton("Paste", linkedEditor.Paste);
paste.Enabled = linkedEditor.CanPaste && !Editor._readOnly;
paste.Enabled = linkedEditor.CanPaste;
if (_canReorder)
{
@@ -745,34 +741,6 @@ namespace FlaxEditor.CustomEditors.Editors
cloned[srcIndex] = tmp;
SetValue(cloned);
}
/// <summary>
/// Duplicates the list item.
/// </summary>
/// <param name="index">The index to duplicate.</param>
public void Duplicate(int index)
{
if (IsSetBlocked)
return;
var count = Count;
var newValues = Allocate(count + 1);
var oldValues = (IList)Values[0];
for (int i = 0; i <= index; i++)
{
newValues[i] = oldValues[i];
}
newValues[index + 1] = Utilities.Utils.CloneValue(oldValues[index]);
for (int i = index + 1; i < count; i++)
{
newValues[i + 1] = oldValues[i];
}
SetValue(newValues);
}
/// <summary>
/// Shifts the specified item at the given index and moves it through the list to the other item. It supports undo.

View File

@@ -22,7 +22,7 @@ internal class UIControlRefPickerControl : FlaxObjectRefPickerControl
/// <inheritdoc />
protected override bool IsValid(Object obj)
{
return obj == null || (obj is UIControl control && ControlType.IsAssignableFrom(control.Control.GetType()));
return obj == null || (obj is UIControl control && control.Control.GetType() == ControlType);
}
}

View File

@@ -14,9 +14,6 @@ namespace FlaxEditor.CustomEditors.GUI
public class PropertiesList : PanelWithMargins
{
// TODO: sync splitter for whole presenter
private const float SplitterPadding = 15;
private const float EditorsMinWidthRatio = 0.4f;
/// <summary>
/// The splitter size (in pixels).
@@ -28,7 +25,6 @@ namespace FlaxEditor.CustomEditors.GUI
private Rectangle _splitterRect;
private bool _splitterClicked, _mouseOverSplitter;
private bool _cursorChanged;
private bool _hasCustomSplitterValue;
/// <summary>
/// Gets or sets the splitter value (always in range [0; 1]).
@@ -70,26 +66,6 @@ namespace FlaxEditor.CustomEditors.GUI
UpdateSplitRect();
}
private void AutoSizeSplitter()
{
if (_hasCustomSplitterValue || !Editor.Instance.Options.Options.Interface.AutoSizePropertiesPanelSplitter)
return;
Font font = Style.Current.FontMedium;
float largestWidth = 0f;
for (int i = 0; i < _element.Labels.Count; i++)
{
Label currentLabel = _element.Labels[i];
Float2 dimensions = font.MeasureText(currentLabel.Text);
float width = dimensions.X + currentLabel.Margin.Left + SplitterPadding;
largestWidth = Mathf.Max(largestWidth, width);
}
SplitterValue = Mathf.Clamp(largestWidth / Width, 0, 1 - EditorsMinWidthRatio);
}
private void UpdateSplitRect()
{
_splitterRect = new Rectangle(Mathf.Clamp(_splitterValue * Width - SplitterSize * 0.5f, 0.0f, Width), 0, SplitterSize, Height);
@@ -146,7 +122,6 @@ namespace FlaxEditor.CustomEditors.GUI
SplitterValue = location.X / Width;
Cursor = CursorType.SizeWE;
_cursorChanged = true;
_hasCustomSplitterValue = true;
}
else if (_mouseOverSplitter)
{
@@ -220,7 +195,6 @@ namespace FlaxEditor.CustomEditors.GUI
// Refresh
UpdateSplitRect();
PerformLayout(true);
AutoSizeSplitter();
}
/// <inheritdoc />

View File

@@ -528,11 +528,7 @@ namespace FlaxEditor
var timeSinceLastSave = Time.UnscaledGameTime - _lastAutoSaveTimer;
var timeToNextSave = options.AutoSaveFrequency * 60.0f - timeSinceLastSave;
if (timeToNextSave <= 0.0f && GetWindows().Any(x => x.GUI.Children.Any(c => c is GUI.ContextMenu.ContextMenuBase)))
{
// Skip aut-save if any context menu is opened to wait for user to end interaction
}
else if (timeToNextSave <= 0.0f || _autoSaveNow)
if (timeToNextSave <= 0.0f || _autoSaveNow)
{
Log("Auto save");
_lastAutoSaveTimer = Time.UnscaledGameTime;

View File

@@ -39,7 +39,6 @@ namespace FlaxEditor
public SpriteHandle Globe32;
public SpriteHandle CamSpeed32;
public SpriteHandle Link32;
public SpriteHandle BrokenLink32;
public SpriteHandle Add32;
public SpriteHandle Left32;
public SpriteHandle Right32;
@@ -95,7 +94,6 @@ namespace FlaxEditor
public SpriteHandle Search64;
public SpriteHandle Bone64;
public SpriteHandle Link64;
public SpriteHandle BrokenLink64;
public SpriteHandle Build64;
public SpriteHandle Add64;
public SpriteHandle ShipIt64;

View File

@@ -117,10 +117,9 @@ namespace FlaxEditor.GUI.ContextMenu
public ContextMenuBase()
: base(0, 0, 120, 32)
{
Visible = false;
AutoFocus = true;
_direction = ContextMenuDirection.RightDown;
Visible = false;
_isSubMenu = true;
}

View File

@@ -76,8 +76,6 @@ namespace FlaxEditor.GUI.Dialogs
public ColorSelector(float wheelSize)
: base(0, 0, wheelSize, wheelSize)
{
AutoFocus = true;
_colorWheelSprite = Editor.Instance.Icons.ColorWheel128;
_wheelRect = new Rectangle(0, 0, wheelSize, wheelSize);
}

View File

@@ -1,7 +1,6 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.Options;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -14,12 +13,12 @@ namespace FlaxEditor.GUI.Docking
public class DockPanelProxy : ContainerControl
{
private DockPanel _panel;
private InterfaceOptions.TabCloseButtonVisibility closeButtonVisibility;
private double _dragEnterTime = -1;
private float _tabHeight = Editor.Instance.Options.Options.Interface.TabHeight;
private bool _useMinimumTabWidth = Editor.Instance.Options.Options.Interface.UseMinimumTabWidth;
private float _minimumTabWidth = Editor.Instance.Options.Options.Interface.MinimumTabWidth;
private readonly bool _hideTabForSingleTab = Utilities.Utils.HideSingleTabWindowTabBars();
#if PLATFORM_WINDOWS
private const bool HideTabForSingleTab = true;
#else
private const bool HideTabForSingleTab = false;
#endif
/// <summary>
/// The is mouse down flag (left button).
@@ -61,8 +60,8 @@ namespace FlaxEditor.GUI.Docking
/// </summary>
public DockWindow StartDragAsyncWindow;
private Rectangle HeaderRectangle => new Rectangle(0, 0, Width, _tabHeight);
private bool IsSingleFloatingWindow => _hideTabForSingleTab && _panel.TabsCount == 1 && _panel.IsFloating && _panel.ChildPanelsCount == 0;
private Rectangle HeaderRectangle => new Rectangle(0, 0, Width, DockPanel.DefaultHeaderHeight);
private bool IsSingleFloatingWindow => HideTabForSingleTab && _panel.TabsCount == 1 && _panel.IsFloating && _panel.ChildPanelsCount == 0;
/// <summary>
/// Initializes a new instance of the <see cref="DockPanelProxy"/> class.
@@ -71,17 +70,11 @@ namespace FlaxEditor.GUI.Docking
internal DockPanelProxy(DockPanel panel)
: base(0, 0, 64, 64)
{
AutoFocus = false;
_panel = panel;
AnchorPreset = AnchorPresets.StretchAll;
Offsets = Margin.Zero;
Editor.Instance.Options.OptionsChanged += OnEditorOptionsChanged;
OnEditorOptionsChanged(Editor.Instance.Options.Options);
}
private void OnEditorOptionsChanged(EditorOptions options)
{
closeButtonVisibility = options.Interface.ShowTabCloseButton;
}
private DockWindow GetTabAtPos(Float2 position, out bool closeButton)
@@ -92,11 +85,11 @@ namespace FlaxEditor.GUI.Docking
var tabsCount = _panel.TabsCount;
if (tabsCount == 1)
{
var crossRect = new Rectangle(Width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (HeaderRectangle.Height - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize);
var crossRect = new Rectangle(Width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (DockPanel.DefaultHeaderHeight - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize);
if (HeaderRectangle.Contains(position))
{
closeButton = crossRect.Contains(position);
result = _panel.GetTab(0);
closeButton = crossRect.Contains(position) && IsCloseButtonVisible(result, closeButtonVisibility);
}
}
else
@@ -105,17 +98,15 @@ namespace FlaxEditor.GUI.Docking
for (int i = 0; i < tabsCount; i++)
{
var tab = _panel.GetTab(i);
float width = CalculateTabWidth(tab, closeButtonVisibility);
if (_useMinimumTabWidth && width < _minimumTabWidth)
width = _minimumTabWidth;
var tabRect = new Rectangle(x, 0, width, HeaderRectangle.Height);
var titleSize = tab.TitleSize;
var iconWidth = tab.Icon.IsValid ? DockPanel.DefaultButtonsSize + DockPanel.DefaultLeftTextMargin : 0;
var width = titleSize.X + DockPanel.DefaultButtonsSize + 2 * DockPanel.DefaultButtonsMargin + DockPanel.DefaultLeftTextMargin + DockPanel.DefaultRightTextMargin + iconWidth;
var tabRect = new Rectangle(x, 0, width, DockPanel.DefaultHeaderHeight);
var isMouseOver = tabRect.Contains(position);
if (isMouseOver)
{
var crossRect = new Rectangle(x + width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (HeaderRectangle.Height - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize);
closeButton = crossRect.Contains(position) && IsCloseButtonVisible(tab, closeButtonVisibility);
var crossRect = new Rectangle(x + width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (DockPanel.DefaultHeaderHeight - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize);
closeButton = crossRect.Contains(position);
result = tab;
break;
}
@@ -126,24 +117,6 @@ namespace FlaxEditor.GUI.Docking
return result;
}
private bool IsCloseButtonVisible(DockWindow win, InterfaceOptions.TabCloseButtonVisibility visibilityMode)
{
return visibilityMode != InterfaceOptions.TabCloseButtonVisibility.Never &&
(visibilityMode == InterfaceOptions.TabCloseButtonVisibility.Always ||
(visibilityMode == InterfaceOptions.TabCloseButtonVisibility.SelectedTab && _panel.SelectedTab == win));
}
private float CalculateTabWidth(DockWindow win, InterfaceOptions.TabCloseButtonVisibility visibilityMode)
{
var iconWidth = win.Icon.IsValid ? DockPanel.DefaultButtonsSize + DockPanel.DefaultLeftTextMargin : 0;
var width = win.TitleSize.X + DockPanel.DefaultLeftTextMargin + DockPanel.DefaultRightTextMargin + iconWidth;
if (IsCloseButtonVisible(win, visibilityMode))
width += 2 * DockPanel.DefaultButtonsMargin + DockPanel.DefaultButtonsSize;
return width;
}
private void GetTabRect(DockWindow win, out Rectangle bounds)
{
FlaxEngine.Assertions.Assert.IsTrue(_panel.ContainsTab(win));
@@ -161,10 +134,10 @@ namespace FlaxEditor.GUI.Docking
{
var tab = _panel.GetTab(i);
var titleSize = tab.TitleSize;
float width = CalculateTabWidth(tab, closeButtonVisibility);
float width = titleSize.X + DockPanel.DefaultButtonsSize + 2 * DockPanel.DefaultButtonsMargin + DockPanel.DefaultLeftTextMargin + DockPanel.DefaultRightTextMargin;
if (tab == win)
{
bounds = new Rectangle(x, 0, width, HeaderRectangle.Height);
bounds = new Rectangle(x, 0, width, DockPanel.DefaultHeaderHeight);
return;
}
x += width;
@@ -244,7 +217,7 @@ namespace FlaxEditor.GUI.Docking
{
Render2D.DrawSprite(
tab.Icon,
new Rectangle(DockPanel.DefaultLeftTextMargin, (HeaderRectangle.Height - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize),
new Rectangle(DockPanel.DefaultLeftTextMargin, (DockPanel.DefaultHeaderHeight - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize),
style.Foreground);
}
@@ -253,20 +226,17 @@ namespace FlaxEditor.GUI.Docking
Render2D.DrawText(
style.FontMedium,
tab.Title,
new Rectangle(DockPanel.DefaultLeftTextMargin + iconWidth, 0, Width - DockPanel.DefaultLeftTextMargin - DockPanel.DefaultButtonsSize - 2 * DockPanel.DefaultButtonsMargin, HeaderRectangle.Height),
new Rectangle(DockPanel.DefaultLeftTextMargin + iconWidth, 0, Width - DockPanel.DefaultLeftTextMargin - DockPanel.DefaultButtonsSize - 2 * DockPanel.DefaultButtonsMargin, DockPanel.DefaultHeaderHeight),
style.Foreground,
TextAlignment.Near,
TextAlignment.Center);
if (IsCloseButtonVisible(tab, closeButtonVisibility))
{
// Draw cross
var crossRect = new Rectangle(Width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (HeaderRectangle.Height - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize);
bool isMouseOverCross = isMouseOver && crossRect.Contains(MousePosition);
if (isMouseOverCross)
Render2D.FillRectangle(crossRect, (containsFocus ? style.BackgroundSelected : style.LightBackground) * 1.3f);
Render2D.DrawSprite(style.Cross, crossRect, isMouseOverCross ? style.Foreground : style.ForegroundGrey);
}
// Draw cross
var crossRect = new Rectangle(Width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (DockPanel.DefaultHeaderHeight - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize);
bool isMouseOverCross = isMouseOver && crossRect.Contains(MousePosition);
if (isMouseOverCross)
Render2D.FillRectangle(crossRect, (containsFocus ? style.BackgroundSelected : style.LightBackground) * 1.3f);
Render2D.DrawSprite(style.Cross, crossRect, isMouseOverCross ? style.Foreground : style.ForegroundGrey);
}
else
{
@@ -280,14 +250,10 @@ namespace FlaxEditor.GUI.Docking
// Cache data
var tab = _panel.GetTab(i);
var tabColor = Color.Black;
var titleSize = tab.TitleSize;
var iconWidth = tab.Icon.IsValid ? DockPanel.DefaultButtonsSize + DockPanel.DefaultLeftTextMargin : 0;
float width = CalculateTabWidth(tab, closeButtonVisibility);
if (_useMinimumTabWidth && width < _minimumTabWidth)
width = _minimumTabWidth;
var tabRect = new Rectangle(x, 0, width, headerRect.Height);
var width = titleSize.X + DockPanel.DefaultButtonsSize + 2 * DockPanel.DefaultButtonsMargin + DockPanel.DefaultLeftTextMargin + DockPanel.DefaultRightTextMargin + iconWidth;
var tabRect = new Rectangle(x, 0, width, DockPanel.DefaultHeaderHeight);
var isMouseOver = tabRect.Contains(MousePosition);
var isSelected = _panel.SelectedTab == tab;
@@ -314,7 +280,7 @@ namespace FlaxEditor.GUI.Docking
{
Render2D.DrawSprite(
tab.Icon,
new Rectangle(x + DockPanel.DefaultLeftTextMargin, (HeaderRectangle.Height - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize),
new Rectangle(x + DockPanel.DefaultLeftTextMargin, (DockPanel.DefaultHeaderHeight - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize),
style.Foreground);
}
@@ -323,27 +289,27 @@ namespace FlaxEditor.GUI.Docking
Render2D.DrawText(
style.FontMedium,
tab.Title,
new Rectangle(x + DockPanel.DefaultLeftTextMargin + iconWidth, 0, 10000, HeaderRectangle.Height),
new Rectangle(x + DockPanel.DefaultLeftTextMargin + iconWidth, 0, 10000, DockPanel.DefaultHeaderHeight),
style.Foreground,
TextAlignment.Near,
TextAlignment.Center);
// Draw cross
if (IsCloseButtonVisible(tab, closeButtonVisibility))
if (isSelected || isMouseOver)
{
var crossRect = new Rectangle(x + width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (HeaderRectangle.Height - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize);
var crossRect = new Rectangle(x + width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (DockPanel.DefaultHeaderHeight - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize);
bool isMouseOverCross = isMouseOver && crossRect.Contains(MousePosition);
if (isMouseOverCross)
Render2D.FillRectangle(crossRect, tabColor * 1.3f);
Render2D.DrawSprite(style.Cross, crossRect, isMouseOverCross ? style.Foreground : style.ForegroundGrey);
}
// Set the start position for the next tab
// Move
x += width;
}
// Draw selected tab strip
Render2D.FillRectangle(new Rectangle(0, HeaderRectangle.Height - 2, Width, 2), containsFocus ? style.BackgroundSelected : style.BackgroundNormal);
Render2D.FillRectangle(new Rectangle(0, DockPanel.DefaultHeaderHeight - 2, Width, 2), containsFocus ? style.BackgroundSelected : style.BackgroundNormal);
}
}
@@ -576,7 +542,7 @@ namespace FlaxEditor.GUI.Docking
if (IsSingleFloatingWindow)
rect = new Rectangle(0, 0, Width, Height);
else
rect = new Rectangle(0, HeaderRectangle.Height, Width, Height - HeaderRectangle.Height);
rect = new Rectangle(0, DockPanel.DefaultHeaderHeight, Width, Height - DockPanel.DefaultHeaderHeight);
}
private DragDropEffect TrySelectTabUnderLocation(ref Float2 location)

View File

@@ -368,8 +368,6 @@ namespace FlaxEditor.GUI.Input
public SliderControl(float value, float x = 0, float y = 0, float width = 120, float min = float.MinValue, float max = float.MaxValue)
: base(x, y, width, TextBox.DefaultHeight)
{
AutoFocus = true;
_min = min;
_max = max;
_value = Mathf.Clamp(value, min, max);

View File

@@ -514,15 +514,20 @@ namespace FlaxEditor.GUI
var items = ItemsPanel.Children;
for (int i = 0; i < items.Count; i++)
{
var currentItem = items[i];
if (currentItem is Item item && item.Visible)
if (items[i] is Item item && item.Visible)
result.Add(item);
else if (currentItem is DropPanel category && (!ignoreFoldedCategories || !category.IsClosed) && currentItem.Visible)
}
if (_categoryPanels != null)
{
for (int i = 0; i < _categoryPanels.Count; i++)
{
var category = _categoryPanels[i];
if (!category.Visible || (ignoreFoldedCategories && category is DropPanel panel && panel.IsClosed))
continue;
for (int j = 0; j < category.Children.Count; j++)
{
if (category.Children[j] is Item categoryItem && categoryItem.Visible)
result.Add(categoryItem);
if (category.Children[j] is Item item2 && item2.Visible)
result.Add(item2);
}
}
}
@@ -586,6 +591,10 @@ namespace FlaxEditor.GUI
var items = GetVisibleItems(!controlDown);
var focusedIndex = items.IndexOf(focusedItem);
// If the user hasn't selected anything yet and is holding control, focus first folded item
if (focusedIndex == -1 && controlDown)
focusedIndex = GetVisibleItems(true).Count - 1;
int delta = key == KeyboardKeys.ArrowDown ? -1 : 1;
int nextIndex = Mathf.Wrap(focusedIndex - delta, 0, items.Count - 1);
var nextItem = items[nextIndex];

View File

@@ -11,9 +11,6 @@ namespace FlaxEditor.GUI
/// <seealso cref="FlaxEngine.GUI.Panel" />
public class NavigationBar : Panel
{
private float _toolstripHeight = 0;
private Margin _toolstripMargin;
/// <summary>
/// The default buttons margin.
/// </summary>
@@ -53,42 +50,9 @@ namespace FlaxEditor.GUI
{
if (toolstrip == null)
return;
if (_toolstripHeight <= 0.0f)
{
// Cache initial toolstrip state
_toolstripHeight = toolstrip.Height;
_toolstripMargin = toolstrip.ItemsMargin;
}
// Control toolstrip bottom margin to prevent navigation bar scroll going over the buttons
var toolstripLocked = toolstrip.IsLayoutLocked;
toolstrip.IsLayoutLocked = true;
var toolstripHeight = _toolstripHeight;
var toolstripMargin = _toolstripMargin;
if (HScrollBar.Visible)
{
float scrollMargin = 8;
toolstripHeight += scrollMargin;
toolstripMargin.Bottom += scrollMargin;
}
toolstrip.Height = toolstripHeight;
toolstrip.IsLayoutLocked = toolstripLocked;
toolstrip.ItemsMargin = toolstripMargin;
var lastToolstripButton = toolstrip.LastButton;
var parentSize = Parent.Size;
Bounds = new Rectangle(lastToolstripButton.Right + 8.0f, 0, parentSize.X - X - 8.0f, toolstrip.Height);
}
/// <inheritdoc />
public override void PerformLayout(bool force = false)
{
base.PerformLayout(force);
// Stretch excluding toolstrip margin to fill the space
if (Parent is ToolStrip toolStrip)
Height = toolStrip.Height;
}
}
}

View File

@@ -130,10 +130,6 @@ namespace FlaxEditor.GUI
/// <returns>Created popup.</returns>
public static RenamePopup Show(Control control, Rectangle area, string value, bool isMultiline)
{
// hardcoded flushing layout for tree controls
if (control is Tree.TreeNode treeNode && treeNode.ParentTree != null)
treeNode.ParentTree.FlushPendingPerformLayout();
// Calculate the control size in the window space to handle scaled controls
var upperLeft = control.PointToWindow(area.UpperLeft);
var bottomRight = control.PointToWindow(area.BottomRight);

View File

@@ -13,7 +13,15 @@ namespace FlaxEditor.GUI
/// <seealso cref="FlaxEngine.GUI.ContainerControl" />
public class ToolStrip : ContainerControl
{
private Margin _itemsMargin;
/// <summary>
/// The default margin vertically.
/// </summary>
public const int DefaultMarginV = 1;
/// <summary>
/// The default margin horizontally.
/// </summary>
public const int DefaultMarginH = 2;
/// <summary>
/// Event fired when button gets clicked with the primary mouse button.
@@ -58,26 +66,10 @@ namespace FlaxEditor.GUI
}
}
/// <summary>
/// Gets or sets the space around items.
/// </summary>
public Margin ItemsMargin
{
get => _itemsMargin;
set
{
if (_itemsMargin != value)
{
_itemsMargin = value;
PerformLayout();
}
}
}
/// <summary>
/// Gets the height for the items.
/// </summary>
public float ItemsHeight => Height - _itemsMargin.Height;
public float ItemsHeight => Height - 2 * DefaultMarginV;
/// <summary>
/// Initializes a new instance of the <see cref="ToolStrip"/> class.
@@ -90,7 +82,6 @@ namespace FlaxEditor.GUI
AnchorPreset = AnchorPresets.HorizontalStretchTop;
BackgroundColor = Style.Current.LightBackground;
Offsets = new Margin(0, 0, y, height * Editor.Instance.Options.Options.Interface.IconsScale);
_itemsMargin = new Margin(2, 2, 1, 1);
}
/// <summary>
@@ -170,7 +161,7 @@ namespace FlaxEditor.GUI
protected override void PerformLayoutBeforeChildren()
{
// Arrange controls
float x = _itemsMargin.Left;
float x = DefaultMarginH;
float h = ItemsHeight;
for (int i = 0; i < _children.Count; i++)
{
@@ -178,8 +169,8 @@ namespace FlaxEditor.GUI
if (c.Visible)
{
var w = c.Width;
c.Bounds = new Rectangle(x, _itemsMargin.Top, w, h);
x += w + _itemsMargin.Width;
c.Bounds = new Rectangle(x, DefaultMarginV, w, h);
x += w + DefaultMarginH;
}
}
}

View File

@@ -41,7 +41,6 @@ namespace FlaxEditor.GUI.Tree
private Margin _margin;
private bool _autoSize = true;
private bool _deferLayoutUpdate = false;
private TreeNode _lastSelectedNode;
/// <summary>
/// The TreeNode that is being dragged over. This could have a value when not dragging.
@@ -68,7 +67,7 @@ namespace FlaxEditor.GUI.Tree
/// Gets the first selected node or null.
/// </summary>
public TreeNode SelectedNode => Selection.Count > 0 ? Selection[0] : null;
/// <summary>
/// Allow nodes to Draw the root tree line.
/// </summary>
@@ -365,19 +364,6 @@ namespace FlaxEditor.GUI.Tree
BulkSelectUpdateExpanded(false);
}
/// <summary>
/// Flushes any pending layout perming action that has been delayed until next update to optimize performance of the complex tree hierarchy.
/// </summary>
public void FlushPendingPerformLayout()
{
if (_deferLayoutUpdate)
{
base.PerformLayout();
AfterDeferredLayout?.Invoke();
_deferLayoutUpdate = false;
}
}
/// <inheritdoc />
public override void PerformLayout(bool force = false)
{
@@ -392,31 +378,25 @@ namespace FlaxEditor.GUI.Tree
public override void Update(float deltaTime)
{
if (_deferLayoutUpdate)
FlushPendingPerformLayout();
var window = Root;
bool shiftDown = window.GetKey(KeyboardKeys.Shift);
bool keyUpArrow = window.GetKey(KeyboardKeys.ArrowUp);
bool keyDownArrow = window.GetKey(KeyboardKeys.ArrowDown);
{
base.PerformLayout();
AfterDeferredLayout?.Invoke();
_deferLayoutUpdate = false;
}
// Use last selection for last selected node if sift is down
if (Selection.Count < 2)
_lastSelectedNode = null;
else if (shiftDown)
_lastSelectedNode ??= Selection[^1];
// Skip root to prevent blocking input
if (_lastSelectedNode != null && _lastSelectedNode.IsRoot)
_lastSelectedNode = null;
var node = _lastSelectedNode ?? SelectedNode;
var node = SelectedNode;
// Check if has focus and if any node is focused and it isn't a root
if (ContainsFocus && node != null && node.AutoFocus)
{
var window = Root;
if (window.GetKeyDown(KeyboardKeys.ArrowUp) || window.GetKeyDown(KeyboardKeys.ArrowDown))
_keyUpdateTime = KeyUpdateTimeout;
if (_keyUpdateTime >= KeyUpdateTimeout && window is WindowRootControl windowRoot && windowRoot.Window.IsFocused)
{
bool keyUpArrow = window.GetKey(KeyboardKeys.ArrowUp);
bool keyDownArrow = window.GetKey(KeyboardKeys.ArrowDown);
// Check if arrow flags are different
if (keyDownArrow != keyUpArrow)
{
@@ -426,38 +406,24 @@ namespace FlaxEditor.GUI.Tree
Assert.AreNotEqual(-1, myIndex);
// Up
List<TreeNode> toSelect = new List<TreeNode>();
if (shiftDown && _supportMultiSelect)
{
toSelect.AddRange(Selection);
}
TreeNode toSelect = null;
if (keyUpArrow)
{
if (myIndex == 0)
{
// Select parent
if (toSelect.Contains(parentNode))
toSelect.Remove(node);
else if (parentNode != null)
toSelect.Add(parentNode);
_lastSelectedNode = parentNode;
toSelect = parentNode;
}
else
{
// Select previous parent child
var select = nodeParent.GetChild(myIndex - 1) as TreeNode;
toSelect = nodeParent.GetChild(myIndex - 1) as TreeNode;
// Select last child if is valid and expanded and has any children
if (select != null && select.IsExpanded && select.HasAnyVisibleChild)
if (toSelect != null && toSelect.IsExpanded && toSelect.HasAnyVisibleChild)
{
select = select.GetChild(select.ChildrenCount - 1) as TreeNode;
toSelect = toSelect.GetChild(toSelect.ChildrenCount - 1) as TreeNode;
}
if (select == null || toSelect.Contains(select))
toSelect.Remove(node);
else
toSelect.Add(select);
_lastSelectedNode = select;
}
}
// Down
@@ -466,48 +432,32 @@ namespace FlaxEditor.GUI.Tree
if (node.IsExpanded && node.HasAnyVisibleChild)
{
// Select the first child
var select = node.GetChild(0) as TreeNode;
if (select == null || toSelect.Contains(select))
toSelect.Remove(node);
else
toSelect.Add(select);
_lastSelectedNode = select;
toSelect = node.GetChild(0) as TreeNode;
}
else if (myIndex == nodeParent.ChildrenCount - 1)
{
// Select next node after parent
TreeNode select = null;
while (parentNode != null && select == null)
while (parentNode != null && toSelect == null)
{
int parentIndex = parentNode.IndexInParent;
if (parentIndex != -1 && parentIndex < parentNode.Parent.ChildrenCount - 1)
{
select = parentNode.Parent.GetChild(parentIndex + 1) as TreeNode;
toSelect = parentNode.Parent.GetChild(parentIndex + 1) as TreeNode;
}
parentNode = parentNode.Parent as TreeNode;
}
if (select == null || toSelect.Contains(select))
toSelect.Remove(node);
else
toSelect.Add(select);
_lastSelectedNode = select;
}
else
{
// Select next parent child
var select = nodeParent.GetChild(myIndex + 1) as TreeNode;
if (select == null || toSelect.Contains(select))
toSelect.Remove(node);
else
toSelect.Add(select);
_lastSelectedNode = select;
toSelect = nodeParent.GetChild(myIndex + 1) as TreeNode;
}
}
if (toSelect.Count > 0)
if (toSelect != null && toSelect.AutoFocus)
{
// Select
Select(toSelect);
_lastSelectedNode?.Focus();
toSelect.Focus();
}
// Reset time

View File

@@ -319,8 +319,6 @@ namespace FlaxEditor.GUI.Tree
public TreeNode(bool canChangeOrder, SpriteHandle iconCollapsed, SpriteHandle iconOpened)
: base(0, 0, 64, 16)
{
AutoFocus = true;
_canChangeOrder = canChangeOrder;
_animationProgress = 1.0f;
_cachedHeight = _headerHeight;

View File

@@ -155,7 +155,6 @@ namespace FlaxEditor.Gizmo
// Ensure player is not moving objects
if (ActiveAxis != Axis.None)
return;
Profiler.BeginEvent("Pick");
// Get mouse ray and try to hit any object
var ray = Owner.MouseRay;
@@ -244,8 +243,6 @@ namespace FlaxEditor.Gizmo
{
sceneEditing.Deselect();
}
Profiler.EndEvent();
}
/// <inheritdoc />

View File

@@ -11,7 +11,6 @@
#include "Engine/Scripting/ManagedCLR/MClass.h"
#include "Engine/Scripting/ManagedCLR/MException.h"
#include "Engine/Scripting/Internal/MainThreadManagedInvokeAction.h"
#include "Engine/Platform/WindowsManager.h"
#include "Engine/Content/Assets/VisualScript.h"
#include "Engine/Content/Content.h"
#include "Engine/Level/Actor.h"
@@ -628,14 +627,6 @@ void ManagedEditor::WipeOutLeftoverSceneObjects()
ObjectsRemovalService::Flush();
}
Array<Window*> ManagedEditor::GetWindows()
{
WindowsManager::WindowsLocker.Lock();
auto result = WindowsManager::Windows;
WindowsManager::WindowsLocker.Unlock();
return result;
}
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 Array<Window*> GetWindows();
private:
void OnEditorAssemblyLoaded(MAssembly* assembly);

View File

@@ -254,29 +254,18 @@ namespace FlaxEditor.Modules
PrefabApplying?.Invoke(prefab, instance);
// When applying changes to prefab from actor in level ignore it's root transformation (see ActorEditor.ProcessDiff)
Actor prefabRoot = null;
var originalTransform = instance.LocalTransform;
var originalName = instance.Name;
if (instance.HasScene)
if (instance.IsPrefabRoot && instance.HasScene)
{
prefabRoot = instance.GetPrefabRoot();
if (prefabRoot != null && prefabRoot.IsPrefabRoot && instance.HasScene)
{
var defaultInstance = prefab.GetDefaultInstance();
originalTransform = prefabRoot.LocalTransform;
originalName = prefabRoot.Name;
prefabRoot.LocalTransform = defaultInstance.Transform;
prefabRoot.Name = defaultInstance.Name;
}
instance.LocalTransform = prefab.GetDefaultInstance().Transform;
instance.Name = prefab.GetDefaultInstance().Name;
}
// Call backend
var failed = PrefabManager.Internal_ApplyAll(FlaxEngine.Object.GetUnmanagedPtr(instance));
if (prefabRoot != null)
{
prefabRoot.LocalTransform = originalTransform;
prefabRoot.Name = originalName;
}
instance.LocalTransform = originalTransform;
instance.Name = originalName;
if (failed)
throw new Exception("Failed to apply the prefab. See log to learn more.");

View File

@@ -569,10 +569,6 @@ namespace FlaxEditor.Modules
return;
}
// Skip if already added
if (SceneGraphFactory.Nodes.ContainsKey(actor.ID))
return;
var node = SceneGraphFactory.BuildActorNode(actor);
if (node != null)
{

View File

@@ -54,9 +54,6 @@ namespace FlaxEditor.Modules.SourceCodeEditing
case CodeEditorTypes.VS2022:
Name = "Visual Studio 2022";
break;
case CodeEditorTypes.VS2026:
Name = "Visual Studio 2026";
break;
case CodeEditorTypes.VSCode:
Name = "Visual Studio Code";
break;
@@ -113,7 +110,6 @@ namespace FlaxEditor.Modules.SourceCodeEditing
case CodeEditorTypes.VS2017:
case CodeEditorTypes.VS2019:
case CodeEditorTypes.VS2022:
case CodeEditorTypes.VS2026:
// TODO: finish dynamic files adding to the project
//Editor.Instance.ProgressReporting.GenerateScriptsProjectFiles.RunAsync();
break;

View File

@@ -652,47 +652,43 @@ namespace FlaxEditor.Options
#endregion
#region Node Editors
#region Node editors
[DefaultValue(typeof(InputBinding), "Shift+W")]
[EditorDisplay("Node Editors"), EditorOrder(4500)]
[EditorDisplay("Node editors"), EditorOrder(4500)]
public InputBinding NodesAlignTop = new InputBinding(KeyboardKeys.W, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "Shift+A")]
[EditorDisplay("Node Editors"), EditorOrder(4510)]
[EditorDisplay("Node editors"), EditorOrder(4510)]
public InputBinding NodesAlignLeft = new InputBinding(KeyboardKeys.A, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "Shift+S")]
[EditorDisplay("Node Editors"), EditorOrder(4520)]
[EditorDisplay("Node editors"), EditorOrder(4520)]
public InputBinding NodesAlignBottom = new InputBinding(KeyboardKeys.S, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "Shift+D")]
[EditorDisplay("Node Editors"), EditorOrder(4530)]
[EditorDisplay("Node editors"), EditorOrder(4530)]
public InputBinding NodesAlignRight = new InputBinding(KeyboardKeys.D, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "Alt+Shift+W")]
[EditorDisplay("Node Editors"), EditorOrder(4540)]
[EditorDisplay("Node editors"), EditorOrder(4540)]
public InputBinding NodesAlignMiddle = new InputBinding(KeyboardKeys.W, KeyboardKeys.Shift, KeyboardKeys.Alt);
[DefaultValue(typeof(InputBinding), "Alt+Shift+S")]
[EditorDisplay("Node Editors"), EditorOrder(4550)]
[EditorDisplay("Node editors"), EditorOrder(4550)]
public InputBinding NodesAlignCenter = new InputBinding(KeyboardKeys.S, KeyboardKeys.Shift, KeyboardKeys.Alt);
[DefaultValue(typeof(InputBinding), "Q")]
[EditorDisplay("Node Editors"), EditorOrder(4560)]
[EditorDisplay("Node editors"), EditorOrder(4560)]
public InputBinding NodesAutoFormat = new InputBinding(KeyboardKeys.Q);
[DefaultValue(typeof(InputBinding), "Shift+Q")]
[EditorDisplay("Node Editors"), EditorOrder(4560)]
public InputBinding NodesStraightenConnections = new InputBinding(KeyboardKeys.Q, KeyboardKeys.Shift);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Node editors"), EditorOrder(4570)]
public InputBinding NodesDistributeHorizontal = new InputBinding(KeyboardKeys.None);
[DefaultValue(typeof(InputBinding), "Alt+W")]
[EditorDisplay("Node Editors"), EditorOrder(4570)]
public InputBinding NodesDistributeHorizontal = new InputBinding(KeyboardKeys.W, KeyboardKeys.Alt);
[DefaultValue(typeof(InputBinding), "Alt+A")]
[EditorDisplay("Node Editors"), EditorOrder(4580)]
public InputBinding NodesDistributeVertical = new InputBinding(KeyboardKeys.A, KeyboardKeys.Alt);
[DefaultValue(typeof(InputBinding), "None")]
[EditorDisplay("Node editors"), EditorOrder(4580)]
public InputBinding NodesDistributeVertical = new InputBinding(KeyboardKeys.None);
#endregion
}

View File

@@ -76,25 +76,6 @@ namespace FlaxEditor.Options
DockBottom = DockState.DockBottom
}
/// <summary>
/// Options for the visibility status of the tab close button.
/// </summary>
public enum TabCloseButtonVisibility
{
/// <summary>
/// Never show the close button.
/// </summary>
Never,
/// <summary>
/// Show the close button on tabs that are currently selected.
/// </summary>
SelectedTab,
/// <summary>
/// Show the close button on all tabs that can be closed.
/// </summary>
Always
}
/// <summary>
/// Options for the action taken by the play button.
/// </summary>
@@ -213,6 +194,13 @@ namespace FlaxEditor.Options
[DefaultValue(1.0f), Limit(0.1f, 10.0f)]
[EditorDisplay("Interface"), EditorOrder(10), Tooltip("Editor User Interface scale. Applied to all UI elements, windows and text. Can be used to scale the interface up on a bigger display. Editor restart required.")]
public float InterfaceScale { get; set; } = 1.0f;
/// <summary>
/// Gets or sets a value indicating whether use native window title bar decorations in child windows. Editor restart required.
/// </summary>
[DefaultValue(WindowDecorationsType.AutoChildOnly)]
[EditorDisplay("Interface"), EditorOrder(70), Tooltip("Determines whether use native window title bar decorations. Editor restart required.")]
public WindowDecorationsType WindowDecorations { get; set; } = WindowDecorationsType.AutoChildOnly;
/// <summary>
/// Gets or sets a value indicating whether show selected camera preview in the editor window.
@@ -221,6 +209,20 @@ namespace FlaxEditor.Options
[EditorDisplay("Interface"), EditorOrder(80), Tooltip("Determines whether show selected camera preview in the edit window.")]
public bool ShowSelectedCameraPreview { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether center mouse position on window focus in play mode. Helps when working with games that lock mouse cursor.
/// </summary>
[DefaultValue(false)]
[EditorDisplay("Interface", "Center Mouse On Game Window Focus"), EditorOrder(100), Tooltip("Determines whether center mouse position on window focus in play mode. Helps when working with games that lock mouse cursor.")]
public bool CenterMouseOnGameWinFocus { get; set; } = false;
/// <summary>
/// Gets or sets the method window opening.
/// </summary>
[DefaultValue(DockStateProxy.Float)]
[EditorDisplay("Interface", "New Window Location"), EditorOrder(150), Tooltip("Define the opening method for new windows, open in a new tab by default.")]
public DockStateProxy NewWindowLocation { get; set; } = DockStateProxy.Float;
/// <summary>
/// Gets or sets the editor icons scale. Editor restart required.
/// </summary>
@@ -256,13 +258,6 @@ namespace FlaxEditor.Options
[EditorDisplay("Interface"), EditorOrder(310)]
public bool SeparateValueAndUnit { get; set; }
/// <summary>
/// Gets or sets the option to auto size the Properties panel splitter based on the longest property name. Editor restart recommended.
/// </summary>
[DefaultValue(false)]
[EditorDisplay("Interface"), EditorOrder(311)]
public bool AutoSizePropertiesPanelSplitter { get; set; }
/// <summary>
/// Gets or sets tree line visibility.
/// </summary>
@@ -296,73 +291,6 @@ namespace FlaxEditor.Options
[EditorDisplay("Interface"), EditorOrder(322)]
public bool ScrollToScriptOnAdd { get; set; } = true;
#if PLATFORM_SDL
/// <summary>
/// Gets or sets a value indicating whether use native window title bar decorations in child windows. Editor restart required.
/// </summary>
[DefaultValue(WindowDecorationsType.AutoChildOnly)]
[EditorDisplay("Interface"), EditorOrder(70), Tooltip("Determines whether use native window title bar decorations. Editor restart required.")]
public WindowDecorationsType WindowDecorations { get; set; } = WindowDecorationsType.AutoChildOnly;
#elif PLATFORM_WINDOWS
/// <summary>
/// Gets or sets a value indicating whether use native window title bar. Editor restart required.
/// </summary>
[DefaultValue(false)]
[EditorDisplay("Tabs & Windows"), EditorOrder(70), Tooltip("Determines whether use native window title bar. Editor restart required.")]
public bool UseNativeWindowSystem { get; set; } = false;
#endif
#if PLATFORM_SDL || PLATFORM_WINDOWS
/// <summary>
/// Gets or sets a value indicating whether a window containing a single tabs hides the tab bar. Editor restart recommended.
/// </summary>
[DefaultValue(true)]
[EditorDisplay("Tabs & Windows", "Hide Single-Tab Window Tab Bars"), EditorOrder(71)]
public bool HideSingleTabWindowTabBars { get; set; } = true;
#endif
/// <summary>
/// Gets or sets a value indicating wether the minum tab width should be used. Editor restart required.
/// </summary>
[DefaultValue(false)]
[EditorDisplay("Tabs & Windows"), EditorOrder(99)]
public bool UseMinimumTabWidth { get; set; } = false;
/// <summary>
/// Gets or sets a value indicating the minimum tab width. If a tab is smaller than this width, its width will be set to this. Editor restart required.
/// </summary>
[DefaultValue(80.0f), Limit(50.0f, 150.0f)]
[EditorDisplay("Tabs & Windows"), EditorOrder(99), VisibleIf(nameof(UseMinimumTabWidth))]
public float MinimumTabWidth { get; set; } = 80.0f;
/// <summary>
/// Gets or sets a value indicating the height of window tabs. Editor restart required.
/// </summary>
[DefaultValue(20.0f), Limit(15.0f, 40.0f)]
[EditorDisplay("Tabs & Windows"), EditorOrder(100)]
public float TabHeight { get; set; } = 20.0f;
/// <summary>
/// Gets or sets a value indicating whether center mouse position on window focus in play mode. Helps when working with games that lock mouse cursor.
/// </summary>
[DefaultValue(false)]
[EditorDisplay("Tabs & Windows", "Center Mouse On Game Window Focus"), EditorOrder(101), Tooltip("Determines whether center mouse position on window focus in play mode. Helps when working with games that lock mouse cursor.")]
public bool CenterMouseOnGameWinFocus { get; set; } = false;
/// <summary>
/// Gets or sets the method window opening.
/// </summary>
[DefaultValue(DockStateProxy.Float)]
[EditorDisplay("Tabs & Windows", "New Window Location"), EditorOrder(150), Tooltip("Define the opening method for new windows, open in a new tab by default.")]
public DockStateProxy NewWindowLocation { get; set; } = DockStateProxy.Float;
/// <summary>
/// Gets or sets a value indicating when the tab close button should be visible.
/// </summary>
[DefaultValue(TabCloseButtonVisibility.SelectedTab)]
[EditorDisplay("Tabs & Windows"), EditorOrder(151)]
public TabCloseButtonVisibility ShowTabCloseButton { get; set; } = TabCloseButtonVisibility.SelectedTab;
/// <summary>
/// Gets or sets the timestamps prefix mode for output log messages.
/// </summary>
@@ -518,12 +446,6 @@ namespace FlaxEditor.Options
[DefaultValue(1), Range(1, 4)]
[EditorDisplay("Cook & Run"), EditorOrder(600)]
public int NumberOfGameClientsToLaunch = 1;
/// <summary>
/// Gets or sets the build configuration to use when using Cook and Run option in the editor.
/// </summary>
[EditorDisplay("Cook & Run"), EditorOrder(601), ExpandGroups, Tooltip("The build configuration to use when using Cook and Run option in the editor.")]
public BuildConfiguration CookAndRunBuildConfiguration { get; set; } = BuildConfiguration.Development;
/// <summary>
/// Gets or sets the curvature of the line connecting to connected visject nodes.

View File

@@ -141,8 +141,6 @@ namespace FlaxEditor.SceneGraph.Actors
b.TooltipText = "Add a box collider to every selected model that will auto resize based on the model bounds.";
b = menu.ContextMenu.AddButton("Sphere", () => OnAddCollider(window, CreateSphere));
b.TooltipText = "Add a sphere collider to every selected model that will auto resize based on the model bounds.";
b = menu.ContextMenu.AddButton("Capsule", () => OnAddCollider(window, CreateCapsule));
b.TooltipText = "Add a capsule collider to every selected model that will auto resize based on the model bounds.";
b = menu.ContextMenu.AddButton("Convex", () => OnAddCollider(window, CreateConvex));
b.TooltipText = "Generate and add a convex collider for every selected model.";
b = menu.ContextMenu.AddButton("Triangle Mesh", () => OnAddCollider(window, CreateTriangle));
@@ -269,20 +267,6 @@ namespace FlaxEditor.SceneGraph.Actors
spawner(collider);
}
private void CreateCapsule(StaticModel actor, Spawner spawner, bool singleNode)
{
var collider = new CapsuleCollider
{
Transform = actor.Transform,
Position = actor.Box.Center,
// Size the capsule to best fit the actor
Radius = (float)actor.Sphere.Radius / Mathf.Max((float)actor.Scale.MaxValue, 0.0001f) * 0.707f,
Height = 100f,
};
spawner(collider);
}
private void CreateConvex(StaticModel actor, Spawner spawner, bool singleNode)
{
CreateMeshCollider(actor, spawner, singleNode, CollisionDataType.ConvexMesh);

View File

@@ -1,9 +1,8 @@
// Copyright (c) Wojciech Figat. All rights reserved.
using System.Collections.Generic;
using FlaxEditor.SceneGraph;
using FlaxEditor.Viewport;
using FlaxEngine;
using System.Collections.Generic;
namespace FlaxEditor
{
@@ -40,23 +39,9 @@ namespace FlaxEditor
/// </summary>
void RenameSelection();
/// <summary>
/// Deletes selected objects.
/// </summary>
void DeleteSelection();
/// <summary>
/// Focuses selected objects.
/// </summary>
void FocusSelection();
/// <summary>
/// Spawns the specified actor to the game (with undo).
/// </summary>
/// <param name="actor">The actor.</param>
/// <param name="parent">The parent actor. Set null as default.</param>
/// <param name="orderInParent">The order under the parent to put the spawned actor.</param>
/// <param name="autoSelect">True if automatically select the spawned actor, otherwise false.</param>
void Spawn(Actor actor, Actor parent = null, int orderInParent = -1, bool autoSelect = true);
}
}

View File

@@ -97,16 +97,13 @@ namespace FlaxEditor.SceneGraph
/// <returns>Hit object or null if there is no intersection at all.</returns>
public SceneGraphNode RayCast(ref Ray ray, ref Ray view, out Real distance, RayCastData.FlagTypes flags = RayCastData.FlagTypes.None)
{
Profiler.BeginEvent("RayCastScene");
var data = new RayCastData
{
Ray = ray,
View = view,
Flags = flags
};
var result = RayCast(ref data, out distance, out _);
Profiler.EndEvent();
return result;
return RayCast(ref data, out distance, out _);
}
/// <summary>
@@ -120,16 +117,13 @@ namespace FlaxEditor.SceneGraph
/// <returns>Hit object or null if there is no intersection at all.</returns>
public SceneGraphNode RayCast(ref Ray ray, ref Ray view, out Real distance, out Vector3 normal, RayCastData.FlagTypes flags = RayCastData.FlagTypes.None)
{
Profiler.BeginEvent("RayCastScene");
var data = new RayCastData
{
Ray = ray,
View = view,
Flags = flags
};
var result = RayCast(ref data, out distance, out normal);
Profiler.EndEvent();
return result;
return RayCast(ref data, out distance, out normal);
}
internal static Quaternion RaycastNormalRotation(ref Vector3 normal)
@@ -181,7 +175,7 @@ namespace FlaxEditor.SceneGraph
public List<SceneGraphNode> Selection => SceneContext.Selection;
/// <summary>
/// Gets the scene editing context.
/// Gets the list of selected scene graph nodes in the editor context.
/// </summary>
public abstract ISceneEditingContext SceneContext { get; }
}

View File

@@ -62,11 +62,6 @@ API_ENUM(Namespace="FlaxEditor", Attributes="HideInEditor") enum class CodeEdito
/// </summary>
VS2022,
/// <summary>
/// Visual Studio 2026
/// </summary>
VS2026,
/// <summary>
/// Visual Studio Code
/// </summary>

View File

@@ -43,9 +43,6 @@ VisualStudioEditor::VisualStudioEditor(VisualStudioVersion version, const String
case VisualStudioVersion::VS2022:
_type = CodeEditorTypes::VS2022;
break;
case VisualStudioVersion::VS2026:
_type = CodeEditorTypes::VS2026;
break;
default: CRASH;
break;
}
@@ -73,9 +70,6 @@ void VisualStudioEditor::FindEditors(Array<CodeEditor*>* output)
VisualStudioVersion version;
switch (info.VersionMajor)
{
case 18:
version = VisualStudioVersion::VS2026;
break;
case 17:
version = VisualStudioVersion::VS2022;
break;

View File

@@ -10,7 +10,7 @@
/// <summary>
/// Microsoft Visual Studio version types
/// </summary>
DECLARE_ENUM_9(VisualStudioVersion, VS2008, VS2010, VS2012, VS2013, VS2015, VS2017, VS2019, VS2022, VS2026);
DECLARE_ENUM_8(VisualStudioVersion, VS2008, VS2010, VS2012, VS2013, VS2015, VS2017, VS2019, VS2022);
/// <summary>
/// Implementation of code editor utility that is using Microsoft Visual Studio.

View File

@@ -233,8 +233,6 @@ namespace FlaxEditor.Surface.Archetypes
public BlendPointsEditor(Animation.MultiBlend node, bool is2D, float x, float y, float width, float height)
: base(x, y, width, height)
{
AutoFocus = true;
_node = node;
_is2D = is2D;
}

View File

@@ -810,7 +810,7 @@ namespace FlaxEditor.Surface.Archetypes
Create = (id, context, arch, groupArch) => new StateMachineState(id, context, arch, groupArch),
Title = "State",
Description = "The animation states machine state node",
Flags = NodeFlags.AnimGraph | NodeFlags.NoSpawnViaGUI,
Flags = NodeFlags.AnimGraph | NodeFlags.NoSpawnViaGUI | NodeFlags.NoSpawnViaPaste,
Size = new Float2(100, 0),
DefaultValues = new object[]
{

View File

@@ -199,7 +199,7 @@ namespace FlaxEditor.Surface.Archetypes
private Label _labelValue;
private FloatValueBox _timeValue;
private ColorValueBox _colorValue;
private const int MaxStops = 12;
private const int MaxStops = 8;
/// <inheritdoc />
public ColorGradientNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch)
@@ -1386,11 +1386,10 @@ namespace FlaxEditor.Surface.Archetypes
Title = "Time",
Description = "Game time constant",
Flags = NodeFlags.MaterialGraph,
Size = new Float2(110, 40),
Size = new Float2(110, 20),
Elements = new[]
{
NodeElementArchetype.Factory.Output(0, "Time", typeof(float), 0),
NodeElementArchetype.Factory.Output(1, "Unscaled Time", typeof(float), 1),
NodeElementArchetype.Factory.Output(0, "", typeof(float), 0),
}
},
new NodeArchetype
@@ -1507,11 +1506,7 @@ namespace FlaxEditor.Surface.Archetypes
0.95f,
Color.White,
// Empty stops 2-11
0.0f, Color.Black,
0.0f, Color.Black,
0.0f, Color.Black,
0.0f, Color.Black,
// Empty stops 2-7
0.0f, Color.Black,
0.0f, Color.Black,
0.0f, Color.Black,

View File

@@ -64,7 +64,6 @@ namespace FlaxEditor.Surface.Elements
{
ParentNode = parentNode;
Archetype = archetype;
AutoFocus = true;
var back = Style.Current.TextBoxBackground;
var grayOutFactor = 0.6f;

View File

@@ -5,39 +5,39 @@ using FlaxEngine;
namespace FlaxEditor.Surface
{
/// <summary>
/// Node Alignment type.
/// Node Alignment type
/// </summary>
[HideInEditor]
public enum NodeAlignmentType
{
/// <summary>
/// Align nodes vertically to top, matching top-most node.
/// Align nodes vertically to top, matching top-most node
/// </summary>
Top,
/// <summary>
/// Align nodes vertically to middle, using average of all nodes.
/// Align nodes vertically to middle, using average of all nodes
/// </summary>
Middle,
/// <summary>
/// Align nodes vertically to bottom, matching bottom-most node.
/// Align nodes vertically to bottom, matching bottom-most node
/// </summary>
Bottom,
/// <summary>
/// Align nodes horizontally to left, matching left-most node.
/// Align nodes horizontally to left, matching left-most node
/// </summary>
Left,
/// <summary>
/// Align nodes horizontally to center, using average of all nodes.
/// Align nodes horizontally to center, using average of all nodes
/// </summary>
Center,
/// <summary>
/// Align nodes horizontally to right, matching right-most node.
/// Align nodes horizontally to right, matching right-most node
/// </summary>
Right,
}
}
}

View File

@@ -59,7 +59,6 @@ namespace FlaxEditor.Surface
protected SurfaceControl(VisjectSurfaceContext context, float width, float height)
: base(0, 0, width, height)
{
AutoFocus = true;
ClipChildren = false;
Surface = context.Surface;

View File

@@ -28,7 +28,7 @@ namespace FlaxEditor.Surface
/// </summary>
/// <param name="scriptType">The input type to process.</param>
/// <param name="cache">Node groups cache that can be used for reusing groups for different nodes.</param>
/// <param name="version">The cache version number. Can be used to reject any cached data after.<see cref="NodesCache"/> rebuilt.</param>
/// <param name="version">The cache version number. Can be used to reject any cached data after <see cref="NodesCache"/> rebuilt.</param>
public delegate void IterateType(ScriptType scriptType, Dictionary<KeyValuePair<string, ushort>, GroupArchetype> cache, int version);
internal static readonly List<NodesCache> Caches = new List<NodesCache>(8);
@@ -412,7 +412,6 @@ namespace FlaxEditor.Surface
_cmFormatNodesMenu.Enabled = CanEdit && HasNodesSelection;
_cmFormatNodesConnectionButton = _cmFormatNodesMenu.ContextMenu.AddButton("Auto format", Editor.Instance.Options.Options.Input.NodesAutoFormat, () => { FormatGraph(SelectedNodes); });
_cmFormatNodesConnectionButton = _cmFormatNodesMenu.ContextMenu.AddButton("Straighten connections", Editor.Instance.Options.Options.Input.NodesStraightenConnections, () => { StraightenGraphConnections(SelectedNodes); });
_cmFormatNodesMenu.ContextMenu.AddSeparator();
_cmAlignNodesTopButton = _cmFormatNodesMenu.ContextMenu.AddButton("Align top", Editor.Instance.Options.Options.Input.NodesAlignTop, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Top); });

View File

@@ -1,9 +1,9 @@
using FlaxEditor.Surface.Elements;
using FlaxEditor.Surface.Undo;
using FlaxEngine;
using System;
using System.Collections.Generic;
using System.Linq;
using FlaxEngine;
using FlaxEditor.Surface.Elements;
using FlaxEditor.Surface.Undo;
namespace FlaxEditor.Surface
{
@@ -14,26 +14,26 @@ namespace FlaxEditor.Surface
private class NodeFormattingData
{
/// <summary>
/// Starting from 0 at the main nodes.
/// Starting from 0 at the main nodes
/// </summary>
public int Layer;
/// <summary>
/// Position in the layer.
/// Position in the layer
/// </summary>
public int Offset;
/// <summary>
/// How far the subtree needs to be moved additionally.
/// How far the subtree needs to be moved additionally
/// </summary>
public int SubtreeOffset;
}
/// <summary>
/// Formats a graph where the nodes can be disjointed.
/// Uses the Sugiyama method.
/// Uses the Sugiyama method
/// </summary>
/// <param name="nodes">List of nodes.</param>
/// <param name="nodes">List of nodes</param>
public void FormatGraph(List<SurfaceNode> nodes)
{
if (nodes.Count <= 1)
@@ -78,9 +78,9 @@ namespace FlaxEditor.Surface
}
/// <summary>
/// Formats a graph where all nodes are connected.
/// Formats a graph where all nodes are connected
/// </summary>
/// <param name="nodes">List of connected nodes.</param>
/// <param name="nodes">List of connected nodes</param>
protected void FormatConnectedGraph(List<SurfaceNode> nodes)
{
if (nodes.Count <= 1)
@@ -160,71 +160,11 @@ namespace FlaxEditor.Surface
}
/// <summary>
/// Straightens every connection between nodes in <paramref name="nodes"/>.
/// Assigns a layer to every node
/// </summary>
/// <param name="nodes">List of nodes.</param>
public void StraightenGraphConnections(List<SurfaceNode> nodes)
{
if (nodes.Count <= 1)
return;
List<MoveNodesAction> undoActions = new List<MoveNodesAction>();
// Only process nodes that have any connection
List<SurfaceNode> connectedNodes = nodes.Where(n => n.GetBoxes().Any(b => b.HasAnyConnection)).ToList();
if (connectedNodes.Count == 0)
return;
for (int i = 0; i < connectedNodes.Count - 1; i++)
{
SurfaceNode nodeA = connectedNodes[i];
List<Box> connectedOutputBoxes = nodeA.GetBoxes().Where(b => b.IsOutput && b.HasAnyConnection).ToList();
for (int j = 0; j < connectedOutputBoxes.Count; j++)
{
Box boxA = connectedOutputBoxes[j];
for (int b = 0; b < boxA.Connections.Count; b++)
{
Box boxB = boxA.Connections[b];
// Ensure the other node is selected
if (!connectedNodes.Contains(boxB.ParentNode))
continue;
// Node with no outgoing connections reached. Advance to next node in list
if (boxA == null || boxB == null)
continue;
SurfaceNode nodeB = boxB.ParentNode;
// Calculate the Y offset needed for nodeB to align boxB's Y to boxA's Y
float boxASurfaceY = boxA.PointToParent(this, Float2.Zero).Y;
float boxBSurfaceY = boxB.PointToParent(this, Float2.Zero).Y;
float deltaY = (boxASurfaceY - boxBSurfaceY) / ViewScale;
Float2 delta = new Float2(0f, deltaY);
nodeB.Location += delta;
if (Undo != null)
undoActions.Add(new MoveNodesAction(Context, new[] { nodeB.ID }, delta));
}
}
}
if (undoActions.Count > 0)
Undo?.AddAction(new MultiUndoAction(undoActions, "Straightned "));
MarkAsEdited(false);
}
/// <summary>
/// Assigns a layer to every node.
/// </summary>
/// <param name="nodeData">The exta node data.</param>
/// <param name="endNodes">The end nodes.</param>
/// <returns>The number of the maximum layer.</returns>
/// <param name="nodeData">The exta node data</param>
/// <param name="endNodes">The end nodes</param>
/// <returns>The number of the maximum layer</returns>
private int SetLayers(Dictionary<SurfaceNode, NodeFormattingData> nodeData, List<SurfaceNode> endNodes)
{
// Longest path layering
@@ -261,12 +201,12 @@ namespace FlaxEditor.Surface
/// <summary>
/// Sets the node offsets.
/// Sets the node offsets
/// </summary>
/// <param name="nodeData">The exta node data.</param>
/// <param name="endNodes">The end nodes.</param>
/// <param name="maxLayer">The number of the maximum layer.</param>
/// <returns>The number of the maximum offset.</returns>
/// <param name="nodeData">The exta node data</param>
/// <param name="endNodes">The end nodes</param>
/// <param name="maxLayer">The number of the maximum layer</param>
/// <returns>The number of the maximum offset</returns>
private int SetOffsets(Dictionary<SurfaceNode, NodeFormattingData> nodeData, List<SurfaceNode> endNodes, int maxLayer)
{
int maxOffset = 0;
@@ -347,10 +287,10 @@ namespace FlaxEditor.Surface
/// Align given nodes on a graph using the given alignment type.
/// Ignores any potential overlap.
/// </summary>
/// <param name="nodes">List of nodes.</param>
/// <param name="alignmentType">Alignemnt type.</param>
/// <param name="nodes">List of nodes</param>
/// <param name="alignmentType">Alignemnt type</param>
public void AlignNodes(List<SurfaceNode> nodes, NodeAlignmentType alignmentType)
{
{
if(nodes.Count <= 1)
return;
@@ -388,8 +328,8 @@ namespace FlaxEditor.Surface
/// <summary>
/// Distribute the given nodes as equally as possible inside the bounding box, if no fit can be done it will use a default pad of 10 pixels between nodes.
/// </summary>
/// <param name="nodes">List of nodes.</param>
/// <param name="vertically">If false will be done horizontally, if true will be done vertically.</param>
/// <param name="nodes">List of nodes</param>
/// <param name="vertically">If false will be done horizontally, if true will be done vertically</param>
public void DistributeNodes(List<SurfaceNode> nodes, bool vertically)
{
if(nodes.Count <= 1)

View File

@@ -120,8 +120,6 @@ namespace FlaxEditor.Surface
private void UpdateSelectionRectangle()
{
if (Root == null)
return;
var p1 = _rootControl.PointFromParent(ref _leftMouseDownPos);
var p2 = _rootControl.PointFromParent(ref _mousePos);
var selectionRect = Rectangle.FromPoints(p1, p2);

View File

@@ -416,7 +416,6 @@ namespace FlaxEditor.Surface
new InputActionsContainer.Binding(options => options.Cut, Cut),
new InputActionsContainer.Binding(options => options.Duplicate, Duplicate),
new InputActionsContainer.Binding(options => options.NodesAutoFormat, () => { FormatGraph(SelectedNodes); }),
new InputActionsContainer.Binding(options => options.NodesStraightenConnections, () => { StraightenGraphConnections(SelectedNodes); }),
new InputActionsContainer.Binding(options => options.NodesAlignTop, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Top); }),
new InputActionsContainer.Binding(options => options.NodesAlignMiddle, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Middle); }),
new InputActionsContainer.Binding(options => options.NodesAlignBottom, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Bottom); }),
@@ -543,12 +542,11 @@ namespace FlaxEditor.Surface
nodes.Add(context);
context = context.Parent;
}
float margin = 1;
float x = NavigationBar.DefaultButtonsMargin;
float h = toolStrip.ItemsHeight - 2 * margin;
float h = toolStrip.ItemsHeight - 2 * ToolStrip.DefaultMarginV;
for (int i = nodes.Count - 1; i >= 0; i--)
{
var button = new VisjectContextNavigationButton(this, nodes[i].Context, x, margin, h);
var button = new VisjectContextNavigationButton(this, nodes[i].Context, x, ToolStrip.DefaultMarginV, h);
button.PerformLayout();
x += button.Width + NavigationBar.DefaultButtonsMargin;
navigationBar.AddChild(button);

View File

@@ -61,7 +61,6 @@ namespace FlaxEditor.Utilities
/// <param name="value">The value.</param>
public void SetMemberValue(object instance, object value)
{
var originalInstance = instance;
var finalMember = MemberPath.GetLastMember(ref instance);
var type = finalMember.Type;
@@ -93,12 +92,6 @@ namespace FlaxEditor.Utilities
}
finalMember.SetValue(instance, value);
if (instance != originalInstance && finalMember.Index != null)
{
// Set collection back to the parent object (in case of properties that always return a new object like 'Spline.SplineKeyframes')
finalMember.Member.SetValue(originalInstance, instance);
}
}
/// <inheritdoc />

View File

@@ -1571,19 +1571,5 @@ namespace FlaxEditor.Utilities
_ => throw new ArgumentOutOfRangeException()
};
}
internal static bool HideSingleTabWindowTabBars()
{
#if PLATFORM_SDL
// We should not hide the tab bars if tab handle is the only way to dock the window
bool clientSideDecorations = UseCustomWindowDecorations(false);
bool draggableDecorations = clientSideDecorations || Platform.SupportsNativeDecorationDragging;
return draggableDecorations && Editor.Instance.Options.Options.Interface.HideSingleTabWindowTabBars;
#elif PLATFORM_WINDOWS
return Editor.Instance.Options.Options.Interface.HideSingleTabWindowTabBars;
#else
return false;
#endif
}
}
}

View File

@@ -340,13 +340,6 @@ namespace FlaxEditor.Viewport
{
_debugDrawData.Clear();
if (task is SceneRenderTask sceneRenderTask)
{
// Sync debug view to avoid lag on culling/LODing
var view = sceneRenderTask.View;
DebugDraw.SetView(ref view);
}
// Collect selected objects debug shapes and visuals
var selectedParents = TransformGizmo.SelectedParents;
if (selectedParents.Count > 0)
@@ -381,7 +374,14 @@ namespace FlaxEditor.Viewport
// Draw selected objects debug shapes and visuals
if (DrawDebugDraw && (renderContext.View.Flags & ViewFlags.DebugDraw) == ViewFlags.DebugDraw)
{
_debugDrawData.DrawActors(true);
unsafe
{
fixed (IntPtr* actors = _debugDrawData.ActorsPtrs)
{
DebugDraw.DrawActors(new IntPtr(actors), _debugDrawData.ActorsCount, true);
}
}
DebugDraw.Draw(ref renderContext, target.View(), targetDepth.View(), true);
}
}

View File

@@ -243,12 +243,7 @@ namespace FlaxEditor.Viewport
_tempDebugDrawContext = DebugDraw.AllocateContext();
DebugDraw.SetContext(_tempDebugDrawContext);
DebugDraw.UpdateContext(_tempDebugDrawContext, 1.0f);
if (task is SceneRenderTask sceneRenderTask)
{
// Sync debug view to avoid lag on culling/LODing
var view = sceneRenderTask.View;
DebugDraw.SetView(ref view);
}
for (int i = 0; i < selectedParents.Count; i++)
{
if (selectedParents[i].IsActiveInHierarchy)
@@ -648,7 +643,14 @@ namespace FlaxEditor.Viewport
if (selectedParents[i].IsActiveInHierarchy)
selectedParents[i].OnDebugDraw(_debugDrawData);
}
_debugDrawData.DrawActors();
unsafe
{
fixed (IntPtr* actors = _debugDrawData.ActorsPtrs)
{
DebugDraw.DrawActors(new IntPtr(actors), _debugDrawData.ActorsCount, false);
}
}
// Debug draw all actors in prefab and collect actors
var view = Task.View;
@@ -668,7 +670,10 @@ namespace FlaxEditor.Viewport
if ((view.Flags & ViewFlags.PhysicsDebug) != 0 || view.Mode == ViewMode.PhysicsColliders)
{
foreach (var actor in _debugDrawActors)
DebugDraw.DrawDebugPhysics(actor, renderContext.View);
{
if (actor is Collider c && c.IsActiveInHierarchy)
DebugDraw.DrawColliderDebugPhysics(c, renderContext.View);
}
}
// Draw lights debug

View File

@@ -264,7 +264,6 @@ namespace FlaxEditor.Viewport.Previews
{
DebugDraw.SetContext(_debugDrawContext);
DebugDraw.UpdateContext(_debugDrawContext, 1.0f / Mathf.Max(Engine.FramesPerSecond, 1));
DebugDraw.SetView(ref renderContext.View);
CustomDebugDraw?.Invoke(context, ref renderContext);
OnDebugDraw(context, ref renderContext);
DebugDraw.Draw(ref renderContext, target.View(), targetDepth.View(), true);

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