Merge branch '1.5' into dotnet7
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
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.
@@ -2,6 +2,7 @@
|
||||
// Version: @0
|
||||
|
||||
#define MATERIAL 1
|
||||
#define USE_PER_VIEW_CONSTANTS 1
|
||||
@3
|
||||
|
||||
#include "./Flax/Common.hlsl"
|
||||
@@ -10,17 +11,9 @@
|
||||
@7
|
||||
// Primary constant buffer (with additional material parameters)
|
||||
META_CB_BEGIN(0, Data)
|
||||
float4x4 ViewProjectionMatrix;
|
||||
float4x4 WorldMatrix;
|
||||
float4x4 ViewMatrix;
|
||||
float4x4 InvWorld;
|
||||
float4x4 SVPositionToWorld;
|
||||
float3 ViewPos;
|
||||
float ViewFar;
|
||||
float3 ViewDir;
|
||||
float TimeParam;
|
||||
float4 ViewInfo;
|
||||
float4 ScreenSize;
|
||||
@1META_CB_END
|
||||
|
||||
// Use depth buffer for per-pixel decal layering
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Version: @0
|
||||
|
||||
#define MATERIAL 1
|
||||
#define USE_PER_VIEW_CONSTANTS 1
|
||||
@3
|
||||
#include "./Flax/Common.hlsl"
|
||||
#include "./Flax/MaterialCommon.hlsl"
|
||||
@@ -9,23 +10,14 @@
|
||||
@7
|
||||
// Primary constant buffer (with additional material parameters)
|
||||
META_CB_BEGIN(0, Data)
|
||||
float4x4 ViewProjectionMatrix;
|
||||
float4x4 WorldMatrix;
|
||||
float4x4 LocalMatrix;
|
||||
float4x4 ViewMatrix;
|
||||
float3 ViewPos;
|
||||
float ViewFar;
|
||||
float3 ViewDir;
|
||||
float TimeParam;
|
||||
float4 ViewInfo;
|
||||
float4 ScreenSize;
|
||||
float3 Dummy0;
|
||||
float WorldDeterminantSign;
|
||||
float MeshMinZ;
|
||||
float Segment;
|
||||
float ChunksPerSegment;
|
||||
float PerInstanceRandom;
|
||||
float4 TemporalAAJitter;
|
||||
float3 GeometrySize;
|
||||
float MeshMaxZ;
|
||||
@1META_CB_END
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Version: @0
|
||||
|
||||
#define MATERIAL 1
|
||||
#define USE_PER_VIEW_CONSTANTS 1
|
||||
@3
|
||||
// Ribbons don't use sorted indices so overlap the segment distances buffer on the slot
|
||||
#define HAS_SORTED_INDICES (!defined(_VS_Ribbon))
|
||||
@@ -19,15 +20,7 @@ struct SpriteInput
|
||||
|
||||
// Primary constant buffer (with additional material parameters)
|
||||
META_CB_BEGIN(0, Data)
|
||||
float4x4 ViewProjectionMatrix;
|
||||
float4x4 WorldMatrix;
|
||||
float4x4 ViewMatrix;
|
||||
float3 ViewPos;
|
||||
float ViewFar;
|
||||
float3 ViewDir;
|
||||
float TimeParam;
|
||||
float4 ViewInfo;
|
||||
float4 ScreenSize;
|
||||
uint SortedIndicesOffset;
|
||||
float PerInstanceRandom;
|
||||
int ParticleStride;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Version: @0
|
||||
|
||||
#define MATERIAL 1
|
||||
#define USE_PER_VIEW_CONSTANTS 1
|
||||
@3
|
||||
#include "./Flax/Common.hlsl"
|
||||
#include "./Flax/MaterialCommon.hlsl"
|
||||
@@ -9,23 +10,11 @@
|
||||
@7
|
||||
// Primary constant buffer (with additional material parameters)
|
||||
META_CB_BEGIN(0, Data)
|
||||
float4x4 ViewProjectionMatrix;
|
||||
float4x4 WorldMatrix;
|
||||
float4x4 ViewMatrix;
|
||||
float4x4 PrevViewProjectionMatrix;
|
||||
float4x4 PrevWorldMatrix;
|
||||
float4x4 MainViewProjectionMatrix;
|
||||
float4 MainScreenSize;
|
||||
float3 ViewPos;
|
||||
float ViewFar;
|
||||
float3 ViewDir;
|
||||
float TimeParam;
|
||||
float4 ViewInfo;
|
||||
float4 ScreenSize;
|
||||
float2 Dummy0;
|
||||
float LODDitherFactor;
|
||||
float PerInstanceRandom;
|
||||
float4 TemporalAAJitter;
|
||||
float3 GeometrySize;
|
||||
float WorldDeterminantSign;
|
||||
@1META_CB_END
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Version: @0
|
||||
|
||||
#define MATERIAL 1
|
||||
#define USE_PER_VIEW_CONSTANTS 1
|
||||
@3
|
||||
// Enables/disables smooth terrain chunks LOD transitions (with morphing higher LOD near edges to the lower LOD in the neighbour)
|
||||
#define USE_SMOOTH_LOD_TRANSITION 1
|
||||
@@ -16,15 +17,7 @@
|
||||
@7
|
||||
// Primary constant buffer (with additional material parameters)
|
||||
META_CB_BEGIN(0, Data)
|
||||
float4x4 ViewProjectionMatrix;
|
||||
float4x4 WorldMatrix;
|
||||
float4x4 ViewMatrix;
|
||||
float3 ViewPos;
|
||||
float ViewFar;
|
||||
float3 ViewDir;
|
||||
float TimeParam;
|
||||
float4 ViewInfo;
|
||||
float4 ScreenSize;
|
||||
float3 WorldInvScale;
|
||||
float WorldDeterminantSign;
|
||||
float PerInstanceRandom;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Version: @0
|
||||
|
||||
#define MATERIAL 1
|
||||
#define USE_PER_VIEW_CONSTANTS 1
|
||||
@3
|
||||
|
||||
#include "./Flax/Common.hlsl"
|
||||
@@ -11,17 +12,9 @@
|
||||
|
||||
// Primary constant buffer (with additional material parameters)
|
||||
META_CB_BEGIN(0, Data)
|
||||
float4x4 ViewProjectionMatrix;
|
||||
float4x4 InverseViewProjectionMatrix;
|
||||
float4x4 ViewMatrix;
|
||||
float4x4 WorldMatrix;
|
||||
float4x4 WorldMatrixInverseTransposed;
|
||||
float3 ViewPos;
|
||||
float ViewFar;
|
||||
float3 ViewDir;
|
||||
float TimeParam;
|
||||
float4 ViewInfo;
|
||||
float4 ScreenSize;
|
||||
float3 GridSize;
|
||||
float PerInstanceRandom;
|
||||
float Dummy0;
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
@@ -7,6 +7,7 @@
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Math/Vector2.h"
|
||||
#include "Engine/Core/Types/DateTime.h"
|
||||
#include "Engine/Core/Types/TimeSpan.h"
|
||||
#include "Editor/Editor.h"
|
||||
#include "Editor/ProjectInfo.h"
|
||||
#include "Engine/Engine/EngineService.h"
|
||||
|
||||
@@ -497,6 +497,8 @@ bool UWPPlatformTools::OnPerformAOT(CookingData& data, AotConfig& config, const
|
||||
|
||||
bool UWPPlatformTools::OnPostProcess(CookingData& data)
|
||||
{
|
||||
LOG(Error, "UWP (Windows Store) platform has been deprecated and soon will be removed!");
|
||||
|
||||
// Special case for UWP
|
||||
// FlaxEngine.dll cannot be added to the solution as `Content` item (due to conflicts with C++ /CX FlaxEngine.dll)
|
||||
// Use special directory for it (generated UWP project handles this case and copies lib to the output)
|
||||
|
||||
@@ -115,6 +115,8 @@ bool DeployDataStep::Perform(CookingData& data)
|
||||
auto& buildSettings = *BuildSettings::Get();
|
||||
for (auto& e : buildSettings.AdditionalAssets)
|
||||
data.AddRootAsset(e.GetID());
|
||||
for (auto& e : buildSettings.AdditionalScenes)
|
||||
data.AddRootAsset(e.ID);
|
||||
Array<String> files;
|
||||
for (auto& e : buildSettings.AdditionalAssetFolders)
|
||||
{
|
||||
|
||||
@@ -225,7 +225,8 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
}
|
||||
|
||||
private static HashSet<PropertiesList> _visibleIfPropertiesListsCache;
|
||||
private static Dictionary<string, GroupElement> _groups;
|
||||
private static Stack<Dictionary<string, GroupElement>> _groups;
|
||||
private static List<Dictionary<string, GroupElement>> _groupsPool;
|
||||
private VisibleIfCache[] _visibleIfCaches;
|
||||
private bool _isNull;
|
||||
|
||||
@@ -514,17 +515,38 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
menu.Show(groupPanel, location);
|
||||
}
|
||||
|
||||
internal static void OnGroupUsage()
|
||||
internal static void OnGroupsBegin()
|
||||
{
|
||||
if (_groups != null)
|
||||
_groups.Clear();
|
||||
if (_groups == null)
|
||||
_groups = new Stack<Dictionary<string, GroupElement>>();
|
||||
if (_groupsPool == null)
|
||||
_groupsPool = new List<Dictionary<string, GroupElement>>();
|
||||
Dictionary<string, GroupElement> group;
|
||||
if (_groupsPool.Count != 0)
|
||||
{
|
||||
group = _groupsPool[0];
|
||||
_groupsPool.RemoveAt(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
group = new Dictionary<string, GroupElement>();
|
||||
}
|
||||
_groups.Push(group);
|
||||
}
|
||||
|
||||
internal static void OnGroupsEnd()
|
||||
{
|
||||
var groups = _groups.Pop();
|
||||
groups.Clear();
|
||||
_groupsPool.Add(groups);
|
||||
}
|
||||
|
||||
internal static LayoutElementsContainer OnGroup(LayoutElementsContainer layout, EditorDisplayAttribute display)
|
||||
{
|
||||
if (display?.Group != null)
|
||||
{
|
||||
if (_groups != null && _groups.TryGetValue(display.Group, out var group))
|
||||
var groups = _groups.Peek();
|
||||
if (groups.TryGetValue(display.Group, out var group))
|
||||
{
|
||||
// Reuse group
|
||||
layout = group;
|
||||
@@ -532,12 +554,10 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
else
|
||||
{
|
||||
// Add new group
|
||||
if (_groups == null)
|
||||
_groups = new Dictionary<string, GroupElement>();
|
||||
group = layout.Group(display.Group);
|
||||
group.Panel.Tag = group;
|
||||
group.Panel.MouseButtonRightClicked += OnGroupPanelMouseButtonRightClicked;
|
||||
_groups.Add(display.Group, group);
|
||||
groups.Add(display.Group, group);
|
||||
layout = group;
|
||||
}
|
||||
}
|
||||
@@ -713,7 +733,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
items.Sort();
|
||||
|
||||
// Add items
|
||||
OnGroupUsage();
|
||||
OnGroupsBegin();
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
{
|
||||
var item = items[i];
|
||||
@@ -759,7 +779,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
} while (c != null);
|
||||
}
|
||||
}
|
||||
OnGroupUsage();
|
||||
OnGroupsEnd();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -37,6 +37,16 @@ namespace FlaxEditor.GUI.Docking
|
||||
// Focus window
|
||||
window.Focus();
|
||||
|
||||
// Check if window is maximized and restore window.
|
||||
if (window.IsMaximized)
|
||||
{
|
||||
// Restore window and set position to mouse.
|
||||
var mousePos = window.MousePosition;
|
||||
var previousSize = window.Size;
|
||||
window.Restore();
|
||||
window.Position = FlaxEngine.Input.MouseScreenPosition - mousePos * window.Size / previousSize;
|
||||
}
|
||||
|
||||
// Calculate dragging offset and move window to the destination position
|
||||
var mouseScreenPosition = FlaxEngine.Input.MouseScreenPosition;
|
||||
|
||||
|
||||
@@ -51,10 +51,6 @@ namespace FlaxEditor.GUI.Docking
|
||||
if (_window == null)
|
||||
return;
|
||||
|
||||
// Check if window is maximized
|
||||
if (_window.IsMaximized)
|
||||
return;
|
||||
|
||||
// Create docking hint window
|
||||
DockHintWindow.Create(this);
|
||||
}
|
||||
|
||||
@@ -81,6 +81,20 @@ namespace FlaxEditor.GUI
|
||||
|
||||
private bool IsInputValid => !string.IsNullOrWhiteSpace(_inputField.Text) && (_inputField.Text == _startValue || Validate == null || Validate(this, _inputField.Text));
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
var mouseLocation = Root.MousePosition;
|
||||
if (!ContainsPoint(ref mouseLocation) && RootWindow.ContainsFocus && Text != _startValue)
|
||||
{
|
||||
// rename item before closing if left mouse button in clicked
|
||||
if (FlaxEngine.Input.GetMouseButtonDown(MouseButton.Left))
|
||||
OnEnd();
|
||||
}
|
||||
|
||||
base.Update(deltaTime);
|
||||
}
|
||||
|
||||
private void OnTextChanged()
|
||||
{
|
||||
if (Validate == null)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
|
||||
@@ -192,4 +193,92 @@ namespace FlaxEditor.GUI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The table row that contains events for mouse interaction.
|
||||
/// </summary>
|
||||
[HideInEditor]
|
||||
public class ClickableRow : Row
|
||||
{
|
||||
private bool _leftClick;
|
||||
private bool _isRightDown;
|
||||
|
||||
/// <summary>
|
||||
/// The double click event.
|
||||
/// </summary>
|
||||
public Action DoubleClick;
|
||||
|
||||
/// <summary>
|
||||
/// The left mouse button click event.
|
||||
/// </summary>
|
||||
public Action LeftClick;
|
||||
|
||||
/// <summary>
|
||||
/// The right mouse button click event.
|
||||
/// </summary>
|
||||
public Action RightClick;
|
||||
|
||||
/// <summary>
|
||||
/// The double click event.
|
||||
/// </summary>
|
||||
public Action<ClickableRow> RowDoubleClick;
|
||||
|
||||
/// <summary>
|
||||
/// The left mouse button click event.
|
||||
/// </summary>
|
||||
public Action<ClickableRow> RowLeftClick;
|
||||
|
||||
/// <summary>
|
||||
/// The right mouse button click event.
|
||||
/// </summary>
|
||||
public Action<ClickableRow> RowRightClick;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
|
||||
{
|
||||
DoubleClick?.Invoke();
|
||||
RowDoubleClick?.Invoke(this);
|
||||
|
||||
return base.OnMouseDoubleClick(location, button);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnMouseDown(Float2 location, MouseButton button)
|
||||
{
|
||||
if (button == MouseButton.Left)
|
||||
_leftClick = true;
|
||||
else if (button == MouseButton.Right)
|
||||
_isRightDown = true;
|
||||
|
||||
return base.OnMouseDown(location, button);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnMouseUp(Float2 location, MouseButton button)
|
||||
{
|
||||
if (button == MouseButton.Left && _leftClick)
|
||||
{
|
||||
_leftClick = false;
|
||||
LeftClick?.Invoke();
|
||||
RowLeftClick?.Invoke(this);
|
||||
}
|
||||
else if (button == MouseButton.Right && _isRightDown)
|
||||
{
|
||||
_isRightDown = false;
|
||||
RightClick?.Invoke();
|
||||
RowRightClick?.Invoke(this);
|
||||
}
|
||||
|
||||
return base.OnMouseUp(location, button);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnMouseLeave()
|
||||
{
|
||||
_leftClick = false;
|
||||
_isRightDown = false;
|
||||
|
||||
base.OnMouseLeave();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace FlaxEditor.SceneGraph.Actors
|
||||
{
|
||||
base.OnContextMenu(contextMenu);
|
||||
|
||||
contextMenu.AddButton("Add mesh collider", OnAddMeshCollider).Enabled = ((StaticModel)Actor).Model != null;
|
||||
contextMenu.AddButton("Add collider", OnAddMeshCollider).Enabled = ((StaticModel)Actor).Model != null;
|
||||
}
|
||||
|
||||
private void OnAddMeshCollider()
|
||||
@@ -33,6 +33,56 @@ namespace FlaxEditor.SceneGraph.Actors
|
||||
var model = ((StaticModel)Actor).Model;
|
||||
if (!model)
|
||||
return;
|
||||
|
||||
// Special case for in-built Editor models that can use analytical collision
|
||||
var modelPath = model.Path;
|
||||
if (modelPath.EndsWith("/Primitives/Cube.flax", StringComparison.Ordinal))
|
||||
{
|
||||
var actor = new BoxCollider
|
||||
{
|
||||
StaticFlags = Actor.StaticFlags,
|
||||
Transform = Actor.Transform,
|
||||
};
|
||||
Editor.Instance.SceneEditing.Spawn(actor, Actor);
|
||||
return;
|
||||
}
|
||||
if (modelPath.EndsWith("/Primitives/Sphere.flax", StringComparison.Ordinal))
|
||||
{
|
||||
var actor = new SphereCollider
|
||||
{
|
||||
StaticFlags = Actor.StaticFlags,
|
||||
Transform = Actor.Transform,
|
||||
};
|
||||
Editor.Instance.SceneEditing.Spawn(actor, Actor);
|
||||
return;
|
||||
}
|
||||
if (modelPath.EndsWith("/Primitives/Plane.flax", StringComparison.Ordinal))
|
||||
{
|
||||
var actor = new BoxCollider
|
||||
{
|
||||
StaticFlags = Actor.StaticFlags,
|
||||
Transform = Actor.Transform,
|
||||
Size = new Float3(100.0f, 100.0f, 1.0f),
|
||||
};
|
||||
Editor.Instance.SceneEditing.Spawn(actor, Actor);
|
||||
return;
|
||||
}
|
||||
if (modelPath.EndsWith("/Primitives/Capsule.flax", StringComparison.Ordinal))
|
||||
{
|
||||
var actor = new CapsuleCollider
|
||||
{
|
||||
StaticFlags = Actor.StaticFlags,
|
||||
Transform = Actor.Transform,
|
||||
Radius = 25.0f,
|
||||
Height = 50.0f,
|
||||
};
|
||||
Editor.Instance.SceneEditing.Spawn(actor, Actor);
|
||||
actor.LocalPosition = new Vector3(0, 50.0f, 0);
|
||||
actor.LocalOrientation = Quaternion.Euler(0, 0, 90.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create collision data (or reuse) and add collision actor
|
||||
Action<CollisionData> created = collisionData =>
|
||||
{
|
||||
var actor = new MeshCollider
|
||||
|
||||
@@ -148,7 +148,16 @@ namespace FlaxEditor.Surface
|
||||
public void GetConnectionColor(ScriptType type, ConnectionsHint hint, out Color color)
|
||||
{
|
||||
if (type == ScriptType.Null)
|
||||
color = Colors.Default;
|
||||
{
|
||||
if (hint == ConnectionsHint.Vector)
|
||||
color = Colors.Vector;
|
||||
else if (hint == ConnectionsHint.Scalar)
|
||||
color = Colors.Float;
|
||||
else if (hint == ConnectionsHint.Enum)
|
||||
color = Colors.Enum;
|
||||
else
|
||||
color = Colors.Default;
|
||||
}
|
||||
else if (type.IsPointer || type.IsReference)
|
||||
{
|
||||
// Find underlying type without `*` or `&`
|
||||
|
||||
@@ -286,7 +286,7 @@ namespace FlaxEditor.Surface
|
||||
|
||||
internal static void DisplayGraphParameters(LayoutElementsContainer layout, GraphParameterData[] data, GetGraphParameterDelegate getter, SetGraphParameterDelegate setter, ValueContainer values, GetGraphParameterDelegate defaultValueGetter = null, CustomPropertySpawnDelegate propertySpawn = null)
|
||||
{
|
||||
CustomEditors.Editors.GenericEditor.OnGroupUsage();
|
||||
CustomEditors.Editors.GenericEditor.OnGroupsBegin();
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
ref var e = ref data[i];
|
||||
@@ -333,7 +333,7 @@ namespace FlaxEditor.Surface
|
||||
else
|
||||
propertySpawn(itemLayout, valueContainer, ref e);
|
||||
}
|
||||
CustomEditors.Editors.GenericEditor.OnGroupUsage();
|
||||
CustomEditors.Editors.GenericEditor.OnGroupsEnd();
|
||||
}
|
||||
|
||||
internal static string GetMethodDisplayName(string methodName)
|
||||
|
||||
@@ -372,7 +372,7 @@ namespace FlaxEditor.Surface
|
||||
return;
|
||||
}
|
||||
var parameters = window.VisjectSurface.Parameters;
|
||||
CustomEditors.Editors.GenericEditor.OnGroupUsage();
|
||||
CustomEditors.Editors.GenericEditor.OnGroupsBegin();
|
||||
for (int i = 0; i < parameters.Count; i++)
|
||||
{
|
||||
var p = parameters[i];
|
||||
@@ -429,7 +429,7 @@ namespace FlaxEditor.Surface
|
||||
var property = itemLayout.AddPropertyItem(propertyLabel, tooltipText);
|
||||
property.Property("Value", propertyValue);
|
||||
}
|
||||
CustomEditors.Editors.GenericEditor.OnGroupUsage();
|
||||
CustomEditors.Editors.GenericEditor.OnGroupsEnd();
|
||||
|
||||
// Parameters creating
|
||||
var newParameterTypes = window.NewParameterTypes;
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace FlaxEditor.Windows
|
||||
ScrollBars = ScrollBars.Both,
|
||||
Parent = _split.Panel1,
|
||||
};
|
||||
|
||||
|
||||
// Content structure tree
|
||||
_tree = new Tree(false)
|
||||
{
|
||||
@@ -179,7 +179,7 @@ namespace FlaxEditor.Windows
|
||||
ScrollBars = ScrollBars.Vertical,
|
||||
Parent = _split.Panel2,
|
||||
};
|
||||
|
||||
|
||||
// Content View
|
||||
_view = new ContentView
|
||||
{
|
||||
@@ -895,6 +895,18 @@ namespace FlaxEditor.Windows
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnMouseDown(Float2 location, MouseButton button)
|
||||
{
|
||||
// Navigate through directories using the side mouse buttons
|
||||
if (button == MouseButton.Extended1)
|
||||
NavigateBackward();
|
||||
else if (button == MouseButton.Extended2)
|
||||
NavigateForward();
|
||||
|
||||
return base.OnMouseDown(location, button);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnMouseUp(Float2 location, MouseButton button)
|
||||
{
|
||||
|
||||
@@ -257,6 +257,7 @@ namespace FlaxEditor.Windows
|
||||
break;
|
||||
case PlatformType.UWP:
|
||||
name = "Windows Store";
|
||||
layout.Label("UWP (Windows Store) platform has been deprecated and soon will be removed!", TextAlignment.Center).Label.TextColor = Color.Red;
|
||||
break;
|
||||
case PlatformType.Linux:
|
||||
name = "Linux";
|
||||
|
||||
@@ -113,6 +113,17 @@ namespace FlaxEditor.Windows
|
||||
set => MainRenderTask.Instance.RenderingPercentage = value;
|
||||
}
|
||||
|
||||
[NoSerialize, DefaultValue(RenderingUpscaleLocation.AfterAntiAliasingPass), VisibleIf(nameof(UpscaleLocation_Visible))]
|
||||
[EditorOrder(1401), EditorDisplay("Quality")]
|
||||
[Tooltip("The image resolution upscale location within rendering pipeline.")]
|
||||
public RenderingUpscaleLocation UpscaleLocation
|
||||
{
|
||||
get => MainRenderTask.Instance.UpscaleLocation;
|
||||
set => MainRenderTask.Instance.UpscaleLocation = value;
|
||||
}
|
||||
|
||||
private bool UpscaleLocation_Visible => MainRenderTask.Instance.RenderingPercentage < 1.0f;
|
||||
|
||||
[NoSerialize, DefaultValue(1.0f), Limit(0, 1)]
|
||||
[EditorOrder(1500), EditorDisplay("Quality"), Tooltip("The global density scale for all foliage instances. The default value is 1. Use values from range 0-1. Lower values decrease amount of foliage instances in-game. Use it to tweak game performance for slower devices.")]
|
||||
public float FoliageDensityScale
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using FlaxEditor.GUI;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.Json;
|
||||
using FlaxEngine.GUI;
|
||||
using FlaxEditor.GUI.ContextMenu;
|
||||
|
||||
namespace FlaxEditor.Windows.Profiler
|
||||
{
|
||||
/// <summary>
|
||||
/// The Assets profiling mode.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Windows.Profiler.ProfilerMode" />
|
||||
internal sealed class Assets : ProfilerMode
|
||||
{
|
||||
private struct Resource
|
||||
{
|
||||
public string Name;
|
||||
public string TypeName;
|
||||
public int ReferencesCount;
|
||||
public ulong MemoryUsage;
|
||||
public Guid AssetId;
|
||||
}
|
||||
|
||||
private readonly SingleChart _memoryUsageChart;
|
||||
private readonly Table _table;
|
||||
private SamplesBuffer<Resource[]> _resources;
|
||||
private List<ClickableRow> _tableRowsCache;
|
||||
private Dictionary<Guid, Resource> _resourceCache;
|
||||
private StringBuilder _stringBuilder;
|
||||
|
||||
public Assets()
|
||||
: base("Assets")
|
||||
{
|
||||
// Layout
|
||||
var panel = new Panel(ScrollBars.Vertical)
|
||||
{
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = Margin.Zero,
|
||||
Parent = this,
|
||||
};
|
||||
var layout = new VerticalPanel
|
||||
{
|
||||
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
||||
Offsets = Margin.Zero,
|
||||
IsScrollable = true,
|
||||
Parent = panel,
|
||||
};
|
||||
|
||||
// Chart
|
||||
_memoryUsageChart = new SingleChart
|
||||
{
|
||||
Title = "Assets Memory Usage (CPU)",
|
||||
FormatSample = v => Utilities.Utils.FormatBytesCount((int)v),
|
||||
Parent = layout,
|
||||
};
|
||||
_memoryUsageChart.SelectedSampleChanged += OnSelectedSampleChanged;
|
||||
|
||||
// Table
|
||||
var headerColor = Style.Current.LightBackground;
|
||||
_table = new Table
|
||||
{
|
||||
Columns = new[]
|
||||
{
|
||||
new ColumnDefinition
|
||||
{
|
||||
UseExpandCollapseMode = true,
|
||||
CellAlignment = TextAlignment.Near,
|
||||
Title = "Resource",
|
||||
TitleBackgroundColor = headerColor,
|
||||
},
|
||||
new ColumnDefinition
|
||||
{
|
||||
Title = "Type",
|
||||
CellAlignment = TextAlignment.Center,
|
||||
TitleBackgroundColor = headerColor,
|
||||
},
|
||||
new ColumnDefinition
|
||||
{
|
||||
Title = "References",
|
||||
TitleBackgroundColor = headerColor,
|
||||
},
|
||||
new ColumnDefinition
|
||||
{
|
||||
Title = "Memory Usage",
|
||||
TitleBackgroundColor = headerColor,
|
||||
FormatValue = v => Utilities.Utils.FormatBytesCount((ulong)v),
|
||||
},
|
||||
},
|
||||
Parent = layout,
|
||||
};
|
||||
_table.Splits = new[]
|
||||
{
|
||||
0.6f,
|
||||
0.2f,
|
||||
0.08f,
|
||||
0.12f,
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Clear()
|
||||
{
|
||||
_memoryUsageChart.Clear();
|
||||
_resources?.Clear();
|
||||
_resourceCache?.Clear();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Update(ref SharedUpdateData sharedData)
|
||||
{
|
||||
if (_resourceCache == null)
|
||||
_resourceCache = new Dictionary<Guid, Resource>();
|
||||
if (_stringBuilder == null)
|
||||
_stringBuilder = new StringBuilder();
|
||||
|
||||
// Capture current assets usage info
|
||||
var assets = FlaxEngine.Content.Assets;
|
||||
var sb = _stringBuilder;
|
||||
var resources = new Resource[assets.Length];
|
||||
var contentDatabase = Editor.Instance.ContentDatabase;
|
||||
ulong totalMemoryUsage = 0;
|
||||
for (int i = 0; i < resources.Length; i++)
|
||||
{
|
||||
var asset = assets[i];
|
||||
if (!asset)
|
||||
continue;
|
||||
|
||||
// Try to reuse cached resource info
|
||||
var assetId = asset.ID;
|
||||
if (!_resourceCache.TryGetValue(assetId, out var resource))
|
||||
{
|
||||
resource = new Resource
|
||||
{
|
||||
Name = asset.Path,
|
||||
TypeName = asset.TypeName,
|
||||
AssetId = assetId,
|
||||
};
|
||||
var typeNameEnding = asset.TypeName.LastIndexOf('.');
|
||||
if (typeNameEnding != -1)
|
||||
resource.TypeName = resource.TypeName.Substring(typeNameEnding + 1);
|
||||
var assetItem = Editor.Instance.ContentDatabase.FindAsset(assetId);
|
||||
if (assetItem != null)
|
||||
{
|
||||
resource.Name = assetItem.NamePath;
|
||||
}
|
||||
if (string.IsNullOrEmpty(resource.Name) && asset.IsVirtual)
|
||||
resource.Name = "<virtual>";
|
||||
_resourceCache.Add(assetId, resource);
|
||||
}
|
||||
|
||||
resource.MemoryUsage = asset.MemoryUsage;
|
||||
totalMemoryUsage += resource.MemoryUsage;
|
||||
resource.ReferencesCount = asset.ReferencesCount;
|
||||
resources[i] = resource;
|
||||
}
|
||||
_memoryUsageChart.AddSample((float)totalMemoryUsage);
|
||||
Array.Sort(resources, SortResources);
|
||||
if (_resources == null)
|
||||
_resources = new SamplesBuffer<Resource[]>();
|
||||
_resources.Add(resources);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void UpdateView(int selectedFrame, bool showOnlyLastUpdateEvents)
|
||||
{
|
||||
_memoryUsageChart.SelectedSampleIndex = selectedFrame;
|
||||
|
||||
if (_resources == null)
|
||||
return;
|
||||
if (_tableRowsCache == null)
|
||||
_tableRowsCache = new List<ClickableRow>();
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
{
|
||||
_resources?.Clear();
|
||||
_resourceCache?.Clear();
|
||||
_tableRowsCache?.Clear();
|
||||
_stringBuilder?.Clear();
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
private static int SortResources(Resource a, Resource b)
|
||||
{
|
||||
return (int)(b.MemoryUsage - a.MemoryUsage);
|
||||
}
|
||||
|
||||
private void UpdateTable()
|
||||
{
|
||||
_table.IsLayoutLocked = true;
|
||||
int idx = 0;
|
||||
while (_table.Children.Count > idx)
|
||||
{
|
||||
var child = _table.Children[idx];
|
||||
if (child is ClickableRow row)
|
||||
{
|
||||
_tableRowsCache.Add(row);
|
||||
child.Parent = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
_table.LockChildrenRecursive();
|
||||
|
||||
UpdateTableInner();
|
||||
|
||||
_table.UnlockChildrenRecursive();
|
||||
_table.PerformLayout();
|
||||
}
|
||||
|
||||
private void UpdateTableInner()
|
||||
{
|
||||
if (_resources.Count == 0)
|
||||
return;
|
||||
var resources = _resources.Get(_memoryUsageChart.SelectedSampleIndex);
|
||||
if (resources == null || resources.Length == 0)
|
||||
return;
|
||||
|
||||
// Add rows
|
||||
var rowColor2 = Style.Current.Background * 1.4f;
|
||||
for (int i = 0; i < resources.Length; i++)
|
||||
{
|
||||
ref var e = ref resources[i];
|
||||
|
||||
ClickableRow row;
|
||||
if (_tableRowsCache.Count != 0)
|
||||
{
|
||||
// Reuse row
|
||||
var last = _tableRowsCache.Count - 1;
|
||||
row = _tableRowsCache[last];
|
||||
_tableRowsCache.RemoveAt(last);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allocate new row
|
||||
row = new ClickableRow { Values = new object[4] };
|
||||
row.RowDoubleClick = OnRowDoubleClick;
|
||||
row.RowRightClick = OnRowRightClick;
|
||||
}
|
||||
|
||||
// Setup row data
|
||||
row.Tag = e.AssetId;
|
||||
row.Values[0] = e.Name;
|
||||
row.Values[1] = e.TypeName;
|
||||
row.Values[2] = e.ReferencesCount;
|
||||
row.Values[3] = e.MemoryUsage;
|
||||
|
||||
// Add row to the table
|
||||
row.Width = _table.Width;
|
||||
row.BackgroundColor = i % 2 == 0 ? rowColor2 : Color.Transparent;
|
||||
row.Parent = _table;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRowDoubleClick(ClickableRow row)
|
||||
{
|
||||
var assetId = (Guid)row.Tag;
|
||||
var assetItem = Editor.Instance.ContentDatabase.FindAsset(assetId);
|
||||
if (assetItem != null)
|
||||
Editor.Instance.ContentEditing.Open(assetItem);
|
||||
}
|
||||
|
||||
private void OnRowRightClick(ClickableRow row)
|
||||
{
|
||||
var assetId = (Guid)row.Tag;
|
||||
var assetItem = Editor.Instance.ContentDatabase.FindAsset(assetId);
|
||||
if (assetItem != null)
|
||||
{
|
||||
var cm = new ContextMenu();
|
||||
ContextMenuButton b;
|
||||
b = cm.AddButton("Open", () => Editor.Instance.ContentEditing.Open(assetItem));
|
||||
cm.AddButton("Show in content window", () => Editor.Instance.Windows.ContentWin.Select(assetItem));
|
||||
cm.AddButton("Show in explorer", () => FileSystem.ShowFileExplorer(System.IO.Path.GetDirectoryName(assetItem.Path)));
|
||||
cm.AddButton("Select actors using this asset", () => Editor.Instance.SceneEditing.SelectActorsUsingAsset(assetItem.ID));
|
||||
cm.AddButton("Show asset references graph", () => Editor.Instance.Windows.Open(new AssetReferencesGraphWindow(Editor.Instance, assetItem)));
|
||||
cm.AddButton("Copy name", () => Clipboard.Text = assetItem.NamePath);
|
||||
cm.AddButton("Copy path", () => Clipboard.Text = assetItem.Path);
|
||||
cm.AddButton("Copy asset ID", () => Clipboard.Text = JsonSerializer.GetStringID(assetItem.ID));
|
||||
cm.Show(row, row.PointFromScreen(Input.MouseScreenPosition));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -205,7 +205,6 @@ namespace FlaxEditor.Windows.Profiler
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
{
|
||||
Clear();
|
||||
_timelineLabelsCache?.Clear();
|
||||
_timelineEventsCache?.Clear();
|
||||
_tableRowsCache?.Clear();
|
||||
|
||||
@@ -166,7 +166,6 @@ namespace FlaxEditor.Windows.Profiler
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
{
|
||||
Clear();
|
||||
_timelineEventsCache?.Clear();
|
||||
_tableRowsCache?.Clear();
|
||||
|
||||
|
||||
@@ -0,0 +1,327 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using FlaxEditor.GUI;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
|
||||
namespace FlaxEditor.Windows.Profiler
|
||||
{
|
||||
/// <summary>
|
||||
/// The GPU Memory profiling mode.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Windows.Profiler.ProfilerMode" />
|
||||
internal sealed class MemoryGPU : ProfilerMode
|
||||
{
|
||||
private struct Resource
|
||||
{
|
||||
public string Name;
|
||||
public string Tooltip;
|
||||
public GPUResourceType Type;
|
||||
public ulong MemoryUsage;
|
||||
public Guid AssetId;
|
||||
public bool IsAssetItem;
|
||||
}
|
||||
|
||||
private readonly SingleChart _memoryUsageChart;
|
||||
private readonly Table _table;
|
||||
private SamplesBuffer<Resource[]> _resources;
|
||||
private List<ClickableRow> _tableRowsCache;
|
||||
private string[] _resourceTypesNames;
|
||||
private Dictionary<string, Guid> _assetPathToId;
|
||||
private Dictionary<Guid, Resource> _resourceCache;
|
||||
private StringBuilder _stringBuilder;
|
||||
|
||||
public MemoryGPU()
|
||||
: base("GPU Memory")
|
||||
{
|
||||
// Layout
|
||||
var panel = new Panel(ScrollBars.Vertical)
|
||||
{
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = Margin.Zero,
|
||||
Parent = this,
|
||||
};
|
||||
var layout = new VerticalPanel
|
||||
{
|
||||
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
||||
Offsets = Margin.Zero,
|
||||
IsScrollable = true,
|
||||
Parent = panel,
|
||||
};
|
||||
|
||||
// Chart
|
||||
_memoryUsageChart = new SingleChart
|
||||
{
|
||||
Title = "GPU Memory Usage",
|
||||
FormatSample = v => Utilities.Utils.FormatBytesCount((int)v),
|
||||
Parent = layout,
|
||||
};
|
||||
_memoryUsageChart.SelectedSampleChanged += OnSelectedSampleChanged;
|
||||
|
||||
// Table
|
||||
var headerColor = Style.Current.LightBackground;
|
||||
_table = new Table
|
||||
{
|
||||
Columns = new[]
|
||||
{
|
||||
new ColumnDefinition
|
||||
{
|
||||
UseExpandCollapseMode = true,
|
||||
CellAlignment = TextAlignment.Near,
|
||||
Title = "Resource",
|
||||
TitleBackgroundColor = headerColor,
|
||||
},
|
||||
new ColumnDefinition
|
||||
{
|
||||
Title = "Type",
|
||||
CellAlignment = TextAlignment.Center,
|
||||
TitleBackgroundColor = headerColor,
|
||||
},
|
||||
new ColumnDefinition
|
||||
{
|
||||
Title = "Memory Usage",
|
||||
TitleBackgroundColor = headerColor,
|
||||
FormatValue = v => Utilities.Utils.FormatBytesCount((ulong)v),
|
||||
},
|
||||
},
|
||||
Parent = layout,
|
||||
};
|
||||
_table.Splits = new[]
|
||||
{
|
||||
0.6f,
|
||||
0.2f,
|
||||
0.2f,
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Clear()
|
||||
{
|
||||
_memoryUsageChart.Clear();
|
||||
_resources?.Clear();
|
||||
_assetPathToId?.Clear();
|
||||
_resourceCache?.Clear();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Update(ref SharedUpdateData sharedData)
|
||||
{
|
||||
_memoryUsageChart.AddSample(sharedData.Stats.MemoryGPU.Used);
|
||||
|
||||
if (_resourceCache == null)
|
||||
_resourceCache = new Dictionary<Guid, Resource>();
|
||||
if (_assetPathToId == null)
|
||||
_assetPathToId = new Dictionary<string, Guid>();
|
||||
if (_stringBuilder == null)
|
||||
_stringBuilder = new StringBuilder();
|
||||
|
||||
// Capture current GPU resources usage info
|
||||
var contentDatabase = Editor.Instance.ContentDatabase;
|
||||
var gpuResources = GPUDevice.Instance.Resources;
|
||||
var resources = new Resource[gpuResources.Length];
|
||||
var sb = _stringBuilder;
|
||||
for (int i = 0; i < resources.Length; i++)
|
||||
{
|
||||
var gpuResource = gpuResources[i];
|
||||
|
||||
// Try to reuse cached resource info
|
||||
var gpuResourceId = gpuResource.ID;
|
||||
if (!_resourceCache.TryGetValue(gpuResourceId, out var resource))
|
||||
{
|
||||
resource = new Resource
|
||||
{
|
||||
Name = gpuResource.Name,
|
||||
Type = gpuResource.ResourceType,
|
||||
};
|
||||
|
||||
// Create tooltip
|
||||
sb.Clear();
|
||||
if (gpuResource is GPUTexture gpuTexture)
|
||||
{
|
||||
var desc = gpuTexture.Description;
|
||||
sb.Append("Format: ").Append(desc.Format).AppendLine();
|
||||
sb.Append("Size: ").Append(desc.Width).Append('x').Append(desc.Height);
|
||||
if (desc.Depth != 1)
|
||||
sb.Append('x').Append(desc.Depth);
|
||||
if (desc.ArraySize != 1)
|
||||
sb.Append('[').Append(desc.ArraySize).Append(']');
|
||||
sb.AppendLine();
|
||||
sb.Append("Mip Levels: ").Append(desc.MipLevels).AppendLine();
|
||||
if (desc.IsMultiSample)
|
||||
sb.Append("MSAA: ").Append('x').Append((int)desc.MultiSampleLevel).AppendLine();
|
||||
sb.Append("Flags: ").Append(desc.Flags).AppendLine();
|
||||
sb.Append("Usage: ").Append(desc.Usage);
|
||||
}
|
||||
else if (gpuResource is GPUBuffer gpuBuffer)
|
||||
{
|
||||
var desc = gpuBuffer.Description;
|
||||
sb.Append("Format: ").Append(desc.Format).AppendLine();
|
||||
sb.Append("Stride: ").Append(desc.Stride).AppendLine();
|
||||
sb.Append("Elements: ").Append(desc.ElementsCount).AppendLine();
|
||||
sb.Append("Flags: ").Append(desc.Flags).AppendLine();
|
||||
sb.Append("Usage: ").Append(desc.Usage);
|
||||
}
|
||||
resource.Tooltip = _stringBuilder.ToString();
|
||||
|
||||
// Detect asset path in the resource name
|
||||
int ext = resource.Name.LastIndexOf(".flax", StringComparison.OrdinalIgnoreCase);
|
||||
if (ext != -1)
|
||||
{
|
||||
var assetPath = resource.Name.Substring(0, ext + 5);
|
||||
if (!_assetPathToId.TryGetValue(assetPath, out resource.AssetId))
|
||||
{
|
||||
var asset = FlaxEngine.Content.GetAsset(assetPath);
|
||||
if (asset != null)
|
||||
resource.AssetId = asset.ID;
|
||||
_assetPathToId.Add(assetPath, resource.AssetId);
|
||||
}
|
||||
var assetItem = contentDatabase.FindAsset(resource.AssetId);
|
||||
if (assetItem != null)
|
||||
{
|
||||
resource.IsAssetItem = true;
|
||||
resource.Name = assetItem.NamePath + resource.Name.Substring(ext + 5); // Use text after asset path to display (eg. subobject)
|
||||
}
|
||||
}
|
||||
|
||||
_resourceCache.Add(gpuResourceId, resource);
|
||||
}
|
||||
|
||||
resource.MemoryUsage = gpuResource.MemoryUsage;
|
||||
if (resource.MemoryUsage == 1)
|
||||
resource.MemoryUsage = 0; // Sometimes GPU backend fakes memory usage as 1 to mark as allocated but not resided in actual GPU memory
|
||||
resources[i] = resource;
|
||||
}
|
||||
Array.Sort(resources, SortResources);
|
||||
if (_resources == null)
|
||||
_resources = new SamplesBuffer<Resource[]>();
|
||||
_resources.Add(resources);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void UpdateView(int selectedFrame, bool showOnlyLastUpdateEvents)
|
||||
{
|
||||
_memoryUsageChart.SelectedSampleIndex = selectedFrame;
|
||||
|
||||
if (_resources == null)
|
||||
return;
|
||||
if (_tableRowsCache == null)
|
||||
_tableRowsCache = new List<ClickableRow>();
|
||||
if (_resourceTypesNames == null)
|
||||
_resourceTypesNames = new string[(int)GPUResourceType.MAX]
|
||||
{
|
||||
"Render Target",
|
||||
"Texture",
|
||||
"Cube Texture",
|
||||
"Volume Texture",
|
||||
"Buffer",
|
||||
"Shader",
|
||||
"Pipeline State",
|
||||
"Descriptor",
|
||||
"Query",
|
||||
"Sampler",
|
||||
};
|
||||
UpdateTable();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
{
|
||||
_resources?.Clear();
|
||||
_resourceCache?.Clear();
|
||||
_assetPathToId?.Clear();
|
||||
_tableRowsCache?.Clear();
|
||||
_stringBuilder?.Clear();
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
private static int SortResources(Resource a, Resource b)
|
||||
{
|
||||
return (int)(b.MemoryUsage - a.MemoryUsage);
|
||||
}
|
||||
|
||||
private void UpdateTable()
|
||||
{
|
||||
_table.IsLayoutLocked = true;
|
||||
int idx = 0;
|
||||
while (_table.Children.Count > idx)
|
||||
{
|
||||
var child = _table.Children[idx];
|
||||
if (child is ClickableRow row)
|
||||
{
|
||||
_tableRowsCache.Add(row);
|
||||
child.Parent = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
_table.LockChildrenRecursive();
|
||||
|
||||
UpdateTableInner();
|
||||
|
||||
_table.UnlockChildrenRecursive();
|
||||
_table.PerformLayout();
|
||||
}
|
||||
|
||||
private void UpdateTableInner()
|
||||
{
|
||||
if (_resources.Count == 0)
|
||||
return;
|
||||
var resources = _resources.Get(_memoryUsageChart.SelectedSampleIndex);
|
||||
if (resources == null || resources.Length == 0)
|
||||
return;
|
||||
|
||||
// Add rows
|
||||
var rowColor2 = Style.Current.Background * 1.4f;
|
||||
for (int i = 0; i < resources.Length; i++)
|
||||
{
|
||||
ref var e = ref resources[i];
|
||||
|
||||
ClickableRow row;
|
||||
if (_tableRowsCache.Count != 0)
|
||||
{
|
||||
// Reuse row
|
||||
var last = _tableRowsCache.Count - 1;
|
||||
row = _tableRowsCache[last];
|
||||
_tableRowsCache.RemoveAt(last);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allocate new row
|
||||
row = new ClickableRow { Values = new object[3] };
|
||||
}
|
||||
|
||||
// Setup row data
|
||||
row.Values[0] = e.Name;
|
||||
row.Values[1] = _resourceTypesNames[(int)e.Type];
|
||||
row.Values[2] = e.MemoryUsage;
|
||||
|
||||
// Setup row interactions
|
||||
row.Tag = e;
|
||||
row.TooltipText = e.Tooltip;
|
||||
row.RowDoubleClick = null;
|
||||
if (e.IsAssetItem)
|
||||
{
|
||||
row.RowDoubleClick = OnRowDoubleClickAsset;
|
||||
}
|
||||
|
||||
// Add row to the table
|
||||
row.Width = _table.Width;
|
||||
row.BackgroundColor = i % 2 == 0 ? rowColor2 : Color.Transparent;
|
||||
row.Parent = _table;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRowDoubleClickAsset(ClickableRow row)
|
||||
{
|
||||
var e = (Resource)row.Tag;
|
||||
var assetItem = Editor.Instance.ContentDatabase.FindAsset(e.AssetId);
|
||||
Editor.Instance.ContentEditing.Open(assetItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
|
||||
namespace FlaxEditor.Windows.Profiler
|
||||
{
|
||||
/// <summary>
|
||||
/// The network profiling mode.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Windows.Profiler.ProfilerMode" />
|
||||
internal sealed class Network : ProfilerMode
|
||||
{
|
||||
private readonly SingleChart _dataSentChart;
|
||||
private readonly SingleChart _dataReceivedChart;
|
||||
private FlaxEngine.Networking.NetworkDriverStats _prevStats;
|
||||
|
||||
public Network()
|
||||
: base("Network")
|
||||
{
|
||||
// Layout
|
||||
var panel = new Panel(ScrollBars.Vertical)
|
||||
{
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = Margin.Zero,
|
||||
Parent = this,
|
||||
};
|
||||
var layout = new VerticalPanel
|
||||
{
|
||||
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
||||
Offsets = Margin.Zero,
|
||||
IsScrollable = true,
|
||||
Parent = panel,
|
||||
};
|
||||
|
||||
// Charts
|
||||
_dataSentChart = new SingleChart
|
||||
{
|
||||
Title = "Data Sent",
|
||||
FormatSample = FormatSampleBytes,
|
||||
Parent = layout,
|
||||
};
|
||||
_dataSentChart.SelectedSampleChanged += OnSelectedSampleChanged;
|
||||
_dataReceivedChart = new SingleChart
|
||||
{
|
||||
Title = "Data Received",
|
||||
FormatSample = FormatSampleBytes,
|
||||
Parent = layout,
|
||||
};
|
||||
_dataReceivedChart.SelectedSampleChanged += OnSelectedSampleChanged;
|
||||
}
|
||||
|
||||
private static string FormatSampleBytes(float v)
|
||||
{
|
||||
return (uint)v + " bytes";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Clear()
|
||||
{
|
||||
_dataSentChart.Clear();
|
||||
_dataReceivedChart.Clear();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Update(ref SharedUpdateData sharedData)
|
||||
{
|
||||
var peer = FlaxEngine.Networking.NetworkManager.Peer;
|
||||
if (peer == null)
|
||||
{
|
||||
_prevStats = new FlaxEngine.Networking.NetworkDriverStats();
|
||||
return;
|
||||
}
|
||||
var stats = peer.NetworkDriver.GetStats();
|
||||
_dataSentChart.AddSample(Mathf.Max((long)stats.TotalDataSent - (long)_prevStats.TotalDataSent, 0));
|
||||
_dataReceivedChart.AddSample(Mathf.Max((long)stats.TotalDataReceived - (long)_prevStats.TotalDataReceived, 0));
|
||||
_prevStats = stats;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void UpdateView(int selectedFrame, bool showOnlyLastUpdateEvents)
|
||||
{
|
||||
_dataSentChart.SelectedSampleIndex = selectedFrame;
|
||||
_dataReceivedChart.SelectedSampleIndex = selectedFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,6 +83,14 @@ namespace FlaxEditor.Windows.Profiler
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
{
|
||||
Clear();
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this instance.
|
||||
/// </summary>
|
||||
|
||||
@@ -52,10 +52,8 @@ namespace FlaxEditor.Windows.Profiler
|
||||
if (_frameIndex != value)
|
||||
{
|
||||
_frameIndex = value;
|
||||
|
||||
UpdateButtons();
|
||||
if (_tabs.SelectedTab is ProfilerMode mode)
|
||||
mode.UpdateView(_frameIndex, _showOnlyLastUpdateEvents);
|
||||
UpdateView();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,10 +69,8 @@ namespace FlaxEditor.Windows.Profiler
|
||||
if (_showOnlyLastUpdateEvents != value)
|
||||
{
|
||||
_showOnlyLastUpdateEvents = value;
|
||||
|
||||
UpdateButtons();
|
||||
if (_tabs.SelectedTab is ProfilerMode mode)
|
||||
mode.UpdateView(_frameIndex, _showOnlyLastUpdateEvents);
|
||||
UpdateView();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,7 +148,9 @@ namespace FlaxEditor.Windows.Profiler
|
||||
if (_tabs.Children[i] is ProfilerMode mode)
|
||||
{
|
||||
mode.Clear();
|
||||
FlaxEngine.Profiler.BeginEvent("ProfilerWindow.UpdateView");
|
||||
mode.UpdateView(ViewFrameIndex, _showOnlyLastUpdateEvents);
|
||||
FlaxEngine.Profiler.EndEvent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +160,11 @@ namespace FlaxEditor.Windows.Profiler
|
||||
private void OnSelectedTabChanged(Tabs tabs)
|
||||
{
|
||||
if (tabs.SelectedTab is ProfilerMode mode)
|
||||
{
|
||||
FlaxEngine.Profiler.BeginEvent("ProfilerWindow.UpdateView");
|
||||
mode.UpdateView(ViewFrameIndex, _showOnlyLastUpdateEvents);
|
||||
FlaxEngine.Profiler.EndEvent();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateButtons()
|
||||
@@ -174,6 +176,16 @@ namespace FlaxEditor.Windows.Profiler
|
||||
_showOnlyLastUpdateEventsButton.Checked = _showOnlyLastUpdateEvents;
|
||||
}
|
||||
|
||||
private void UpdateView()
|
||||
{
|
||||
if (_tabs.SelectedTab is ProfilerMode mode)
|
||||
{
|
||||
FlaxEngine.Profiler.BeginEvent("ProfilerWindow.UpdateView");
|
||||
mode.UpdateView(_frameIndex, _showOnlyLastUpdateEvents);
|
||||
FlaxEngine.Profiler.EndEvent();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnInit()
|
||||
{
|
||||
@@ -181,7 +193,10 @@ namespace FlaxEditor.Windows.Profiler
|
||||
AddMode(new Overall());
|
||||
AddMode(new CPU());
|
||||
AddMode(new GPU());
|
||||
AddMode(new MemoryGPU());
|
||||
AddMode(new Memory());
|
||||
AddMode(new Assets());
|
||||
AddMode(new Network());
|
||||
|
||||
// Init view
|
||||
_frameIndex = -1;
|
||||
@@ -192,6 +207,8 @@ namespace FlaxEditor.Windows.Profiler
|
||||
}
|
||||
|
||||
UpdateButtons();
|
||||
|
||||
ScriptsBuilder.ScriptsReloadEnd += Clear; // Prevent crashes if any of the profiler tabs has some scripting types cached (eg. asset type info)
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -206,11 +223,19 @@ namespace FlaxEditor.Windows.Profiler
|
||||
for (int i = 0; i < _tabs.ChildrenCount; i++)
|
||||
{
|
||||
if (_tabs.Children[i] is ProfilerMode mode)
|
||||
{
|
||||
FlaxEngine.Profiler.BeginEvent(mode.GetType().FullName);
|
||||
mode.Update(ref sharedData);
|
||||
FlaxEngine.Profiler.EndEvent();
|
||||
}
|
||||
}
|
||||
{
|
||||
if (_tabs.SelectedTab is ProfilerMode mode)
|
||||
{
|
||||
FlaxEngine.Profiler.BeginEvent("ProfilerWindow.UpdateView");
|
||||
mode.UpdateView(_frameIndex, _showOnlyLastUpdateEvents);
|
||||
FlaxEngine.Profiler.EndEvent();
|
||||
}
|
||||
}
|
||||
sharedData.End();
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FlaxEditor.GUI.Tabs;
|
||||
using FlaxEditor.GUI.Tree;
|
||||
using FlaxEditor.Scripting;
|
||||
@@ -100,6 +99,7 @@ namespace FlaxEditor.Windows
|
||||
|
||||
private TextBox _searchBox;
|
||||
private ContainerControl _groupSearch;
|
||||
private Tabs _actorGroups;
|
||||
|
||||
/// <summary>
|
||||
/// The editor instance.
|
||||
@@ -117,8 +117,9 @@ namespace FlaxEditor.Windows
|
||||
Editor = editor;
|
||||
Selected += tab => Editor.Windows.EditWin.Viewport.SetActiveMode<TransformGizmoMode>();
|
||||
ScriptsBuilder.ScriptsReload += OnScriptsReload;
|
||||
ScriptsBuilder.ScriptsReloadEnd += OnScriptsReloadEnd;
|
||||
|
||||
var actorGroups = new Tabs
|
||||
_actorGroups = new Tabs
|
||||
{
|
||||
Orientation = Orientation.Vertical,
|
||||
UseScroll = true,
|
||||
@@ -128,74 +129,19 @@ namespace FlaxEditor.Windows
|
||||
Parent = this,
|
||||
};
|
||||
|
||||
_groupSearch = CreateGroupWithList(actorGroups, "Search", 26);
|
||||
_groupSearch = CreateGroupWithList(_actorGroups, "Search", 26);
|
||||
_searchBox = new TextBox
|
||||
{
|
||||
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
||||
WatermarkText = "Search...",
|
||||
Parent = _groupSearch.Parent.Parent,
|
||||
Bounds = new Rectangle(4, 4, actorGroups.Width - 8, 18),
|
||||
Bounds = new Rectangle(4, 4, _actorGroups.Width - 8, 18),
|
||||
};
|
||||
_searchBox.TextChanged += OnSearchBoxTextChanged;
|
||||
|
||||
var groupBasicModels = CreateGroupWithList(actorGroups, "Basic Models");
|
||||
groupBasicModels.AddChild(CreateEditorAssetItem("Cube", "Primitives/Cube.flax"));
|
||||
groupBasicModels.AddChild(CreateEditorAssetItem("Sphere", "Primitives/Sphere.flax"));
|
||||
groupBasicModels.AddChild(CreateEditorAssetItem("Plane", "Primitives/Plane.flax"));
|
||||
groupBasicModels.AddChild(CreateEditorAssetItem("Cylinder", "Primitives/Cylinder.flax"));
|
||||
groupBasicModels.AddChild(CreateEditorAssetItem("Cone", "Primitives/Cone.flax"));
|
||||
groupBasicModels.AddChild(CreateEditorAssetItem("Capsule", "Primitives/Capsule.flax"));
|
||||
RefreshActorTabs();
|
||||
|
||||
var groupLights = CreateGroupWithList(actorGroups, "Lights");
|
||||
groupLights.AddChild(CreateActorItem("Directional Light", typeof(DirectionalLight)));
|
||||
groupLights.AddChild(CreateActorItem("Point Light", typeof(PointLight)));
|
||||
groupLights.AddChild(CreateActorItem("Spot Light", typeof(SpotLight)));
|
||||
groupLights.AddChild(CreateActorItem("Sky Light", typeof(SkyLight)));
|
||||
|
||||
var groupVisuals = CreateGroupWithList(actorGroups, "Visuals");
|
||||
groupVisuals.AddChild(CreateActorItem("Camera", typeof(Camera)));
|
||||
groupVisuals.AddChild(CreateActorItem("Environment Probe", typeof(EnvironmentProbe)));
|
||||
groupVisuals.AddChild(CreateActorItem("Skybox", typeof(Skybox)));
|
||||
groupVisuals.AddChild(CreateActorItem("Sky", typeof(Sky)));
|
||||
groupVisuals.AddChild(CreateActorItem("Exponential Height Fog", typeof(ExponentialHeightFog)));
|
||||
groupVisuals.AddChild(CreateActorItem("PostFx Volume", typeof(PostFxVolume)));
|
||||
groupVisuals.AddChild(CreateActorItem("Decal", typeof(Decal)));
|
||||
groupVisuals.AddChild(CreateActorItem("Particle Effect", typeof(ParticleEffect)));
|
||||
|
||||
var groupPhysics = CreateGroupWithList(actorGroups, "Physics");
|
||||
groupPhysics.AddChild(CreateActorItem("Rigid Body", typeof(RigidBody)));
|
||||
groupPhysics.AddChild(CreateActorItem("Character Controller", typeof(CharacterController)));
|
||||
groupPhysics.AddChild(CreateActorItem("Box Collider", typeof(BoxCollider)));
|
||||
groupPhysics.AddChild(CreateActorItem("Sphere Collider", typeof(SphereCollider)));
|
||||
groupPhysics.AddChild(CreateActorItem("Capsule Collider", typeof(CapsuleCollider)));
|
||||
groupPhysics.AddChild(CreateActorItem("Mesh Collider", typeof(MeshCollider)));
|
||||
groupPhysics.AddChild(CreateActorItem("Fixed Joint", typeof(FixedJoint)));
|
||||
groupPhysics.AddChild(CreateActorItem("Distance Joint", typeof(DistanceJoint)));
|
||||
groupPhysics.AddChild(CreateActorItem("Slider Joint", typeof(SliderJoint)));
|
||||
groupPhysics.AddChild(CreateActorItem("Spherical Joint", typeof(SphericalJoint)));
|
||||
groupPhysics.AddChild(CreateActorItem("Hinge Joint", typeof(HingeJoint)));
|
||||
groupPhysics.AddChild(CreateActorItem("D6 Joint", typeof(D6Joint)));
|
||||
|
||||
var groupOther = CreateGroupWithList(actorGroups, "Other");
|
||||
groupOther.AddChild(CreateActorItem("Animated Model", typeof(AnimatedModel)));
|
||||
groupOther.AddChild(CreateActorItem("Bone Socket", typeof(BoneSocket)));
|
||||
groupOther.AddChild(CreateActorItem("CSG Box Brush", typeof(BoxBrush)));
|
||||
groupOther.AddChild(CreateActorItem("Audio Source", typeof(AudioSource)));
|
||||
groupOther.AddChild(CreateActorItem("Audio Listener", typeof(AudioListener)));
|
||||
groupOther.AddChild(CreateActorItem("Empty Actor", typeof(EmptyActor)));
|
||||
groupOther.AddChild(CreateActorItem("Scene Animation", typeof(SceneAnimationPlayer)));
|
||||
groupOther.AddChild(CreateActorItem("Nav Mesh Bounds Volume", typeof(NavMeshBoundsVolume)));
|
||||
groupOther.AddChild(CreateActorItem("Nav Link", typeof(NavLink)));
|
||||
groupOther.AddChild(CreateActorItem("Nav Modifier Volume", typeof(NavModifierVolume)));
|
||||
groupOther.AddChild(CreateActorItem("Spline", typeof(Spline)));
|
||||
|
||||
var groupGui = CreateGroupWithList(actorGroups, "GUI");
|
||||
groupGui.AddChild(CreateActorItem("UI Control", typeof(UIControl)));
|
||||
groupGui.AddChild(CreateActorItem("UI Canvas", typeof(UICanvas)));
|
||||
groupGui.AddChild(CreateActorItem("Text Render", typeof(TextRender)));
|
||||
groupGui.AddChild(CreateActorItem("Sprite Render", typeof(SpriteRender)));
|
||||
|
||||
actorGroups.SelectedTabIndex = 1;
|
||||
_actorGroups.SelectedTabIndex = 1;
|
||||
}
|
||||
|
||||
private void OnScriptsReload()
|
||||
@@ -206,6 +152,91 @@ namespace FlaxEditor.Windows
|
||||
_groupSearch.PerformLayout();
|
||||
}
|
||||
|
||||
private void OnScriptsReloadEnd()
|
||||
{
|
||||
RefreshActorTabs();
|
||||
}
|
||||
|
||||
private void RefreshActorTabs()
|
||||
{
|
||||
// Remove tabs
|
||||
var tabs = new List<Tab>();
|
||||
foreach (var child in _actorGroups.Children)
|
||||
{
|
||||
if (child is Tab tab)
|
||||
{
|
||||
if (tab.Text != "Search")
|
||||
tabs.Add(tab);
|
||||
}
|
||||
}
|
||||
foreach (var tab in tabs)
|
||||
{
|
||||
var group = _actorGroups.Children.Find(T => T == tab);
|
||||
group.Dispose();
|
||||
}
|
||||
|
||||
// Setup primitives tabs
|
||||
var groupBasicModels = CreateGroupWithList(_actorGroups, "Basic Models");
|
||||
groupBasicModels.AddChild(CreateEditorAssetItem("Cube", "Primitives/Cube.flax"));
|
||||
groupBasicModels.AddChild(CreateEditorAssetItem("Sphere", "Primitives/Sphere.flax"));
|
||||
groupBasicModels.AddChild(CreateEditorAssetItem("Plane", "Primitives/Plane.flax"));
|
||||
groupBasicModels.AddChild(CreateEditorAssetItem("Cylinder", "Primitives/Cylinder.flax"));
|
||||
groupBasicModels.AddChild(CreateEditorAssetItem("Cone", "Primitives/Cone.flax"));
|
||||
groupBasicModels.AddChild(CreateEditorAssetItem("Capsule", "Primitives/Capsule.flax"));
|
||||
|
||||
// Created first to order specific tabs
|
||||
CreateGroupWithList(_actorGroups, "Lights");
|
||||
CreateGroupWithList(_actorGroups, "Visuals");
|
||||
CreateGroupWithList(_actorGroups, "Physics");
|
||||
CreateGroupWithList(_actorGroups, "GUI");
|
||||
CreateGroupWithList(_actorGroups, "Other");
|
||||
|
||||
// Add other actor types to respective tab based on attribute
|
||||
foreach (var actorType in Editor.CodeEditing.Actors.Get())
|
||||
{
|
||||
if (actorType.IsAbstract)
|
||||
continue;
|
||||
ActorToolboxAttribute attribute = null;
|
||||
foreach (var e in actorType.GetAttributes(false))
|
||||
{
|
||||
if (e is ActorToolboxAttribute actorToolboxAttribute)
|
||||
{
|
||||
attribute = actorToolboxAttribute;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (attribute == null)
|
||||
continue;
|
||||
var groupName = attribute.Group.Trim();
|
||||
|
||||
// Check if tab already exists and add it to the tab
|
||||
var actorTabExists = false;
|
||||
foreach (var child in _actorGroups.Children)
|
||||
{
|
||||
if (child is Tab tab)
|
||||
{
|
||||
if (string.Equals(tab.Text, groupName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var tree = tab.GetChild<Panel>().GetChild<Tree>();
|
||||
if (tree != null)
|
||||
{
|
||||
tree.AddChild(string.IsNullOrEmpty(attribute.Name) ? CreateActorItem(Utilities.Utils.GetPropertyNameUI(actorType.Name), actorType) : CreateActorItem(attribute.Name, actorType));
|
||||
tree.SortChildren();
|
||||
}
|
||||
actorTabExists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (actorTabExists)
|
||||
continue;
|
||||
|
||||
var group = CreateGroupWithList(_actorGroups, groupName);
|
||||
group.AddChild(string.IsNullOrEmpty(attribute.Name) ? CreateActorItem(Utilities.Utils.GetPropertyNameUI(actorType.Name), actorType) : CreateActorItem(attribute.Name, actorType));
|
||||
group.SortChildren();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSearchBoxTextChanged()
|
||||
{
|
||||
// Skip events during setup or init stuff
|
||||
@@ -218,7 +249,17 @@ namespace FlaxEditor.Windows
|
||||
|
||||
foreach (var actorType in Editor.CodeEditing.Actors.Get())
|
||||
{
|
||||
var text = actorType.Name;
|
||||
ActorToolboxAttribute attribute = null;
|
||||
foreach (var e in actorType.GetAttributes(true))
|
||||
{
|
||||
if (e is ActorToolboxAttribute actorToolboxAttribute)
|
||||
{
|
||||
attribute = actorToolboxAttribute;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var text = (attribute == null) ? actorType.Name : string.IsNullOrEmpty(attribute.Name) ? actorType.Name : attribute.Name;
|
||||
|
||||
if (!QueryFilterHelper.Match(filterText, text, out QueryFilterHelper.Range[] ranges))
|
||||
continue;
|
||||
@@ -249,11 +290,6 @@ namespace FlaxEditor.Windows
|
||||
return new Item(name, GUI.Drag.DragItems.GetDragData(path));
|
||||
}
|
||||
|
||||
private Item CreateActorItem(string name, Type type)
|
||||
{
|
||||
return CreateActorItem(name, new ScriptType(type));
|
||||
}
|
||||
|
||||
private Item CreateActorItem(string name, ScriptType type)
|
||||
{
|
||||
return new ScriptTypeItem(name, type, GUI.Drag.DragActorType.GetDragData(type));
|
||||
|
||||
@@ -86,6 +86,11 @@ public:
|
||||
{
|
||||
return Position.GetKeyframes().Count() + Rotation.GetKeyframes().Count() + Scale.GetKeyframes().Count();
|
||||
}
|
||||
|
||||
uint64 GetMemoryUsage() const
|
||||
{
|
||||
return NodeName.Length() * sizeof(Char) + Position.GetMemoryUsage() + Rotation.GetMemoryUsage() + Scale.GetMemoryUsage();
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -131,6 +136,14 @@ public:
|
||||
return static_cast<float>(Duration / FramesPerSecond);
|
||||
}
|
||||
|
||||
uint64 GetMemoryUsage() const
|
||||
{
|
||||
uint64 result = RootNodeName.Length() * sizeof(Char) + Channels.Capacity() * sizeof(NodeAnimationData);
|
||||
for (const auto& e : Channels)
|
||||
result += e.GetMemoryUsage();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total amount of keyframes in the all animation channels.
|
||||
/// </summary>
|
||||
|
||||
@@ -733,6 +733,11 @@ public:
|
||||
_keyframes[i].Time = _keyframes[i].Time * timeScale + timeOffset;;
|
||||
}
|
||||
|
||||
uint64 GetMemoryUsage() const
|
||||
{
|
||||
return _keyframes.Capacity() * sizeof(KeyFrame);
|
||||
}
|
||||
|
||||
public:
|
||||
FORCE_INLINE KeyFrame& operator[](int32 index)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
/// <summary>
|
||||
/// The scene animation playback actor.
|
||||
/// </summary>
|
||||
API_CLASS(Attributes = "ActorContextMenu(\"New/Other/Scene Animation\")") class FLAXENGINE_API SceneAnimationPlayer : public Actor, public IPostFxSettingsProvider
|
||||
API_CLASS(Attributes="ActorContextMenu(\"New/Other/Scene Animation\"), ActorToolbox(\"Other\", \"Scene Animation\")")
|
||||
class FLAXENGINE_API SceneAnimationPlayer : public Actor, public IPostFxSettingsProvider
|
||||
{
|
||||
DECLARE_SCENE_OBJECT(SceneAnimationPlayer);
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
/// <summary>
|
||||
/// Represents a listener that hears audio sources. For spatial audio the volume and pitch of played audio is determined by the distance, orientation and velocity differences between the source and the listener.
|
||||
/// </summary>
|
||||
API_CLASS(Attributes="ActorContextMenu(\"New/Audio/Audio Listener\")") class FLAXENGINE_API AudioListener : public Actor
|
||||
API_CLASS(Attributes="ActorContextMenu(\"New/Audio/Audio Listener\"), ActorToolbox(\"Other\")")
|
||||
class FLAXENGINE_API AudioListener : public Actor
|
||||
{
|
||||
DECLARE_SCENE_OBJECT(AudioListener);
|
||||
private:
|
||||
|
||||
@@ -132,7 +132,7 @@ void AudioSource::Play()
|
||||
Clip->RequestStreamingUpdate();
|
||||
|
||||
// If we are looping and streaming also update streaming buffers
|
||||
if (_loop)
|
||||
if (_loop || state == States::Stopped)
|
||||
RequestStreamingBuffersUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
/// <remarks>
|
||||
/// Whether or not an audio source is spatial is controlled by the assigned AudioClip.The volume and the pitch of a spatial audio source is controlled by its position and the AudioListener's position/direction/velocity.
|
||||
/// </remarks>
|
||||
API_CLASS(Attributes="ActorContextMenu(\"New/Audio/Audio Source\")") class FLAXENGINE_API AudioSource : public Actor
|
||||
API_CLASS(Attributes="ActorContextMenu(\"New/Audio/Audio Source\"), ActorToolbox(\"Other\")")
|
||||
class FLAXENGINE_API AudioSource : public Actor
|
||||
{
|
||||
DECLARE_SCENE_OBJECT(AudioSource);
|
||||
friend class AudioStreamingHandler;
|
||||
|
||||
@@ -314,6 +314,17 @@ bool Asset::ShouldDeleteFileOnUnload() const
|
||||
|
||||
#endif
|
||||
|
||||
uint64 Asset::GetMemoryUsage() const
|
||||
{
|
||||
uint64 result = sizeof(Asset);
|
||||
Locker.Lock();
|
||||
if (_loadingTask)
|
||||
result += sizeof(ContentLoadTask);
|
||||
result += (OnLoaded.Capacity() + OnReloading.Capacity() + OnUnloaded.Capacity()) * sizeof(EventType::FunctionType);
|
||||
Locker.Unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
void Asset::Reload()
|
||||
{
|
||||
// Virtual assets are memory-only so reloading them makes no sense
|
||||
|
||||
@@ -128,14 +128,17 @@ public:
|
||||
}
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this asset was marked to be deleted on unload.
|
||||
/// </summary>
|
||||
API_PROPERTY() bool ShouldDeleteFileOnUnload() const;
|
||||
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Gets amount of CPU memory used by this resource (in bytes). It's a rough estimation. Memory may be fragmented, compressed or sub-allocated so the actual memory pressure from this resource may vary.
|
||||
/// </summary>
|
||||
API_PROPERTY() virtual uint64 GetMemoryUsage() const;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Reloads the asset.
|
||||
@@ -160,7 +163,6 @@ public:
|
||||
virtual void CancelStreaming();
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
/// <summary>
|
||||
/// Gets the asset references. Supported only in Editor.
|
||||
/// </summary>
|
||||
@@ -184,7 +186,6 @@ public:
|
||||
/// </remarks>
|
||||
/// <returns>The collection of the asset ids referenced by this asset.</returns>
|
||||
API_FUNCTION() Array<Guid, HeapAllocation> GetReferences() const;
|
||||
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -54,8 +54,5 @@ public:
|
||||
/// Gets the string.
|
||||
/// </summary>
|
||||
/// <returns>The string.</returns>
|
||||
String ToString() const
|
||||
{
|
||||
return String::Format(TEXT("ID: {0}, TypeName: {1}, Path: \'{2}\'"), ID, TypeName, Path);
|
||||
}
|
||||
String ToString() const;
|
||||
};
|
||||
|
||||
@@ -569,6 +569,23 @@ void Animation::OnSkinnedModelUnloaded(Asset* obj)
|
||||
MappingCache.Remove(i);
|
||||
}
|
||||
|
||||
uint64 Animation::GetMemoryUsage() const
|
||||
{
|
||||
Locker.Lock();
|
||||
uint64 result = BinaryAsset::GetMemoryUsage();
|
||||
result += sizeof(Animation) - sizeof(BinaryAsset);
|
||||
result += Data.GetMemoryUsage();
|
||||
result += Events.Capacity() * sizeof(Pair<String, StepCurve<AnimEventData>>);
|
||||
for (const auto& e : Events)
|
||||
result += e.First.Length() * sizeof(Char) + e.Second.GetMemoryUsage();
|
||||
result += NestedAnims.Capacity() * sizeof(Pair<String, NestedAnimData>);
|
||||
result += MappingCache.Capacity() * sizeof(Pair<String, StepCurve<AnimEventData>>);
|
||||
for (const auto& e : MappingCache)
|
||||
result += e.Value.Capacity() * sizeof(int32);
|
||||
Locker.Unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
void Animation::OnScriptingDispose()
|
||||
{
|
||||
// Dispose any events to prevent crashes (scripting is released before content)
|
||||
|
||||
@@ -152,7 +152,6 @@ public:
|
||||
const NodeToChannel* GetMapping(SkinnedModel* obj);
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
/// <summary>
|
||||
/// Gets the animation as serialized timeline data. Used to show it in Editor.
|
||||
/// </summary>
|
||||
@@ -173,7 +172,6 @@ public:
|
||||
/// <remarks>The cannot be used by virtual assets.</remarks>
|
||||
/// <returns><c>true</c> failed to save data; otherwise, <c>false</c>.</returns>
|
||||
bool Save(const StringView& path = StringView::Empty);
|
||||
|
||||
#endif
|
||||
|
||||
private:
|
||||
@@ -181,6 +179,7 @@ private:
|
||||
|
||||
public:
|
||||
// [BinaryAsset]
|
||||
uint64 GetMemoryUsage() const override;
|
||||
void OnScriptingDispose() override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -482,7 +482,7 @@ void Material::InitCompilationOptions(ShaderCompilationOptions& options)
|
||||
options.Macros.Add({ "MATERIAL_TESSELLATION", "MATERIAL_TESSELLATION_PHONG" });
|
||||
break;
|
||||
}
|
||||
options.Macros.Add({ "MAX_TESSELLATION_FACTOR", Numbers[info.MaxTessellationFactor] });
|
||||
options.Macros.Add({ "MAX_TESSELLATION_FACTOR", Numbers[Math::Min<int32>(info.MaxTessellationFactor, ARRAY_COUNT(Numbers) - 1)] });
|
||||
}
|
||||
|
||||
// Helper macros (used by the parser)
|
||||
|
||||
@@ -722,6 +722,7 @@ bool Model::Init(const Span<int32>& meshesCountPerLod)
|
||||
{
|
||||
auto& lod = LODs[lodIndex];
|
||||
lod._model = this;
|
||||
lod._lodIndex = lodIndex;
|
||||
lod.ScreenSize = 1.0f;
|
||||
const int32 meshesCount = meshesCountPerLod[lodIndex];
|
||||
if (meshesCount <= 0 || meshesCount > MODEL_MAX_MESHES)
|
||||
@@ -922,6 +923,7 @@ Asset::LoadResult Model::load()
|
||||
{
|
||||
auto& lod = LODs[lodIndex];
|
||||
lod._model = this;
|
||||
lod._lodIndex = lodIndex;
|
||||
|
||||
// Screen Size
|
||||
stream->ReadFloat(&lod.ScreenSize);
|
||||
@@ -977,7 +979,13 @@ Asset::LoadResult Model::load()
|
||||
ModelSDFHeader data;
|
||||
sdfStream.ReadBytes(&data, sizeof(data));
|
||||
if (!SDF.Texture)
|
||||
SDF.Texture = GPUTexture::New();
|
||||
{
|
||||
String name;
|
||||
#if !BUILD_RELEASE
|
||||
name = GetPath() + TEXT(".SDF");
|
||||
#endif
|
||||
SDF.Texture = GPUDevice::Instance->CreateTexture(name);
|
||||
}
|
||||
if (SDF.Texture->Init(GPUTextureDescription::New3D(data.Width, data.Height, data.Depth, data.Format, GPUTextureFlags::ShaderResource, data.MipLevels)))
|
||||
return LoadResult::Failed;
|
||||
SDF.LocalToUVWMul = data.LocalToUVWMul;
|
||||
|
||||
@@ -64,6 +64,16 @@ bool RawDataAsset::Save(const StringView& path)
|
||||
|
||||
#endif
|
||||
|
||||
uint64 RawDataAsset::GetMemoryUsage() const
|
||||
{
|
||||
Locker.Lock();
|
||||
uint64 result = BinaryAsset::GetMemoryUsage();
|
||||
result += sizeof(RawDataAsset) - sizeof(BinaryAsset);
|
||||
result += Data.Count();
|
||||
Locker.Unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
Asset::LoadResult RawDataAsset::load()
|
||||
{
|
||||
auto chunk0 = GetChunk(0);
|
||||
|
||||
@@ -28,6 +28,10 @@ public:
|
||||
|
||||
#endif
|
||||
|
||||
public:
|
||||
// [BinaryAsset]
|
||||
uint64 GetMemoryUsage() const override;
|
||||
|
||||
protected:
|
||||
// [BinaryAsset]
|
||||
LoadResult load() override;
|
||||
|
||||
@@ -452,6 +452,22 @@ const String& BinaryAsset::GetPath() const
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64 BinaryAsset::GetMemoryUsage() const
|
||||
{
|
||||
Locker.Lock();
|
||||
uint64 result = Asset::GetMemoryUsage();
|
||||
result += sizeof(BinaryAsset) - sizeof(Asset);
|
||||
result += _dependantAssets.Capacity() * sizeof(BinaryAsset*);
|
||||
for (int32 i = 0; i < ASSET_FILE_DATA_CHUNKS; i++)
|
||||
{
|
||||
auto chunk = _header.Chunks[i];
|
||||
if (chunk != nullptr && chunk->IsLoaded())
|
||||
result += chunk->Size();
|
||||
}
|
||||
Locker.Unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper task used to initialize binary asset and upgrade it if need to in background.
|
||||
/// </summary>
|
||||
|
||||
@@ -41,7 +41,6 @@ public:
|
||||
FlaxStorage* Storage;
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
/// <summary>
|
||||
/// The asset metadata information. Stored in a Json format.
|
||||
/// </summary>
|
||||
@@ -51,14 +50,12 @@ public:
|
||||
/// Asset dependencies list used by the asset for tracking (eg. material functions used by material asset). The pair of asset ID and cached file edit time (for tracking modification).
|
||||
/// </summary>
|
||||
Array<Pair<Guid, DateTime>> Dependencies;
|
||||
|
||||
#endif
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets the asset serialized version.
|
||||
/// </summary>
|
||||
/// <returns>Version number.</returns>
|
||||
virtual uint32 GetSerializedVersion() const = 0;
|
||||
|
||||
/// <summary>
|
||||
@@ -84,14 +81,11 @@ public:
|
||||
|
||||
public:
|
||||
#if USE_EDITOR
|
||||
|
||||
#if COMPILE_WITH_ASSETS_IMPORTER
|
||||
|
||||
/// <summary>
|
||||
/// Reimports asset from the source file.
|
||||
/// </summary>
|
||||
API_FUNCTION() void Reimport() const;
|
||||
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
@@ -130,7 +124,6 @@ protected:
|
||||
virtual void OnDependencyModified(BinaryAsset* asset)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@@ -255,7 +248,6 @@ public:
|
||||
bool LoadChunks(AssetChunksFlag chunks);
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
/// <summary>
|
||||
/// Saves this asset to the storage container.
|
||||
/// </summary>
|
||||
@@ -281,7 +273,6 @@ public:
|
||||
/// <param name="silentMode">In silent mode don't reload opened storage container that is using target file.</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
static bool SaveToAsset(const StringView& path, AssetInitData& data, bool silentMode = false);
|
||||
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@@ -302,6 +293,7 @@ public:
|
||||
void OnDeleteObject() override;
|
||||
#endif
|
||||
const String& GetPath() const final override;
|
||||
uint64 GetMemoryUsage() const override;
|
||||
|
||||
protected:
|
||||
// [Asset]
|
||||
|
||||
@@ -34,6 +34,11 @@ TimeSpan Content::AssetsUnloadInterval = TimeSpan::FromSeconds(10);
|
||||
Delegate<Asset*> Content::AssetDisposing;
|
||||
Delegate<Asset*> Content::AssetReloading;
|
||||
|
||||
String AssetInfo::ToString() const
|
||||
{
|
||||
return String::Format(TEXT("ID: {0}, TypeName: {1}, Path: \'{2}\'"), ID, TypeName, Path);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// Assets
|
||||
|
||||
@@ -93,6 +93,17 @@ const String& JsonAssetBase::GetPath() const
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64 JsonAssetBase::GetMemoryUsage() const
|
||||
{
|
||||
Locker.Lock();
|
||||
uint64 result = Asset::GetMemoryUsage();
|
||||
result += sizeof(JsonAssetBase) - sizeof(Asset);
|
||||
if (Data)
|
||||
result += Document.GetAllocator().Capacity();
|
||||
Locker.Unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
void FindIds(ISerializable::DeserializeStream& node, Array<Guid>& output)
|
||||
@@ -248,6 +259,17 @@ JsonAsset::JsonAsset(const SpawnParams& params, const AssetInfo* info)
|
||||
{
|
||||
}
|
||||
|
||||
uint64 JsonAsset::GetMemoryUsage() const
|
||||
{
|
||||
Locker.Lock();
|
||||
uint64 result = JsonAssetBase::GetMemoryUsage();
|
||||
result += sizeof(JsonAsset) - sizeof(JsonAssetBase);
|
||||
if (Instance && InstanceType)
|
||||
result += InstanceType.GetType().Size;
|
||||
Locker.Unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
Asset::LoadResult JsonAsset::loadAsset()
|
||||
{
|
||||
const auto result = JsonAssetBase::loadAsset();
|
||||
|
||||
@@ -77,6 +77,7 @@ public:
|
||||
public:
|
||||
// [Asset]
|
||||
const String& GetPath() const override;
|
||||
uint64 GetMemoryUsage() const override;
|
||||
#if USE_EDITOR
|
||||
void GetReferences(Array<Guid, HeapAllocation>& output) const override;
|
||||
#endif
|
||||
@@ -122,6 +123,10 @@ public:
|
||||
return Instance && InstanceType.IsAssignableFrom(T::TypeInitializer) ? (T*)Instance : nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
// [JsonAssetBase]
|
||||
uint64 GetMemoryUsage() const override;
|
||||
|
||||
protected:
|
||||
// [JsonAssetBase]
|
||||
LoadResult loadAsset() override;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Threading/Task.h"
|
||||
#include "Engine/Core/Types/String.h"
|
||||
|
||||
class Asset;
|
||||
class LoadingThread;
|
||||
@@ -46,7 +45,6 @@ public:
|
||||
/// <summary>
|
||||
/// Gets a task type.
|
||||
/// </summary>
|
||||
/// <returns>The type.</returns>
|
||||
FORCE_INLINE Type GetType() const
|
||||
{
|
||||
return _type;
|
||||
@@ -68,13 +66,7 @@ protected:
|
||||
|
||||
public:
|
||||
// [Task]
|
||||
String ToString() const override
|
||||
{
|
||||
return String::Format(TEXT("Content Load Task {0} ({1})"),
|
||||
ToString(GetType()),
|
||||
::ToString(GetState())
|
||||
);
|
||||
}
|
||||
String ToString() const override;
|
||||
|
||||
protected:
|
||||
// [Task]
|
||||
|
||||
@@ -211,6 +211,11 @@ void ContentLoadingManagerService::Dispose()
|
||||
Tasks.CancelAll();
|
||||
}
|
||||
|
||||
String ContentLoadTask::ToString() const
|
||||
{
|
||||
return String::Format(TEXT("Content Load Task {0} ({1})"), ToString(GetType()), (int32)GetState());
|
||||
}
|
||||
|
||||
void ContentLoadTask::Enqueue()
|
||||
{
|
||||
Tasks.Add(this);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Core/Types/Guid.h"
|
||||
|
||||
/// <summary>
|
||||
/// Represents the reference to the scene asset. Stores the unique ID of the scene to reference. Can be used to load the selected scene.
|
||||
/// </summary>
|
||||
API_STRUCT(NoDefault) struct FLAXENGINE_API SceneReference
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_STRUCTURE(SceneReference);
|
||||
|
||||
/// <summary>
|
||||
/// The identifier of the scene asset (and the scene object).
|
||||
/// </summary>
|
||||
API_FIELD() Guid ID;
|
||||
};
|
||||
@@ -509,14 +509,14 @@ public:
|
||||
_deletedCount = _elementsCount = 0;
|
||||
if (capacity != 0 && (capacity & (capacity - 1)) != 0)
|
||||
{
|
||||
// Align capacity value to the next power of two (if it's not)
|
||||
capacity++;
|
||||
// Align capacity value to the next power of two (http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2)
|
||||
capacity--;
|
||||
capacity |= capacity >> 1;
|
||||
capacity |= capacity >> 2;
|
||||
capacity |= capacity >> 4;
|
||||
capacity |= capacity >> 8;
|
||||
capacity |= capacity >> 16;
|
||||
capacity = capacity + 1;
|
||||
capacity++;
|
||||
}
|
||||
if (capacity)
|
||||
{
|
||||
|
||||
@@ -380,14 +380,14 @@ public:
|
||||
_deletedCount = _elementsCount = 0;
|
||||
if (capacity != 0 && (capacity & (capacity - 1)) != 0)
|
||||
{
|
||||
// Align capacity value to the next power of two (if it's not)
|
||||
capacity++;
|
||||
// Align capacity value to the next power of two (http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2)
|
||||
capacity--;
|
||||
capacity |= capacity >> 1;
|
||||
capacity |= capacity >> 2;
|
||||
capacity |= capacity >> 4;
|
||||
capacity |= capacity >> 8;
|
||||
capacity |= capacity >> 16;
|
||||
capacity = capacity + 1;
|
||||
capacity++;
|
||||
}
|
||||
if (capacity)
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "Engine/Serialization/Serialization.h"
|
||||
#include "Engine/Content/Asset.h"
|
||||
#include "Engine/Content/AssetReference.h"
|
||||
#include "Engine/Content/SceneReference.h"
|
||||
|
||||
/// <summary>
|
||||
/// The game building rendering settings.
|
||||
@@ -50,6 +51,12 @@ public:
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(1000), EditorDisplay(\"Additional Data\")")
|
||||
Array<AssetReference<Asset>> AdditionalAssets;
|
||||
|
||||
/// <summary>
|
||||
/// The list of additional scenes to include into build (into root assets set).
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(1000), EditorDisplay(\"Additional Data\")")
|
||||
Array<SceneReference> AdditionalScenes;
|
||||
|
||||
/// <summary>
|
||||
/// The list of additional folders with assets to include into build (into root assets set). Paths relative to the project directory (or absolute).
|
||||
|
||||
@@ -557,6 +557,14 @@ public:
|
||||
return count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current capacity of delegate table (amount of function to store before resizing).
|
||||
/// </summary>
|
||||
int32 Capacity() const
|
||||
{
|
||||
return (int32)Platform::AtomicRead((intptr volatile*)&_size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether any function is binded.
|
||||
/// </summary>
|
||||
|
||||
@@ -105,14 +105,16 @@ public:
|
||||
|
||||
FORCE_INLINE int32 CalculateCapacityGrow(int32 capacity, int32 minCapacity) const
|
||||
{
|
||||
if (capacity == 0)
|
||||
if (capacity < minCapacity)
|
||||
capacity = minCapacity;
|
||||
if (capacity < 8)
|
||||
{
|
||||
capacity = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Round up to the next power of 2 and multiply by 2
|
||||
capacity++;
|
||||
// Round up to the next power of 2 and multiply by 2 (http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2)
|
||||
capacity--;
|
||||
capacity |= capacity >> 1;
|
||||
capacity |= capacity >> 2;
|
||||
capacity |= capacity >> 4;
|
||||
@@ -120,8 +122,6 @@ public:
|
||||
capacity |= capacity >> 16;
|
||||
capacity = (capacity + 1) * 2;
|
||||
}
|
||||
if (capacity < minCapacity)
|
||||
capacity = minCapacity;
|
||||
return capacity;
|
||||
}
|
||||
|
||||
|
||||
@@ -88,22 +88,14 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
// Compares two Guids for equality
|
||||
// @param left The first Guid to compare
|
||||
// @param right The second Guid to compare
|
||||
// @returns True if the Guids are equal, otherwise false
|
||||
friend bool operator==(const Guid& left, const Guid& right)
|
||||
bool operator==(const Guid& other) const
|
||||
{
|
||||
return ((left.A ^ right.A) | (left.B ^ right.B) | (left.C ^ right.C) | (left.D ^ right.D)) == 0;
|
||||
return ((A ^ other.A) | (B ^ other.B) | (C ^ other.C) | (D ^ other.D)) == 0;
|
||||
}
|
||||
|
||||
// Compares two Guids for inequality
|
||||
// @param left The first Guid to compare
|
||||
// @param right The second Guid to compare
|
||||
// @returns True if the GUIDs are not equal, otherwise false
|
||||
friend bool operator!=(const Guid& left, const Guid& right)
|
||||
bool operator!=(const Guid& other) const
|
||||
{
|
||||
return ((left.A ^ right.A) | (left.B ^ right.B) | (left.C ^ right.C) | (left.D ^ right.D)) != 0;
|
||||
return ((A ^ other.A) | (B ^ other.B) | (C ^ other.C) | (D ^ other.D)) != 0;
|
||||
}
|
||||
|
||||
// Provides access to the GUIDs components
|
||||
|
||||
@@ -81,14 +81,14 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend bool operator==(const Pair& a, const Pair& b)
|
||||
bool operator==(const Pair& other) const
|
||||
{
|
||||
return a.First == b.First && a.Second == b.Second;
|
||||
return First == other.First && Second == other.Second;
|
||||
}
|
||||
|
||||
friend bool operator!=(const Pair& a, const Pair& b)
|
||||
bool operator!=(const Pair& other) const
|
||||
{
|
||||
return a.First != b.First || a.Second != b.Second;
|
||||
return First != other.First || Second != other.Second;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Core/Enums.h"
|
||||
#include "Engine/Core/Types/BaseTypes.h"
|
||||
|
||||
/// <summary>
|
||||
/// Build game header flags.
|
||||
|
||||
@@ -4,16 +4,8 @@ using System;
|
||||
|
||||
namespace FlaxEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the reference to the scene asset. Stores the unique ID of the scene to reference. Can be used to load the selected scene.
|
||||
/// </summary>
|
||||
public struct SceneReference : IComparable, IComparable<Guid>, IComparable<SceneReference>
|
||||
partial struct SceneReference : IComparable, IComparable<Guid>, IComparable<SceneReference>
|
||||
{
|
||||
/// <summary>
|
||||
/// The identifier of the scene asset (and the scene object).
|
||||
/// </summary>
|
||||
public Guid ID;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SceneReference"/> class.
|
||||
/// </summary>
|
||||
|
||||
@@ -154,9 +154,9 @@ private:
|
||||
const Mesh* Geo;
|
||||
int32 Lightmap;
|
||||
|
||||
friend bool operator==(const DrawKey& lhs, const DrawKey& rhs)
|
||||
bool operator==(const DrawKey& other) const
|
||||
{
|
||||
return lhs.Mat == rhs.Mat && lhs.Geo == rhs.Geo && lhs.Lightmap == rhs.Lightmap;
|
||||
return Mat == other.Mat && Geo == other.Geo && Lightmap == other.Lightmap;
|
||||
}
|
||||
|
||||
friend uint32 GetHash(const DrawKey& key)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "DefaultGPUTasksExecutor.h"
|
||||
#include "GPUTasksContext.h"
|
||||
#include "GPUTask.h"
|
||||
#include "GPUTasksManager.h"
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
|
||||
DefaultGPUTasksExecutor::DefaultGPUTasksExecutor()
|
||||
@@ -30,7 +31,7 @@ void DefaultGPUTasksExecutor::FrameEnd()
|
||||
|
||||
// Default implementation performs async operations on end of the frame which is synchronized with a rendering thread
|
||||
GPUTask* buffer[32];
|
||||
const int32 count = GPUDevice::Instance->TasksManager.RequestWork(buffer, 32);
|
||||
const int32 count = GPUDevice::Instance->GetTasksManager()->RequestWork(buffer, 32);
|
||||
for (int32 i = 0; i < count; i++)
|
||||
{
|
||||
_context->Run(buffer[i]);
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include "Engine/Threading/Task.h"
|
||||
#include "Engine/Platform/Platform.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "GPUTasksContext.h"
|
||||
|
||||
class GPUResource;
|
||||
@@ -89,32 +88,7 @@ public:
|
||||
/// Executes this task.
|
||||
/// </summary>
|
||||
/// <param name="context">The context.</param>
|
||||
void Execute(GPUTasksContext* context)
|
||||
{
|
||||
// Begin
|
||||
ASSERT(IsQueued() && _context == nullptr);
|
||||
_state = TaskState::Running;
|
||||
|
||||
// Perform an operation
|
||||
const auto result = run(context);
|
||||
|
||||
// Process result
|
||||
if (IsCancelRequested())
|
||||
{
|
||||
_state = TaskState::Canceled;
|
||||
}
|
||||
else if (result != Result::Ok)
|
||||
{
|
||||
LOG(Warning, "\'{0}\' failed with result: {1}", ToString(), ToString(result));
|
||||
OnFail();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Save task completion point (for synchronization)
|
||||
_syncPoint = context->GetCurrentSyncPoint();
|
||||
_context = context;
|
||||
}
|
||||
}
|
||||
void Execute(GPUTasksContext* context);
|
||||
|
||||
/// <summary>
|
||||
/// Action fired when asynchronous operation has been synchronized with a GPU
|
||||
@@ -154,10 +128,7 @@ protected:
|
||||
|
||||
public:
|
||||
// [Task]
|
||||
String ToString() const override
|
||||
{
|
||||
return String::Format(TEXT("GPU Async Task {0} ({1})"), ToString(GetType()), ::ToString(GetState()));
|
||||
}
|
||||
String ToString() const override;
|
||||
|
||||
protected:
|
||||
// [Task]
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "GPUTasksContext.h"
|
||||
#include "GPUTask.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
#include "Engine/Threading/Threading.h"
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "GPUTasksExecutor.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Graphics/GPUDevice.h"
|
||||
|
||||
GPUTasksExecutor::~GPUTasksExecutor()
|
||||
|
||||
@@ -37,7 +37,6 @@ public:
|
||||
/// <summary>
|
||||
/// Gets the context list.
|
||||
/// </summary>
|
||||
/// <returns>GPU contexts</returns>
|
||||
FORCE_INLINE const Array<GPUTasksContext*>* GetContextList() const
|
||||
{
|
||||
return &_contextList;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user