Merge remote-tracking branch 'origin/master' into 1.10
This commit is contained in:
@@ -490,6 +490,60 @@ namespace FlaxEditor.Modules
|
||||
return;
|
||||
}
|
||||
|
||||
var projects = Editor.ContentDatabase.Projects;
|
||||
var contentPaths = new List<string>();
|
||||
var sourcePaths = new List<string>();
|
||||
foreach (var project in projects)
|
||||
{
|
||||
if (project.Content != null)
|
||||
contentPaths.Add(project.Content.Path);
|
||||
if (project.Source != null)
|
||||
sourcePaths.Add(project.Source.Path);
|
||||
}
|
||||
|
||||
// Check if moving from content to source folder. Item may lose reference in Asset Database. Warn user.
|
||||
foreach (var contentPath in contentPaths)
|
||||
{
|
||||
if (item.Path.Contains(contentPath, StringComparison.Ordinal))
|
||||
{
|
||||
bool isFound = false;
|
||||
foreach (var sourcePath in sourcePaths)
|
||||
{
|
||||
if (newParent.Path.Contains(sourcePath, StringComparison.Ordinal))
|
||||
{
|
||||
isFound = true;
|
||||
var result = MessageBox.Show(Editor.Windows.MainWindow, "Moving item from \"Content\" to \"Source\" folder may lose asset database reference.\nDo you want to continue?", "Moving item", MessageBoxButtons.OKCancel);
|
||||
if (result == DialogResult.Cancel)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isFound)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Check if moving from source to content folder. Item may lose reference in Asset Database. Warn user.
|
||||
foreach (var sourcePath in sourcePaths)
|
||||
{
|
||||
if (item.Path.Contains(sourcePath, StringComparison.Ordinal))
|
||||
{
|
||||
bool isFound = false;
|
||||
foreach (var contentPath in contentPaths)
|
||||
{
|
||||
if (newParent.Path.Contains(contentPath, StringComparison.Ordinal))
|
||||
{
|
||||
isFound = true;
|
||||
var result = MessageBox.Show(Editor.Windows.MainWindow, "Moving item from \"Source\" to \"Content\" folder may lose asset database reference.\nDo you want to continue?", "Moving item", MessageBoxButtons.OKCancel);
|
||||
if (result == DialogResult.Cancel)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isFound)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Perform renaming
|
||||
{
|
||||
string oldPath = item.Path;
|
||||
|
||||
@@ -555,10 +555,20 @@ namespace FlaxEditor.Modules
|
||||
/// </summary>
|
||||
public void CreateParentForSelectedActors()
|
||||
{
|
||||
Actor actor = new EmptyActor();
|
||||
Editor.SceneEditing.Spawn(actor, null, false);
|
||||
List<SceneGraphNode> selection = Editor.SceneEditing.Selection;
|
||||
var actors = selection.Where(x => x is ActorNode).Select(x => ((ActorNode)x).Actor);
|
||||
var actorsCount = actors.Count();
|
||||
if (actorsCount == 0)
|
||||
return;
|
||||
Vector3 center = Vector3.Zero;
|
||||
foreach (var actor in actors)
|
||||
center += actor.Position;
|
||||
center /= actorsCount;
|
||||
Actor parent = new EmptyActor
|
||||
{
|
||||
Position = center,
|
||||
};
|
||||
Editor.SceneEditing.Spawn(parent, null, false);
|
||||
using (new UndoMultiBlock(Undo, actors, "Reparent actors"))
|
||||
{
|
||||
for (int i = 0; i < selection.Count; i++)
|
||||
@@ -574,15 +584,15 @@ namespace FlaxEditor.Modules
|
||||
|
||||
// Put created node as child of the Parent Node of node
|
||||
int parentOrder = node.Actor.OrderInParent;
|
||||
actor.Parent = node.Actor.Parent;
|
||||
actor.OrderInParent = parentOrder;
|
||||
parent.SetParent(node.Actor.Parent, true, true);
|
||||
parent.OrderInParent = parentOrder;
|
||||
}
|
||||
node.Actor.Parent = actor;
|
||||
node.Actor.SetParent(parent, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
Editor.SceneEditing.Select(actor);
|
||||
Editor.Scene.GetActorNode(actor).TreeNode.StartRenaming(Editor.Windows.SceneWin, Editor.Windows.SceneWin.SceneTreePanel);
|
||||
Editor.SceneEditing.Select(parent);
|
||||
Editor.Scene.GetActorNode(parent).TreeNode.StartRenaming(Editor.Windows.SceneWin, Editor.Windows.SceneWin.SceneTreePanel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using FlaxEditor.GUI.Docking;
|
||||
using FlaxEditor.States;
|
||||
using FlaxEditor.Windows;
|
||||
using FlaxEngine;
|
||||
@@ -20,6 +21,7 @@ namespace FlaxEditor.Modules
|
||||
private bool _updateOrFixedUpdateWasCalled;
|
||||
private long _breakpointHangFlag;
|
||||
private EditorWindow _enterPlayFocusedWindow;
|
||||
private DockWindow _previousWindow;
|
||||
private Guid[] _scenesToReload;
|
||||
|
||||
internal SimulationModule(Editor editor)
|
||||
@@ -272,23 +274,43 @@ namespace FlaxEditor.Modules
|
||||
// Show Game widow if hidden
|
||||
if (gameWin != null)
|
||||
{
|
||||
if (gameWin.FocusOnPlay)
|
||||
switch (gameWin.FocusOnPlayOption)
|
||||
{
|
||||
case Options.InterfaceOptions.PlayModeFocus.None: break;
|
||||
|
||||
case Options.InterfaceOptions.PlayModeFocus.GameWindow:
|
||||
gameWin.FocusGameViewport();
|
||||
break;
|
||||
|
||||
case Options.InterfaceOptions.PlayModeFocus.GameWindowThenRestore:
|
||||
_previousWindow = gameWin.ParentDockPanel.SelectedTab;
|
||||
gameWin.FocusGameViewport();
|
||||
break;
|
||||
}
|
||||
|
||||
gameWin.SetWindowMode(Editor.Options.Options.Interface.DefaultGameWindowMode);
|
||||
}
|
||||
|
||||
|
||||
Editor.Log("[PlayMode] Enter");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnPlayEnd()
|
||||
{
|
||||
// Restore focused window before play mode
|
||||
if (_enterPlayFocusedWindow != null)
|
||||
var gameWin = Editor.Windows.GameWin;
|
||||
|
||||
switch (gameWin.FocusOnPlayOption)
|
||||
{
|
||||
_enterPlayFocusedWindow.FocusOrShow();
|
||||
_enterPlayFocusedWindow = null;
|
||||
case Options.InterfaceOptions.PlayModeFocus.None: break;
|
||||
case Options.InterfaceOptions.PlayModeFocus.GameWindow: break;
|
||||
case Options.InterfaceOptions.PlayModeFocus.GameWindowThenRestore:
|
||||
if (_previousWindow != null && !_previousWindow.IsDisposing)
|
||||
{
|
||||
if (!Editor.Windows.GameWin.ParentDockPanel.ContainsTab(_previousWindow))
|
||||
break;
|
||||
_previousWindow.Focus();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Editor.UI.UncheckPauseButton();
|
||||
|
||||
@@ -556,7 +556,7 @@ namespace FlaxEditor.Modules
|
||||
cm.AddSeparator();
|
||||
_menuEditSelectAll = cm.AddButton("Select all", inputOptions.SelectAll, Editor.SceneEditing.SelectAllScenes);
|
||||
_menuEditDeselectAll = cm.AddButton("Deselect all", inputOptions.DeselectAll, Editor.SceneEditing.DeselectAllScenes);
|
||||
_menuCreateParentForSelectedActors = cm.AddButton("Create parent for selected actors", Editor.SceneEditing.CreateParentForSelectedActors);
|
||||
_menuCreateParentForSelectedActors = cm.AddButton("Parent to new Actor", inputOptions.GroupSelectedActors, Editor.SceneEditing.CreateParentForSelectedActors);
|
||||
_menuEditFind = cm.AddButton("Find", inputOptions.Search, Editor.Windows.SceneWin.Search);
|
||||
cm.AddSeparator();
|
||||
cm.AddButton("Game Settings", () =>
|
||||
|
||||
@@ -160,6 +160,10 @@ namespace FlaxEditor.Options
|
||||
[EditorDisplay("Scene"), EditorOrder(573)]
|
||||
public InputBinding PilotActor = new InputBinding(KeyboardKeys.None);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Ctrl+G")]
|
||||
[EditorDisplay("Scene"), EditorOrder(574)]
|
||||
public InputBinding GroupSelectedActors = new InputBinding(KeyboardKeys.G, KeyboardKeys.Control);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Tools
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using FlaxEditor.GUI.Docking;
|
||||
using FlaxEditor.Utilities;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
|
||||
@@ -139,6 +139,27 @@ namespace FlaxEditor.Options
|
||||
AutoUnit,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Options focus Game Window behaviour when play mode is entered.
|
||||
/// </summary>
|
||||
public enum PlayModeFocus
|
||||
{
|
||||
/// <summary>
|
||||
/// Don't change focus.
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// Focus the Game Window.
|
||||
/// </summary>
|
||||
GameWindow,
|
||||
|
||||
/// <summary>
|
||||
/// Focus the Game Window. On play mode end restore focus to the previous window.
|
||||
/// </summary>
|
||||
GameWindowThenRestore,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the 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.
|
||||
/// </summary>
|
||||
@@ -339,6 +360,18 @@ namespace FlaxEditor.Options
|
||||
[EditorDisplay("Output Log", "Text Shadow Offset"), EditorOrder(445), Tooltip("The output log text shadow offset. Set to 0 to disable this feature.")]
|
||||
public Float2 OutputLogTextShadowOffset { get; set; } = new Float2(1);
|
||||
|
||||
// [Deprecated in v1.10]
|
||||
[Serialize, Obsolete, NoUndo]
|
||||
private bool FocusGameWinOnPlay
|
||||
{
|
||||
get => throw new Exception();
|
||||
set
|
||||
{
|
||||
// Upgrade value
|
||||
FocusOnPlayMode = value ? PlayModeFocus.GameWindow : PlayModeFocus.None;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether auto-focus output log window on code compilation error.
|
||||
/// </summary>
|
||||
@@ -361,11 +394,11 @@ namespace FlaxEditor.Options
|
||||
public bool OutputLogScrollToBottom { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether auto-focus game window on play mode start.
|
||||
/// Gets or sets a value indicating what panel should be focused when play mode start.
|
||||
/// </summary>
|
||||
[DefaultValue(true)]
|
||||
[EditorDisplay("Play In-Editor", "Focus Game Window On Play"), EditorOrder(500), Tooltip("Determines whether auto-focus game window on play mode start.")]
|
||||
public bool FocusGameWinOnPlay { get; set; } = true;
|
||||
[DefaultValue(PlayModeFocus.GameWindow)]
|
||||
[EditorDisplay("Play In-Editor", "Focus On Play"), EditorOrder(500), Tooltip("Set what panel to focus on play mode start.")]
|
||||
public PlayModeFocus FocusOnPlayMode { get; set; } = PlayModeFocus.GameWindow;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating what action should be taken upon pressing the play button.
|
||||
|
||||
@@ -109,29 +109,42 @@ namespace FlaxEditor.States
|
||||
|
||||
private void TryEnter()
|
||||
{
|
||||
// Remove redundant scene changes
|
||||
for (int i = 0; i < _scenesToUnload.Count; i++)
|
||||
// Reload existing scene if only 1 scene exists
|
||||
bool reloadExistingScene = false;
|
||||
if (Level.Scenes.Length == 1 && _scenesToLoad.Count == 1)
|
||||
{
|
||||
var id = _scenesToUnload[i].ID;
|
||||
for (int j = 0; j < _scenesToLoad.Count; j++)
|
||||
if (Level.FindScene(_scenesToLoad[0]))
|
||||
{
|
||||
if (_scenesToLoad[j] == id)
|
||||
{
|
||||
_scenesToLoad.RemoveAt(j--);
|
||||
_scenesToUnload.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
reloadExistingScene = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Skip already loaded scenes
|
||||
for (int j = 0; j < _scenesToLoad.Count; j++)
|
||||
if (!reloadExistingScene)
|
||||
{
|
||||
if (Level.FindScene(_scenesToLoad[j]))
|
||||
// Remove redundant scene changes
|
||||
for (int i = 0; i < _scenesToUnload.Count; i++)
|
||||
{
|
||||
_scenesToLoad.RemoveAt(j--);
|
||||
if (_scenesToLoad.Count == 0)
|
||||
break;
|
||||
var id = _scenesToUnload[i].ID;
|
||||
for (int j = 0; j < _scenesToLoad.Count; j++)
|
||||
{
|
||||
if (_scenesToLoad[j] == id)
|
||||
{
|
||||
_scenesToLoad.RemoveAt(j--);
|
||||
_scenesToUnload.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Skip already loaded scenes
|
||||
for (int j = 0; j < _scenesToLoad.Count; j++)
|
||||
{
|
||||
if (Level.FindScene(_scenesToLoad[j]))
|
||||
{
|
||||
_scenesToLoad.RemoveAt(j--);
|
||||
if (_scenesToLoad.Count == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1432,6 +1432,7 @@ namespace FlaxEditor.Utilities
|
||||
inputActions.Add(options => options.SelectAll, Editor.Instance.SceneEditing.SelectAllScenes);
|
||||
inputActions.Add(options => options.DeselectAll, Editor.Instance.SceneEditing.DeselectAllScenes);
|
||||
inputActions.Add(options => options.Delete, Editor.Instance.SceneEditing.Delete);
|
||||
inputActions.Add(options => options.GroupSelectedActors, Editor.Instance.SceneEditing.CreateParentForSelectedActors);
|
||||
inputActions.Add(options => options.Search, () => Editor.Instance.Windows.SceneWin.Search());
|
||||
inputActions.Add(options => options.MoveActorToViewport, Editor.Instance.UI.MoveActorToViewport);
|
||||
inputActions.Add(options => options.AlignActorWithViewport, Editor.Instance.UI.AlignActorWithViewport);
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FlaxEditor.Content;
|
||||
@@ -137,6 +139,7 @@ namespace FlaxEditor.Windows
|
||||
}
|
||||
}
|
||||
|
||||
private string _cacheFolder;
|
||||
private Guid _assetId;
|
||||
private Surface _surface;
|
||||
private Label _loadingLabel;
|
||||
@@ -161,6 +164,9 @@ namespace FlaxEditor.Windows
|
||||
{
|
||||
Title = assetItem.ShortName + " References";
|
||||
|
||||
_cacheFolder = Path.Combine(Globals.ProjectCacheFolder, "References");
|
||||
if (!Directory.Exists(_cacheFolder))
|
||||
Directory.CreateDirectory(_cacheFolder);
|
||||
_assetId = assetItem.ID;
|
||||
_surface = new Surface(this)
|
||||
{
|
||||
@@ -189,7 +195,7 @@ namespace FlaxEditor.Windows
|
||||
return node;
|
||||
}
|
||||
|
||||
private void SearchRefs(Guid assetId)
|
||||
private unsafe void SearchRefs(Guid assetId)
|
||||
{
|
||||
// Skip assets that never contain references to prevent loading them
|
||||
if (FlaxEngine.Content.GetAssetInfo(assetId, out var assetInfo) &&
|
||||
@@ -202,8 +208,24 @@ namespace FlaxEditor.Windows
|
||||
if (_refs.ContainsKey(assetId))
|
||||
return;
|
||||
|
||||
// Try to load cached references form previous run
|
||||
var cachePath = Path.Combine(_cacheFolder, $"{FlaxEngine.Json.JsonSerializer.GetStringID(assetId)}.1.cache");
|
||||
var hasInfo = FlaxEngine.Content.GetAssetInfo(assetId, out var info);
|
||||
if (hasInfo && File.Exists(cachePath) && File.GetLastWriteTime(cachePath) > File.GetLastWriteTime(info.Path))
|
||||
{
|
||||
byte[] rawData = File.ReadAllBytes(cachePath);
|
||||
Guid[] loadedRefs = new Guid[rawData.Length / sizeof(Guid)];
|
||||
if (rawData.Length != 0)
|
||||
{
|
||||
fixed (byte* rawDataPtr = rawData)
|
||||
fixed (Guid* loadedRefsPtr = loadedRefs)
|
||||
Unsafe.CopyBlock(loadedRefsPtr, rawDataPtr, (uint)rawData.Length);
|
||||
}
|
||||
_refs[assetId] = loadedRefs;
|
||||
return;
|
||||
}
|
||||
|
||||
// Load asset (with cancel support)
|
||||
//Debug.Log("Searching refs for " + assetInfo.Path);
|
||||
var obj = FlaxEngine.Object.TryFind<FlaxEngine.Object>(ref assetId);
|
||||
if (obj is Scene scene)
|
||||
{
|
||||
@@ -226,7 +248,21 @@ namespace FlaxEditor.Windows
|
||||
return;
|
||||
|
||||
// Get direct references
|
||||
_refs[assetId] = asset.GetReferences();
|
||||
var references = asset.GetReferences();
|
||||
_refs[assetId] = references;
|
||||
|
||||
// Save reference to the cache
|
||||
if (hasInfo)
|
||||
{
|
||||
byte[] rawData = new byte[references.Length * sizeof(Guid)];
|
||||
if (rawData.Length != 0)
|
||||
{
|
||||
fixed (byte* rawDataPtr = rawData)
|
||||
fixed (Guid* referencesPtr = references)
|
||||
Unsafe.CopyBlock(rawDataPtr, referencesPtr, (uint)rawData.Length);
|
||||
}
|
||||
File.WriteAllBytes(cachePath, rawData);
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildGraph(AssetNode node, int level, bool reverse)
|
||||
|
||||
@@ -39,6 +39,28 @@ namespace FlaxEditor.Windows
|
||||
private bool _useAspect = false;
|
||||
private bool _freeAspect = true;
|
||||
|
||||
private List<PlayModeFocusOptions> _focusOptions = new List<PlayModeFocusOptions>()
|
||||
{
|
||||
new PlayModeFocusOptions
|
||||
{
|
||||
Name = "None",
|
||||
Tooltip = "Don't change focus.",
|
||||
FocusOption = InterfaceOptions.PlayModeFocus.None,
|
||||
},
|
||||
new PlayModeFocusOptions
|
||||
{
|
||||
Name = "Game Window",
|
||||
Tooltip = "Focus the Game Window.",
|
||||
FocusOption = InterfaceOptions.PlayModeFocus.GameWindow,
|
||||
},
|
||||
new PlayModeFocusOptions
|
||||
{
|
||||
Name = "Game Window Then Restore",
|
||||
Tooltip = "Focus the Game Window. On play mode end restore focus to the previous window.",
|
||||
FocusOption = InterfaceOptions.PlayModeFocus.GameWindowThenRestore,
|
||||
},
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets the viewport.
|
||||
/// </summary>
|
||||
@@ -162,9 +184,9 @@ namespace FlaxEditor.Windows
|
||||
public bool CenterMouseOnFocus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether auto-focus game window on play mode start.
|
||||
/// Gets or sets a value indicating what panel should be focused when play mode start.
|
||||
/// </summary>
|
||||
public bool FocusOnPlay { get; set; }
|
||||
public InterfaceOptions.PlayModeFocus FocusOnPlayOption { get; set; }
|
||||
|
||||
private enum ViewportScaleType
|
||||
{
|
||||
@@ -195,6 +217,29 @@ namespace FlaxEditor.Windows
|
||||
public bool Active;
|
||||
}
|
||||
|
||||
private class PlayModeFocusOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// The name.
|
||||
/// </summary>
|
||||
public string Name;
|
||||
|
||||
/// <summary>
|
||||
/// The tooltip.
|
||||
/// </summary>
|
||||
public string Tooltip;
|
||||
|
||||
/// <summary>
|
||||
/// The type of focus.
|
||||
/// </summary>
|
||||
public InterfaceOptions.PlayModeFocus FocusOption;
|
||||
|
||||
/// <summary>
|
||||
/// If the option is active.
|
||||
/// </summary>
|
||||
public bool Active;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Root control for game UI preview in Editor. Supports basic UI editing via <see cref="UIEditorRoot"/>.
|
||||
/// </summary>
|
||||
@@ -432,7 +477,7 @@ namespace FlaxEditor.Windows
|
||||
private void OnOptionsChanged(EditorOptions options)
|
||||
{
|
||||
CenterMouseOnFocus = options.Interface.CenterMouseOnGameWinFocus;
|
||||
FocusOnPlay = options.Interface.FocusGameWinOnPlay;
|
||||
FocusOnPlayOption = options.Interface.FocusOnPlayMode;
|
||||
}
|
||||
|
||||
private void PlayingStateOnSceneDuplicating()
|
||||
@@ -497,10 +542,15 @@ namespace FlaxEditor.Windows
|
||||
|
||||
// Focus on play
|
||||
{
|
||||
var focus = menu.AddButton("Start Focused");
|
||||
focus.CloseMenuOnClick = false;
|
||||
var checkbox = new CheckBox(140, 2, FocusOnPlay) { Parent = focus };
|
||||
checkbox.StateChanged += state => FocusOnPlay = state.Checked;
|
||||
var pfMenu = menu.AddChildMenu("Focus On Play Override").ContextMenu;
|
||||
|
||||
GenerateFocusOptionsContextMenu(pfMenu);
|
||||
|
||||
pfMenu.AddSeparator();
|
||||
|
||||
var button = pfMenu.AddButton("Remove override");
|
||||
button.TooltipText = "Reset the override to the value set in the editor options.";
|
||||
button.Clicked += () => FocusOnPlayOption = Editor.Instance.Options.Options.Interface.FocusOnPlayMode;
|
||||
}
|
||||
|
||||
menu.AddSeparator();
|
||||
@@ -602,6 +652,40 @@ namespace FlaxEditor.Windows
|
||||
menu.AddSeparator();
|
||||
}
|
||||
|
||||
private void GenerateFocusOptionsContextMenu(ContextMenu pfMenu)
|
||||
{
|
||||
foreach (PlayModeFocusOptions f in _focusOptions)
|
||||
{
|
||||
f.Active = f.FocusOption == FocusOnPlayOption;
|
||||
|
||||
var button = pfMenu.AddButton(f.Name);
|
||||
button.CloseMenuOnClick = false;
|
||||
button.Tag = f;
|
||||
button.TooltipText = f.Tooltip;
|
||||
button.Icon = f.Active ? Style.Current.CheckBoxTick : SpriteHandle.Invalid;
|
||||
button.Clicked += () =>
|
||||
{
|
||||
foreach (var child in pfMenu.Items)
|
||||
{
|
||||
if (child is ContextMenuButton cmb && cmb.Tag is PlayModeFocusOptions p)
|
||||
{
|
||||
if (cmb == button)
|
||||
{
|
||||
p.Active = true;
|
||||
button.Icon = Style.Current.CheckBoxTick;
|
||||
FocusOnPlayOption = p.FocusOption;
|
||||
}
|
||||
else if (p.Active)
|
||||
{
|
||||
cmb.Icon = SpriteHandle.Invalid;
|
||||
p.Active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateViewportSizingContextMenu(ContextMenu vsMenu)
|
||||
{
|
||||
// Add default viewport sizing options
|
||||
|
||||
@@ -926,8 +926,10 @@ namespace FlaxEditor.Windows
|
||||
// Update the output
|
||||
var cachedScrollValue = _vScroll.Value;
|
||||
var cachedSelection = _output.SelectionRange;
|
||||
var isBottomScroll = _vScroll.Value >= _vScroll.Maximum - 20.0f || wasEmpty;
|
||||
var cachedOutputTargetViewOffset = _output.TargetViewOffset;
|
||||
var isBottomScroll = _vScroll.Value >= _vScroll.Maximum - (_scrollSize*2) || wasEmpty;
|
||||
_output.Text = _textBuffer.ToString();
|
||||
_output.TargetViewOffset = cachedOutputTargetViewOffset;
|
||||
_textBufferCount = _entries.Count;
|
||||
if (!_vScroll.IsThumbClicked)
|
||||
_vScroll.TargetValue = isBottomScroll ? _vScroll.Maximum : cachedScrollValue;
|
||||
|
||||
@@ -133,7 +133,7 @@ namespace FlaxEditor.Windows
|
||||
|
||||
contextMenu.AddSeparator();
|
||||
|
||||
b = contextMenu.AddButton("Create parent for selected actors", Editor.SceneEditing.CreateParentForSelectedActors);
|
||||
b = contextMenu.AddButton("Parent to new Actor", inputOptions.GroupSelectedActors, Editor.SceneEditing.CreateParentForSelectedActors);
|
||||
b.Enabled = canEditScene && hasSthSelected;
|
||||
|
||||
b = contextMenu.AddButton("Create Prefab", Editor.Prefabs.CreatePrefab);
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "Engine/Serialization/MemoryReadStream.h"
|
||||
#if USE_EDITOR
|
||||
#include "Engine/Serialization/MemoryWriteStream.h"
|
||||
#include "Engine/Serialization/JsonWriters.h"
|
||||
#include "Engine/Content/JsonAsset.h"
|
||||
#include "Engine/Level/Level.h"
|
||||
#endif
|
||||
|
||||
@@ -486,6 +488,34 @@ bool Animation::Save(const StringView& path)
|
||||
return false;
|
||||
}
|
||||
|
||||
void Animation::GetReferences(Array<Guid>& assets, Array<String>& files) const
|
||||
{
|
||||
BinaryAsset::GetReferences(assets, files);
|
||||
|
||||
for (const auto& e : Events)
|
||||
{
|
||||
for (const auto& k : e.Second.GetKeyframes())
|
||||
{
|
||||
if (k.Value.Instance)
|
||||
{
|
||||
// Collect refs from Anim Event data (as Json)
|
||||
rapidjson_flax::StringBuffer buffer;
|
||||
CompactJsonWriter writer(buffer);
|
||||
writer.StartObject();
|
||||
k.Value.Instance->Serialize(writer, nullptr);
|
||||
writer.EndObject();
|
||||
JsonAssetBase::GetReferences(StringAnsiView((const char*)buffer.GetString(), (int32)buffer.GetSize()), assets);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add nested animations
|
||||
for (const auto& e : NestedAnims)
|
||||
{
|
||||
assets.Add(e.Second.Anim.GetID());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
uint64 Animation::GetMemoryUsage() const
|
||||
|
||||
@@ -153,6 +153,9 @@ public:
|
||||
|
||||
public:
|
||||
// [BinaryAsset]
|
||||
#if USE_EDITOR
|
||||
void GetReferences(Array<Guid>& assets, Array<String>& files) const override;
|
||||
#endif
|
||||
uint64 GetMemoryUsage() const override;
|
||||
void OnScriptingDispose() override;
|
||||
|
||||
|
||||
@@ -17,15 +17,15 @@ API_CLASS(InBuild) class Array
|
||||
{
|
||||
friend Array;
|
||||
public:
|
||||
typedef T ItemType;
|
||||
typedef typename AllocationType::template Data<T> AllocationData;
|
||||
using ItemType = T;
|
||||
using AllocationData = typename AllocationType::template Data<T>;
|
||||
|
||||
private:
|
||||
int32 _count;
|
||||
int32 _capacity;
|
||||
AllocationData _allocation;
|
||||
|
||||
FORCE_INLINE static void MoveToEmpty(AllocationData& to, AllocationData& from, int32 fromCount, int32 fromCapacity)
|
||||
FORCE_INLINE static void MoveToEmpty(AllocationData& to, AllocationData& from, const int32 fromCount, const int32 fromCapacity)
|
||||
{
|
||||
if IF_CONSTEXPR (AllocationType::HasSwap)
|
||||
to.Swap(from);
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
/// Initializes a new instance of the <see cref="Array"/> class.
|
||||
/// </summary>
|
||||
/// <param name="capacity">The initial capacity.</param>
|
||||
Array(int32 capacity)
|
||||
explicit Array(const int32 capacity)
|
||||
: _count(0)
|
||||
, _capacity(capacity)
|
||||
{
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
/// <param name="initList">The initial values defined in the array.</param>
|
||||
Array(std::initializer_list<T> initList)
|
||||
{
|
||||
_count = _capacity = (int32)initList.size();
|
||||
_count = _capacity = static_cast<int32>(initList.size());
|
||||
if (_count > 0)
|
||||
{
|
||||
_allocation.Allocate(_count);
|
||||
@@ -79,7 +79,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="data">The initial data.</param>
|
||||
/// <param name="length">The amount of items.</param>
|
||||
Array(const T* data, int32 length)
|
||||
Array(const T* data, const int32 length)
|
||||
{
|
||||
ASSERT(length >= 0);
|
||||
_count = _capacity = length;
|
||||
@@ -160,8 +160,8 @@ public:
|
||||
Clear();
|
||||
if (initList.size() > 0)
|
||||
{
|
||||
EnsureCapacity((int32)initList.size());
|
||||
_count = (int32)initList.size();
|
||||
EnsureCapacity(static_cast<int32>(initList.size()));
|
||||
_count = static_cast<int32>(initList.size());
|
||||
Memory::ConstructItems(_allocation.Get(), initList.begin(), _count);
|
||||
}
|
||||
return *this;
|
||||
@@ -255,7 +255,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="index">The index.</param>
|
||||
/// <returns><c>true</c> if is valid a index; otherwise, <c>false</c>.</returns>
|
||||
bool IsValidIndex(int32 index) const
|
||||
bool IsValidIndex(const int32 index) const
|
||||
{
|
||||
return index < _count && index >= 0;
|
||||
}
|
||||
@@ -280,7 +280,7 @@ public:
|
||||
/// Gets item at the given index.
|
||||
/// </summary>
|
||||
/// <returns>The reference to the item.</returns>
|
||||
FORCE_INLINE T& At(int32 index)
|
||||
FORCE_INLINE T& At(const int32 index)
|
||||
{
|
||||
ASSERT(index >= 0 && index < _count);
|
||||
return _allocation.Get()[index];
|
||||
@@ -290,7 +290,7 @@ public:
|
||||
/// Gets item at the given index.
|
||||
/// </summary>
|
||||
/// <returns>The reference to the item.</returns>
|
||||
FORCE_INLINE const T& At(int32 index) const
|
||||
FORCE_INLINE const T& At(const int32 index) const
|
||||
{
|
||||
ASSERT(index >= 0 && index < _count);
|
||||
return _allocation.Get()[index];
|
||||
@@ -300,7 +300,7 @@ public:
|
||||
/// Gets or sets the item at the given index.
|
||||
/// </summary>
|
||||
/// <returns>The reference to the item.</returns>
|
||||
FORCE_INLINE T& operator[](int32 index)
|
||||
FORCE_INLINE T& operator[](const int32 index)
|
||||
{
|
||||
ASSERT(index >= 0 && index < _count);
|
||||
return _allocation.Get()[index];
|
||||
@@ -310,7 +310,7 @@ public:
|
||||
/// Gets the item at the given index.
|
||||
/// </summary>
|
||||
/// <returns>The reference to the item.</returns>
|
||||
FORCE_INLINE const T& operator[](int32 index) const
|
||||
FORCE_INLINE const T& operator[](const int32 index) const
|
||||
{
|
||||
ASSERT(index >= 0 && index < _count);
|
||||
return _allocation.Get()[index];
|
||||
@@ -406,7 +406,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="capacity">The new capacity.</param>
|
||||
/// <param name="preserveContents">True if preserve collection data when changing its size, otherwise collection after resize will be empty.</param>
|
||||
void SetCapacity(const int32 capacity, bool preserveContents = true)
|
||||
void SetCapacity(const int32 capacity, const bool preserveContents = true)
|
||||
{
|
||||
if (capacity == _capacity)
|
||||
return;
|
||||
@@ -422,7 +422,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="size">The new collection size.</param>
|
||||
/// <param name="preserveContents">True if preserve collection data when changing its size, otherwise collection after resize might not contain the previous data.</param>
|
||||
void Resize(int32 size, bool preserveContents = true)
|
||||
void Resize(const int32 size, const bool preserveContents = true)
|
||||
{
|
||||
if (_count > size)
|
||||
{
|
||||
@@ -441,7 +441,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="minCapacity">The minimum capacity.</param>
|
||||
/// <param name="preserveContents">True if preserve collection data when changing its size, otherwise collection after resize will be empty.</param>
|
||||
void EnsureCapacity(int32 minCapacity, bool preserveContents = true)
|
||||
void EnsureCapacity(const int32 minCapacity, const bool preserveContents = true)
|
||||
{
|
||||
if (_capacity < minCapacity)
|
||||
{
|
||||
@@ -466,7 +466,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <param name="count">The amount of items.</param>
|
||||
void Set(const T* data, int32 count)
|
||||
void Set(const T* data, const int32 count)
|
||||
{
|
||||
EnsureCapacity(count, false);
|
||||
Memory::DestructItems(_allocation.Get(), _count);
|
||||
@@ -482,7 +482,7 @@ public:
|
||||
{
|
||||
EnsureCapacity(_count + 1);
|
||||
Memory::ConstructItems(_allocation.Get() + _count, &item, 1);
|
||||
_count++;
|
||||
++_count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -493,7 +493,7 @@ public:
|
||||
{
|
||||
EnsureCapacity(_count + 1);
|
||||
Memory::MoveItems(_allocation.Get() + _count, &item, 1);
|
||||
_count++;
|
||||
++_count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -501,7 +501,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="items">The items to add.</param>
|
||||
/// <param name="count">The items count.</param>
|
||||
void Add(const T* items, int32 count)
|
||||
void Add(const T* items, const int32 count)
|
||||
{
|
||||
EnsureCapacity(_count + count);
|
||||
Memory::ConstructItems(_allocation.Get() + _count, items, count);
|
||||
@@ -532,7 +532,7 @@ public:
|
||||
/// Adds the given amount of items to the collection.
|
||||
/// </summary>
|
||||
/// <param name="count">The items count.</param>
|
||||
FORCE_INLINE void AddDefault(int32 count = 1)
|
||||
FORCE_INLINE void AddDefault(const int32 count = 1)
|
||||
{
|
||||
EnsureCapacity(_count + count);
|
||||
Memory::ConstructItems(_allocation.Get() + _count, count);
|
||||
@@ -543,7 +543,7 @@ public:
|
||||
/// Adds the given amount of uninitialized items to the collection without calling the constructor.
|
||||
/// </summary>
|
||||
/// <param name="count">The items count.</param>
|
||||
FORCE_INLINE void AddUninitialized(int32 count = 1)
|
||||
FORCE_INLINE void AddUninitialized(const int32 count = 1)
|
||||
{
|
||||
EnsureCapacity(_count + count);
|
||||
_count += count;
|
||||
@@ -557,7 +557,7 @@ public:
|
||||
{
|
||||
EnsureCapacity(_count + 1);
|
||||
Memory::ConstructItems(_allocation.Get() + _count, 1);
|
||||
_count++;
|
||||
++_count;
|
||||
return _allocation.Get()[_count - 1];
|
||||
}
|
||||
|
||||
@@ -568,7 +568,7 @@ public:
|
||||
/// Warning! AddZeroed() will create items without calling the constructor and this is not appropriate for item types that require a constructor to function properly.
|
||||
/// </remarks>
|
||||
/// <param name="count">The number of new items to add.</param>
|
||||
void AddZeroed(int32 count = 1)
|
||||
void AddZeroed(const int32 count = 1)
|
||||
{
|
||||
EnsureCapacity(_count + count);
|
||||
Platform::MemoryClear(_allocation.Get() + _count, count * sizeof(T));
|
||||
@@ -580,7 +580,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index at which item should be inserted.</param>
|
||||
/// <param name="item">The item to be inserted by copying.</param>
|
||||
void Insert(int32 index, const T& item)
|
||||
void Insert(const int32 index, const T& item)
|
||||
{
|
||||
ASSERT(index >= 0 && index <= _count);
|
||||
EnsureCapacity(_count + 1);
|
||||
@@ -597,7 +597,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index at which item should be inserted.</param>
|
||||
/// <param name="item">The item to inserted by moving.</param>
|
||||
void Insert(int32 index, T&& item)
|
||||
void Insert(const int32 index, T&& item)
|
||||
{
|
||||
ASSERT(index >= 0 && index <= _count);
|
||||
EnsureCapacity(_count + 1);
|
||||
@@ -605,7 +605,7 @@ public:
|
||||
Memory::ConstructItems(data + _count, 1);
|
||||
for (int32 i = _count - 1; i >= index; i--)
|
||||
data[i + 1] = MoveTemp(data[i]);
|
||||
_count++;
|
||||
++_count;
|
||||
data[index] = MoveTemp(item);
|
||||
}
|
||||
|
||||
@@ -613,7 +613,7 @@ public:
|
||||
/// Insert the given item at specified index with keeping items order.
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index at which item should be inserted.</param>
|
||||
void Insert(int32 index)
|
||||
void Insert(const int32 index)
|
||||
{
|
||||
ASSERT(index >= 0 && index <= _count);
|
||||
EnsureCapacity(_count + 1);
|
||||
@@ -621,7 +621,7 @@ public:
|
||||
Memory::ConstructItems(data + _count, 1);
|
||||
for (int32 i = _count - 1; i >= index; i--)
|
||||
data[i + 1] = data[i];
|
||||
_count++;
|
||||
++_count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -661,7 +661,7 @@ public:
|
||||
/// <param name="item">The item to remove.</param>
|
||||
void RemoveAllKeepOrder(const T& item)
|
||||
{
|
||||
for (int32 i = Count() - 1; i >= 0; i--)
|
||||
for (int32 i = Count() - 1; i >= 0; --i)
|
||||
{
|
||||
if (_allocation.Get()[i] == item)
|
||||
{
|
||||
@@ -679,14 +679,14 @@ public:
|
||||
void RemoveAtKeepOrder(const int32 index)
|
||||
{
|
||||
ASSERT(index < _count && index >= 0);
|
||||
_count--;
|
||||
--_count;
|
||||
T* data = _allocation.Get();
|
||||
if (index < _count)
|
||||
{
|
||||
T* dst = data + index;
|
||||
T* src = data + (index + 1);
|
||||
const int32 count = _count - index;
|
||||
for (int32 i = 0; i < count; i++)
|
||||
for (int32 i = 0; i < count; ++i)
|
||||
dst[i] = MoveTemp(src[i]);
|
||||
}
|
||||
Memory::DestructItems(data + _count, 1);
|
||||
@@ -712,7 +712,7 @@ public:
|
||||
/// <param name="item">The item to remove.</param>
|
||||
void RemoveAll(const T& item)
|
||||
{
|
||||
for (int32 i = Count() - 1; i >= 0; i--)
|
||||
for (int32 i = Count() - 1; i >= 0; --i)
|
||||
{
|
||||
if (_allocation.Get()[i] == item)
|
||||
{
|
||||
@@ -730,7 +730,7 @@ public:
|
||||
void RemoveAt(const int32 index)
|
||||
{
|
||||
ASSERT(index < _count && index >= 0);
|
||||
_count--;
|
||||
--_count;
|
||||
T* data = _allocation.Get();
|
||||
if (_count)
|
||||
data[index] = data[_count];
|
||||
@@ -743,7 +743,7 @@ public:
|
||||
void RemoveLast()
|
||||
{
|
||||
ASSERT(_count > 0);
|
||||
_count--;
|
||||
--_count;
|
||||
Memory::DestructItems(_allocation.Get() + _count, 1);
|
||||
}
|
||||
|
||||
@@ -772,7 +772,7 @@ public:
|
||||
{
|
||||
T* data = _allocation.Get();
|
||||
const int32 count = _count / 2;
|
||||
for (int32 i = 0; i < count; i++)
|
||||
for (int32 i = 0; i < count; ++i)
|
||||
::Swap(data[i], data[_count - i - 1]);
|
||||
}
|
||||
|
||||
@@ -954,7 +954,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
Iterator(Array const* array, const int32 index)
|
||||
Iterator(const Array* array, const int32 index)
|
||||
: _array(const_cast<Array*>(array))
|
||||
, _index(index)
|
||||
{
|
||||
@@ -1052,7 +1052,7 @@ public:
|
||||
Iterator& operator--()
|
||||
{
|
||||
if (_index > 0)
|
||||
_index--;
|
||||
--_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1060,7 +1060,7 @@ public:
|
||||
{
|
||||
Iterator temp = *this;
|
||||
if (_index > 0)
|
||||
_index--;
|
||||
--_index;
|
||||
return temp;
|
||||
}
|
||||
};
|
||||
@@ -1084,7 +1084,7 @@ public:
|
||||
};
|
||||
|
||||
template<typename T, typename AllocationType>
|
||||
void* operator new(size_t size, Array<T, AllocationType>& array)
|
||||
void* operator new(const size_t size, Array<T, AllocationType>& array)
|
||||
{
|
||||
ASSERT(size == sizeof(T));
|
||||
const int32 index = array.Count();
|
||||
@@ -1093,7 +1093,7 @@ void* operator new(size_t size, Array<T, AllocationType>& array)
|
||||
}
|
||||
|
||||
template<typename T, typename AllocationType>
|
||||
void* operator new(size_t size, Array<T, AllocationType>& array, int32 index)
|
||||
void* operator new(const size_t size, Array<T, AllocationType>& array, const int32 index)
|
||||
{
|
||||
ASSERT(size == sizeof(T));
|
||||
array.Insert(index);
|
||||
|
||||
@@ -14,20 +14,20 @@ API_CLASS(InBuild) class BitArray
|
||||
{
|
||||
friend BitArray;
|
||||
public:
|
||||
typedef uint64 ItemType;
|
||||
typedef typename AllocationType::template Data<ItemType> AllocationData;
|
||||
using ItemType = uint64;
|
||||
using AllocationData = typename AllocationType::template Data<ItemType>;
|
||||
|
||||
private:
|
||||
int32 _count;
|
||||
int32 _capacity;
|
||||
AllocationData _allocation;
|
||||
|
||||
FORCE_INLINE static int32 ToItemCount(int32 size)
|
||||
FORCE_INLINE static int32 ToItemCount(const int32 size)
|
||||
{
|
||||
return Math::DivideAndRoundUp<int32>(size, sizeof(ItemType));
|
||||
}
|
||||
|
||||
FORCE_INLINE static int32 ToItemCapacity(int32 size)
|
||||
FORCE_INLINE static int32 ToItemCapacity(const int32 size)
|
||||
{
|
||||
return Math::Max<int32>(Math::DivideAndRoundUp<int32>(size, sizeof(ItemType)), 1);
|
||||
}
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
/// Initializes a new instance of the <see cref="BitArray"/> class.
|
||||
/// </summary>
|
||||
/// <param name="capacity">The initial capacity.</param>
|
||||
BitArray(int32 capacity)
|
||||
explicit BitArray(const int32 capacity)
|
||||
: _count(0)
|
||||
, _capacity(capacity)
|
||||
{
|
||||
@@ -200,7 +200,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the item.</param>
|
||||
/// <returns>The value of the item.</returns>
|
||||
FORCE_INLINE bool operator[](int32 index) const
|
||||
FORCE_INLINE bool operator[](const int32 index) const
|
||||
{
|
||||
return Get(index);
|
||||
}
|
||||
@@ -210,7 +210,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the item.</param>
|
||||
/// <returns>The value of the item.</returns>
|
||||
bool Get(int32 index) const
|
||||
bool Get(const int32 index) const
|
||||
{
|
||||
ASSERT(index >= 0 && index < _count);
|
||||
const ItemType offset = index / sizeof(ItemType);
|
||||
@@ -224,7 +224,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the item.</param>
|
||||
/// <param name="value">The value to set.</param>
|
||||
void Set(int32 index, bool value)
|
||||
void Set(const int32 index, const bool value)
|
||||
{
|
||||
ASSERT(index >= 0 && index < _count);
|
||||
const ItemType offset = index / sizeof(ItemType);
|
||||
@@ -233,7 +233,7 @@ public:
|
||||
if (value)
|
||||
item |= bitMask;
|
||||
else
|
||||
item &= ~bitMask;
|
||||
item &= ~bitMask; // Clear the bit
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -250,7 +250,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="capacity">The new capacity.</param>
|
||||
/// <param name="preserveContents">True if preserve collection data when changing its size, otherwise collection after resize will be empty.</param>
|
||||
void SetCapacity(const int32 capacity, bool preserveContents = true)
|
||||
void SetCapacity(const int32 capacity, const bool preserveContents = true)
|
||||
{
|
||||
if (capacity == _capacity)
|
||||
return;
|
||||
@@ -266,7 +266,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="size">The new collection size.</param>
|
||||
/// <param name="preserveContents">True if preserve collection data when changing its size, otherwise collection after resize might not contain the previous data.</param>
|
||||
void Resize(int32 size, bool preserveContents = true)
|
||||
void Resize(const int32 size, const bool preserveContents = true)
|
||||
{
|
||||
if (_count <= size)
|
||||
EnsureCapacity(size, preserveContents);
|
||||
@@ -278,7 +278,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="minCapacity">The minimum capacity.</param>
|
||||
/// <param name="preserveContents">True if preserve collection data when changing its size, otherwise collection after resize will be empty.</param>
|
||||
void EnsureCapacity(int32 minCapacity, bool preserveContents = true)
|
||||
void EnsureCapacity(const int32 minCapacity, const bool preserveContents = true)
|
||||
{
|
||||
if (_capacity < minCapacity)
|
||||
{
|
||||
@@ -304,7 +304,7 @@ public:
|
||||
void Add(const bool item)
|
||||
{
|
||||
EnsureCapacity(_count + 1);
|
||||
_count++;
|
||||
++_count;
|
||||
Set(_count - 1, item);
|
||||
}
|
||||
|
||||
@@ -313,10 +313,10 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="items">The items to add.</param>
|
||||
/// <param name="count">The items count.</param>
|
||||
void Add(const bool* items, int32 count)
|
||||
void Add(const bool* items, const int32 count)
|
||||
{
|
||||
EnsureCapacity(_count + count);
|
||||
for (int32 i = 0; i < count; i++)
|
||||
for (int32 i = 0; i < count; ++i)
|
||||
Add(items[i]);
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ public:
|
||||
void Add(const BitArray& other)
|
||||
{
|
||||
EnsureCapacity(_count, other.Count());
|
||||
for (int32 i = 0; i < other.Count(); i++)
|
||||
for (int32 i = 0; i < other.Count(); ++i)
|
||||
Add(other[i]);
|
||||
}
|
||||
|
||||
|
||||
15
Source/Engine/Core/Collections/BucketState.h
Normal file
15
Source/Engine/Core/Collections/BucketState.h
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Core/Types/BaseTypes.h"
|
||||
|
||||
/// <summary>
|
||||
/// Tells if the object is occupied, and if not, if the bucket is a subject of compaction.
|
||||
/// </summary>
|
||||
enum class BucketState : byte
|
||||
{
|
||||
Empty = 0,
|
||||
Deleted = 1,
|
||||
Occupied = 2,
|
||||
};
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "Engine/Core/Memory/Memory.h"
|
||||
#include "Engine/Core/Memory/Allocation.h"
|
||||
#include "Engine/Core/Collections/BucketState.h"
|
||||
#include "Engine/Core/Collections/HashFunctions.h"
|
||||
#include "Engine/Core/Collections/Config.h"
|
||||
|
||||
@@ -25,34 +26,27 @@ public:
|
||||
{
|
||||
friend Dictionary;
|
||||
|
||||
enum State : byte
|
||||
{
|
||||
Empty = 0,
|
||||
Deleted = 1,
|
||||
Occupied = 2,
|
||||
};
|
||||
|
||||
/// <summary>The key.</summary>
|
||||
KeyType Key;
|
||||
/// <summary>The value.</summary>
|
||||
ValueType Value;
|
||||
|
||||
private:
|
||||
State _state;
|
||||
BucketState _state;
|
||||
|
||||
FORCE_INLINE void Free()
|
||||
{
|
||||
if (_state == Occupied)
|
||||
if (_state == BucketState::Occupied)
|
||||
{
|
||||
Memory::DestructItem(&Key);
|
||||
Memory::DestructItem(&Value);
|
||||
}
|
||||
_state = Empty;
|
||||
_state = BucketState::Empty;
|
||||
}
|
||||
|
||||
FORCE_INLINE void Delete()
|
||||
{
|
||||
_state = Deleted;
|
||||
_state = BucketState::Deleted;
|
||||
Memory::DestructItem(&Key);
|
||||
Memory::DestructItem(&Value);
|
||||
}
|
||||
@@ -62,7 +56,7 @@ public:
|
||||
{
|
||||
Memory::ConstructItems(&Key, &key, 1);
|
||||
Memory::ConstructItem(&Value);
|
||||
_state = Occupied;
|
||||
_state = BucketState::Occupied;
|
||||
}
|
||||
|
||||
template<typename KeyComparableType>
|
||||
@@ -70,7 +64,7 @@ public:
|
||||
{
|
||||
Memory::ConstructItems(&Key, &key, 1);
|
||||
Memory::ConstructItems(&Value, &value, 1);
|
||||
_state = Occupied;
|
||||
_state = BucketState::Occupied;
|
||||
}
|
||||
|
||||
template<typename KeyComparableType>
|
||||
@@ -78,31 +72,31 @@ public:
|
||||
{
|
||||
Memory::ConstructItems(&Key, &key, 1);
|
||||
Memory::MoveItems(&Value, &value, 1);
|
||||
_state = Occupied;
|
||||
_state = BucketState::Occupied;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool IsEmpty() const
|
||||
{
|
||||
return _state == Empty;
|
||||
return _state == BucketState::Empty;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool IsDeleted() const
|
||||
{
|
||||
return _state == Deleted;
|
||||
return _state == BucketState::Deleted;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool IsOccupied() const
|
||||
{
|
||||
return _state == Occupied;
|
||||
return _state == BucketState::Occupied;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool IsNotOccupied() const
|
||||
{
|
||||
return _state != Occupied;
|
||||
return _state != BucketState::Occupied;
|
||||
}
|
||||
};
|
||||
|
||||
typedef typename AllocationType::template Data<Bucket> AllocationData;
|
||||
using AllocationData = typename AllocationType::template Data<Bucket>;
|
||||
|
||||
private:
|
||||
int32 _elementsCount = 0;
|
||||
@@ -110,7 +104,7 @@ private:
|
||||
int32 _size = 0;
|
||||
AllocationData _allocation;
|
||||
|
||||
FORCE_INLINE static void MoveToEmpty(AllocationData& to, AllocationData& from, int32 fromSize)
|
||||
FORCE_INLINE static void MoveToEmpty(AllocationData& to, AllocationData& from, const int32 fromSize)
|
||||
{
|
||||
if IF_CONSTEXPR (AllocationType::HasSwap)
|
||||
to.Swap(from);
|
||||
@@ -127,10 +121,10 @@ private:
|
||||
Bucket& toBucket = toData[i];
|
||||
Memory::MoveItems(&toBucket.Key, &fromBucket.Key, 1);
|
||||
Memory::MoveItems(&toBucket.Value, &fromBucket.Value, 1);
|
||||
toBucket._state = Bucket::Occupied;
|
||||
toBucket._state = BucketState::Occupied;
|
||||
Memory::DestructItem(&fromBucket.Key);
|
||||
Memory::DestructItem(&fromBucket.Value);
|
||||
fromBucket._state = Bucket::Empty;
|
||||
fromBucket._state = BucketState::Empty;
|
||||
}
|
||||
}
|
||||
from.Free();
|
||||
@@ -149,7 +143,7 @@ public:
|
||||
/// Initializes a new instance of the <see cref="Dictionary"/> class.
|
||||
/// </summary>
|
||||
/// <param name="capacity">The initial capacity.</param>
|
||||
Dictionary(int32 capacity)
|
||||
explicit Dictionary(const int32 capacity)
|
||||
{
|
||||
SetCapacity(capacity);
|
||||
}
|
||||
@@ -289,7 +283,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
Iterator(Iterator&& i)
|
||||
Iterator(Iterator&& i) noexcept
|
||||
: _collection(i._collection)
|
||||
, _index(i._index)
|
||||
{
|
||||
@@ -348,7 +342,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iterator& operator=(Iterator&& v)
|
||||
Iterator& operator=(Iterator&& v) noexcept
|
||||
{
|
||||
_collection = v._collection;
|
||||
_index = v._index;
|
||||
@@ -363,8 +357,9 @@ public:
|
||||
const Bucket* data = _collection->_allocation.Get();
|
||||
do
|
||||
{
|
||||
_index++;
|
||||
} while (_index != capacity && data[_index].IsNotOccupied());
|
||||
++_index;
|
||||
}
|
||||
while (_index != capacity && data[_index].IsNotOccupied());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -383,8 +378,9 @@ public:
|
||||
const Bucket* data = _collection->_allocation.Get();
|
||||
do
|
||||
{
|
||||
_index--;
|
||||
} while (_index > 0 && data[_index].IsNotOccupied());
|
||||
--_index;
|
||||
}
|
||||
while (_index > 0 && data[_index].IsNotOccupied());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -423,7 +419,7 @@ public:
|
||||
|
||||
// Insert
|
||||
ASSERT(pos.FreeSlotIndex != -1);
|
||||
_elementsCount++;
|
||||
++_elementsCount;
|
||||
Bucket& bucket = _allocation.Get()[pos.FreeSlotIndex];
|
||||
bucket.Occupy(key);
|
||||
return bucket.Value;
|
||||
@@ -498,7 +494,7 @@ public:
|
||||
FindPosition(key, pos);
|
||||
if (pos.ObjectIndex == -1)
|
||||
return nullptr;
|
||||
return (ValueType*)&_allocation.Get()[pos.ObjectIndex].Value;
|
||||
return const_cast<ValueType*>(&_allocation.Get()[pos.ObjectIndex].Value); //TODO This one is problematic. I think this entire method should be removed.
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -538,7 +534,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="capacity">The new capacity.</param>
|
||||
/// <param name="preserveContents">Enables preserving collection contents during resizing.</param>
|
||||
void SetCapacity(int32 capacity, bool preserveContents = true)
|
||||
void SetCapacity(int32 capacity, const bool preserveContents = true)
|
||||
{
|
||||
if (capacity == Capacity())
|
||||
return;
|
||||
@@ -564,7 +560,7 @@ public:
|
||||
_allocation.Allocate(capacity);
|
||||
Bucket* data = _allocation.Get();
|
||||
for (int32 i = 0; i < capacity; i++)
|
||||
data[i]._state = Bucket::Empty;
|
||||
data[i]._state = BucketState::Empty;
|
||||
}
|
||||
_size = capacity;
|
||||
Bucket* oldData = oldAllocation.Get();
|
||||
@@ -581,8 +577,8 @@ public:
|
||||
Bucket* bucket = &_allocation.Get()[pos.FreeSlotIndex];
|
||||
Memory::MoveItems(&bucket->Key, &oldBucket.Key, 1);
|
||||
Memory::MoveItems(&bucket->Value, &oldBucket.Value, 1);
|
||||
bucket->_state = Bucket::Occupied;
|
||||
_elementsCount++;
|
||||
bucket->_state = BucketState::Occupied;
|
||||
++_elementsCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -598,7 +594,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="minCapacity">The minimum required capacity.</param>
|
||||
/// <param name="preserveContents">True if preserve collection data when changing its size, otherwise collection after resize will be empty.</param>
|
||||
void EnsureCapacity(int32 minCapacity, bool preserveContents = true)
|
||||
void EnsureCapacity(int32 minCapacity, const bool preserveContents = true)
|
||||
{
|
||||
if (_size >= minCapacity)
|
||||
return;
|
||||
@@ -682,8 +678,8 @@ public:
|
||||
if (pos.ObjectIndex != -1)
|
||||
{
|
||||
_allocation.Get()[pos.ObjectIndex].Delete();
|
||||
_elementsCount--;
|
||||
_deletedCount++;
|
||||
--_elementsCount;
|
||||
++_deletedCount;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -701,8 +697,8 @@ public:
|
||||
{
|
||||
ASSERT(_allocation.Get()[i._index].IsOccupied());
|
||||
_allocation.Get()[i._index].Delete();
|
||||
_elementsCount--;
|
||||
_deletedCount++;
|
||||
--_elementsCount;
|
||||
++_deletedCount;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -721,7 +717,7 @@ public:
|
||||
if (i->Value == value)
|
||||
{
|
||||
Remove(i);
|
||||
result++;
|
||||
++result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -768,7 +764,7 @@ public:
|
||||
if (HasItems())
|
||||
{
|
||||
const Bucket* data = _allocation.Get();
|
||||
for (int32 i = 0; i < _size; i++)
|
||||
for (int32 i = 0; i < _size; ++i)
|
||||
{
|
||||
if (data[i].IsOccupied() && data[i].Value == value)
|
||||
return true;
|
||||
@@ -788,7 +784,7 @@ public:
|
||||
if (HasItems())
|
||||
{
|
||||
const Bucket* data = _allocation.Get();
|
||||
for (int32 i = 0; i < _size; i++)
|
||||
for (int32 i = 0; i < _size; ++i)
|
||||
{
|
||||
if (data[i].IsOccupied() && data[i].Value == value)
|
||||
{
|
||||
@@ -862,14 +858,14 @@ public:
|
||||
return Iterator(this, _size);
|
||||
}
|
||||
|
||||
const Iterator begin() const
|
||||
Iterator begin() const
|
||||
{
|
||||
Iterator i(this, -1);
|
||||
++i;
|
||||
return i;
|
||||
}
|
||||
|
||||
FORCE_INLINE const Iterator end() const
|
||||
FORCE_INLINE Iterator end() const
|
||||
{
|
||||
return Iterator(this, _size);
|
||||
}
|
||||
@@ -928,7 +924,7 @@ private:
|
||||
result.ObjectIndex = bucketIndex;
|
||||
return;
|
||||
}
|
||||
checksCount++;
|
||||
++checksCount;
|
||||
bucketIndex = (bucketIndex + DICTIONARY_PROB_FUNC(_size, checksCount)) & tableSizeMinusOne;
|
||||
}
|
||||
result.ObjectIndex = -1;
|
||||
@@ -965,7 +961,7 @@ private:
|
||||
// Fast path if it's empty
|
||||
Bucket* data = _allocation.Get();
|
||||
for (int32 i = 0; i < _size; i++)
|
||||
data[i]._state = Bucket::Empty;
|
||||
data[i]._state = BucketState::Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -975,7 +971,7 @@ private:
|
||||
_allocation.Allocate(_size);
|
||||
Bucket* data = _allocation.Get();
|
||||
for (int32 i = 0; i < _size; i++)
|
||||
data[i]._state = Bucket::Empty;
|
||||
data[i]._state = BucketState::Empty;
|
||||
Bucket* oldData = oldAllocation.Get();
|
||||
FindPositionResult pos;
|
||||
for (int32 i = 0; i < _size; i++)
|
||||
@@ -988,7 +984,7 @@ private:
|
||||
Bucket* bucket = &_allocation.Get()[pos.FreeSlotIndex];
|
||||
Memory::MoveItems(&bucket->Key, &oldBucket.Key, 1);
|
||||
Memory::MoveItems(&bucket->Value, &oldBucket.Value, 1);
|
||||
bucket->_state = Bucket::Occupied;
|
||||
bucket->_state = BucketState::Occupied;
|
||||
}
|
||||
}
|
||||
for (int32 i = 0; i < _size; i++)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "Engine/Core/Memory/Memory.h"
|
||||
#include "Engine/Core/Memory/Allocation.h"
|
||||
#include "Engine/Core/Collections/BucketState.h"
|
||||
#include "Engine/Core/Collections/HashFunctions.h"
|
||||
#include "Engine/Core/Collections/Config.h"
|
||||
|
||||
@@ -24,29 +25,22 @@ public:
|
||||
{
|
||||
friend HashSet;
|
||||
|
||||
enum State : byte
|
||||
{
|
||||
Empty,
|
||||
Deleted,
|
||||
Occupied,
|
||||
};
|
||||
|
||||
/// <summary>The item.</summary>
|
||||
T Item;
|
||||
|
||||
private:
|
||||
State _state;
|
||||
BucketState _state;
|
||||
|
||||
FORCE_INLINE void Free()
|
||||
{
|
||||
if (_state == Occupied)
|
||||
if (_state == BucketState::Occupied)
|
||||
Memory::DestructItem(&Item);
|
||||
_state = Empty;
|
||||
_state = BucketState::Empty;
|
||||
}
|
||||
|
||||
FORCE_INLINE void Delete()
|
||||
{
|
||||
_state = Deleted;
|
||||
_state = BucketState::Deleted;
|
||||
Memory::DestructItem(&Item);
|
||||
}
|
||||
|
||||
@@ -54,38 +48,38 @@ public:
|
||||
FORCE_INLINE void Occupy(const ItemType& item)
|
||||
{
|
||||
Memory::ConstructItems(&Item, &item, 1);
|
||||
_state = Occupied;
|
||||
_state = BucketState::Occupied;
|
||||
}
|
||||
|
||||
template<typename ItemType>
|
||||
FORCE_INLINE void Occupy(ItemType&& item)
|
||||
{
|
||||
Memory::MoveItems(&Item, &item, 1);
|
||||
_state = Occupied;
|
||||
_state = BucketState::Occupied;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool IsEmpty() const
|
||||
{
|
||||
return _state == Empty;
|
||||
return _state == BucketState::Empty;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool IsDeleted() const
|
||||
{
|
||||
return _state == Deleted;
|
||||
return _state == BucketState::Deleted;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool IsOccupied() const
|
||||
{
|
||||
return _state == Occupied;
|
||||
return _state == BucketState::Occupied;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool IsNotOccupied() const
|
||||
{
|
||||
return _state != Occupied;
|
||||
return _state != BucketState::Occupied;
|
||||
}
|
||||
};
|
||||
|
||||
typedef typename AllocationType::template Data<Bucket> AllocationData;
|
||||
using AllocationData = typename AllocationType::template Data<Bucket>;
|
||||
|
||||
private:
|
||||
int32 _elementsCount = 0;
|
||||
@@ -93,7 +87,7 @@ private:
|
||||
int32 _size = 0;
|
||||
AllocationData _allocation;
|
||||
|
||||
FORCE_INLINE static void MoveToEmpty(AllocationData& to, AllocationData& from, int32 fromSize)
|
||||
FORCE_INLINE static void MoveToEmpty(AllocationData& to, AllocationData& from, const int32 fromSize)
|
||||
{
|
||||
if IF_CONSTEXPR (AllocationType::HasSwap)
|
||||
to.Swap(from);
|
||||
@@ -102,16 +96,16 @@ private:
|
||||
to.Allocate(fromSize);
|
||||
Bucket* toData = to.Get();
|
||||
Bucket* fromData = from.Get();
|
||||
for (int32 i = 0; i < fromSize; i++)
|
||||
for (int32 i = 0; i < fromSize; ++i)
|
||||
{
|
||||
Bucket& fromBucket = fromData[i];
|
||||
if (fromBucket.IsOccupied())
|
||||
{
|
||||
Bucket& toBucket = toData[i];
|
||||
Memory::MoveItems(&toBucket.Item, &fromBucket.Item, 1);
|
||||
toBucket._state = Bucket::Occupied;
|
||||
toBucket._state = BucketState::Occupied;
|
||||
Memory::DestructItem(&fromBucket.Item);
|
||||
fromBucket._state = Bucket::Empty;
|
||||
fromBucket._state = BucketState::Empty;
|
||||
}
|
||||
}
|
||||
from.Free();
|
||||
@@ -130,7 +124,7 @@ public:
|
||||
/// Initializes a new instance of the <see cref="HashSet"/> class.
|
||||
/// </summary>
|
||||
/// <param name="capacity">The initial capacity.</param>
|
||||
HashSet(int32 capacity)
|
||||
explicit HashSet(const int32 capacity)
|
||||
{
|
||||
SetCapacity(capacity);
|
||||
}
|
||||
@@ -252,7 +246,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
Iterator(HashSet const* collection, const int32 index)
|
||||
Iterator(const HashSet* collection, const int32 index)
|
||||
: _collection(const_cast<HashSet*>(collection))
|
||||
, _index(index)
|
||||
{
|
||||
@@ -270,7 +264,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
Iterator(Iterator&& i)
|
||||
Iterator(Iterator&& i) noexcept
|
||||
: _collection(i._collection)
|
||||
, _index(i._index)
|
||||
{
|
||||
@@ -307,7 +301,7 @@ public:
|
||||
return _index >= 0 && _index < _collection->_size;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool operator !() const
|
||||
FORCE_INLINE bool operator!() const
|
||||
{
|
||||
return !(bool)*this;
|
||||
}
|
||||
@@ -329,7 +323,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iterator& operator=(Iterator&& v)
|
||||
Iterator& operator=(Iterator&& v) noexcept
|
||||
{
|
||||
_collection = v._collection;
|
||||
_index = v._index;
|
||||
@@ -344,8 +338,9 @@ public:
|
||||
const Bucket* data = _collection->_allocation.Get();
|
||||
do
|
||||
{
|
||||
_index++;
|
||||
} while (_index != capacity && data[_index].IsNotOccupied());
|
||||
++_index;
|
||||
}
|
||||
while (_index != capacity && data[_index].IsNotOccupied());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -364,8 +359,9 @@ public:
|
||||
const Bucket* data = _collection->_allocation.Get();
|
||||
do
|
||||
{
|
||||
_index--;
|
||||
} while (_index > 0 && data[_index].IsNotOccupied());
|
||||
--_index;
|
||||
}
|
||||
while (_index > 0 && data[_index].IsNotOccupied());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -415,7 +411,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="capacity">New capacity</param>
|
||||
/// <param name="preserveContents">Enable/disable preserving collection contents during resizing</param>
|
||||
void SetCapacity(int32 capacity, bool preserveContents = true)
|
||||
void SetCapacity(int32 capacity, const bool preserveContents = true)
|
||||
{
|
||||
if (capacity == Capacity())
|
||||
return;
|
||||
@@ -441,7 +437,7 @@ public:
|
||||
_allocation.Allocate(capacity);
|
||||
Bucket* data = _allocation.Get();
|
||||
for (int32 i = 0; i < capacity; i++)
|
||||
data[i]._state = Bucket::Empty;
|
||||
data[i]._state = BucketState::Empty;
|
||||
}
|
||||
_size = capacity;
|
||||
Bucket* oldData = oldAllocation.Get();
|
||||
@@ -457,7 +453,7 @@ public:
|
||||
ASSERT(pos.FreeSlotIndex != -1);
|
||||
Bucket* bucket = &_allocation.Get()[pos.FreeSlotIndex];
|
||||
Memory::MoveItems(&bucket->Item, &oldBucket.Item, 1);
|
||||
bucket->_state = Bucket::Occupied;
|
||||
bucket->_state = BucketState::Occupied;
|
||||
_elementsCount++;
|
||||
}
|
||||
}
|
||||
@@ -474,7 +470,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="minCapacity">The minimum required capacity.</param>
|
||||
/// <param name="preserveContents">True if preserve collection data when changing its size, otherwise collection after resize will be empty.</param>
|
||||
void EnsureCapacity(int32 minCapacity, bool preserveContents = true)
|
||||
void EnsureCapacity(const int32 minCapacity, const bool preserveContents = true)
|
||||
{
|
||||
if (_size >= minCapacity)
|
||||
return;
|
||||
@@ -559,8 +555,8 @@ public:
|
||||
if (pos.ObjectIndex != -1)
|
||||
{
|
||||
_allocation.Get()[pos.ObjectIndex].Delete();
|
||||
_elementsCount--;
|
||||
_deletedCount++;
|
||||
--_elementsCount;
|
||||
++_deletedCount;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -578,8 +574,8 @@ public:
|
||||
{
|
||||
ASSERT(_allocation.Get()[i._index].IsOccupied());
|
||||
_allocation.Get()[i._index].Delete();
|
||||
_elementsCount--;
|
||||
_deletedCount++;
|
||||
--_elementsCount;
|
||||
++_deletedCount;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -656,14 +652,14 @@ public:
|
||||
return Iterator(this, _size);
|
||||
}
|
||||
|
||||
const Iterator begin() const
|
||||
Iterator begin() const
|
||||
{
|
||||
Iterator i(this, -1);
|
||||
++i;
|
||||
return i;
|
||||
}
|
||||
|
||||
FORCE_INLINE const Iterator end() const
|
||||
FORCE_INLINE Iterator end() const
|
||||
{
|
||||
return Iterator(this, _size);
|
||||
}
|
||||
@@ -750,7 +746,7 @@ private:
|
||||
|
||||
// Insert
|
||||
ASSERT(pos.FreeSlotIndex != -1);
|
||||
_elementsCount++;
|
||||
++_elementsCount;
|
||||
return &_allocation.Get()[pos.FreeSlotIndex];
|
||||
}
|
||||
|
||||
@@ -760,8 +756,8 @@ private:
|
||||
{
|
||||
// Fast path if it's empty
|
||||
Bucket* data = _allocation.Get();
|
||||
for (int32 i = 0; i < _size; i++)
|
||||
data[i]._state = Bucket::Empty;
|
||||
for (int32 i = 0; i < _size; ++i)
|
||||
data[i]._state = BucketState::Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -770,11 +766,11 @@ private:
|
||||
MoveToEmpty(oldAllocation, _allocation, _size);
|
||||
_allocation.Allocate(_size);
|
||||
Bucket* data = _allocation.Get();
|
||||
for (int32 i = 0; i < _size; i++)
|
||||
data[i]._state = Bucket::Empty;
|
||||
for (int32 i = 0; i < _size; ++i)
|
||||
data[i]._state = BucketState::Empty;
|
||||
Bucket* oldData = oldAllocation.Get();
|
||||
FindPositionResult pos;
|
||||
for (int32 i = 0; i < _size; i++)
|
||||
for (int32 i = 0; i < _size; ++i)
|
||||
{
|
||||
Bucket& oldBucket = oldData[i];
|
||||
if (oldBucket.IsOccupied())
|
||||
@@ -783,10 +779,10 @@ private:
|
||||
ASSERT(pos.FreeSlotIndex != -1);
|
||||
Bucket* bucket = &_allocation.Get()[pos.FreeSlotIndex];
|
||||
Memory::MoveItems(&bucket->Item, &oldBucket.Item, 1);
|
||||
bucket->_state = Bucket::Occupied;
|
||||
bucket->_state = BucketState::Occupied;
|
||||
}
|
||||
}
|
||||
for (int32 i = 0; i < _size; i++)
|
||||
for (int32 i = 0; i < _size; ++i)
|
||||
oldData[i].Free();
|
||||
}
|
||||
_deletedCount = 0;
|
||||
|
||||
@@ -14,8 +14,8 @@ template<typename T, typename AllocationType = HeapAllocation>
|
||||
class RingBuffer
|
||||
{
|
||||
public:
|
||||
typedef T ItemType;
|
||||
typedef typename AllocationType::template Data<T> AllocationData;
|
||||
using ItemType = T;
|
||||
using AllocationData = typename AllocationType::template Data<T>;
|
||||
|
||||
private:
|
||||
int32 _front = 0, _back = 0, _count = 0, _capacity = 0;
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
}
|
||||
Memory::ConstructItems(_allocation.Get() + _back, &data, 1);
|
||||
_back = (_back + 1) % _capacity;
|
||||
_count++;
|
||||
++_count;
|
||||
}
|
||||
|
||||
FORCE_INLINE T& PeekFront()
|
||||
@@ -75,13 +75,13 @@ public:
|
||||
return _allocation.Get()[_front];
|
||||
}
|
||||
|
||||
FORCE_INLINE T& operator[](int32 index)
|
||||
FORCE_INLINE T& operator[](const int32 index)
|
||||
{
|
||||
ASSERT(index >= 0 && index < _count);
|
||||
return _allocation.Get()[(_front + index) % _capacity];
|
||||
}
|
||||
|
||||
FORCE_INLINE const T& operator[](int32 index) const
|
||||
FORCE_INLINE const T& operator[](const int32 index) const
|
||||
{
|
||||
ASSERT(index >= 0 && index < _count);
|
||||
return _allocation.Get()[(_front + index) % _capacity];
|
||||
@@ -91,7 +91,7 @@ public:
|
||||
{
|
||||
Memory::DestructItems(_allocation.Get() + _front, 1);
|
||||
_front = (_front + 1) % _capacity;
|
||||
_count--;
|
||||
--_count;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
|
||||
@@ -54,12 +54,17 @@ void LogContext::Print(LogType verbosity)
|
||||
StringBuilder msg;
|
||||
for (int32 index = (int32)stack.Count - 1; index >= 0; index--)
|
||||
{
|
||||
LogContextData& context = stack.Ptr[index];
|
||||
|
||||
// Skip duplicates
|
||||
if (index < (int32)stack.Count - 1 && stack.Ptr[stack.Count - 1] == context)
|
||||
continue;
|
||||
|
||||
// Build call hierarchy via indentation
|
||||
msg.Clear();
|
||||
for (uint32 i = index; i < stack.Count; i++)
|
||||
msg.Append(indentation);
|
||||
|
||||
LogContextData& context = stack.Ptr[index];
|
||||
if (context.ObjectID != Guid::Empty)
|
||||
{
|
||||
// Object reference context
|
||||
|
||||
@@ -20,6 +20,11 @@ API_STRUCT(NoDefault) struct FLAXENGINE_API LogContextData
|
||||
/// A GUID for an object which this context applies to.
|
||||
/// </summary>
|
||||
API_FIELD() Guid ObjectID;
|
||||
|
||||
friend bool operator==(const LogContextData& lhs, const LogContextData& rhs)
|
||||
{
|
||||
return lhs.ObjectID == rhs.ObjectID;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
|
||||
@@ -31,28 +31,28 @@ public:
|
||||
|
||||
FORCE_INLINE T* Get()
|
||||
{
|
||||
return (T*)_data;
|
||||
return reinterpret_cast<T*>(_data);
|
||||
}
|
||||
|
||||
FORCE_INLINE const T* Get() const
|
||||
{
|
||||
return (T*)_data;
|
||||
return reinterpret_cast<const T*>(_data);
|
||||
}
|
||||
|
||||
FORCE_INLINE int32 CalculateCapacityGrow(int32 capacity, int32 minCapacity) const
|
||||
FORCE_INLINE int32 CalculateCapacityGrow(int32 capacity, const int32 minCapacity) const
|
||||
{
|
||||
ASSERT(minCapacity <= Capacity);
|
||||
return Capacity;
|
||||
}
|
||||
|
||||
FORCE_INLINE void Allocate(int32 capacity)
|
||||
FORCE_INLINE void Allocate(const int32 capacity)
|
||||
{
|
||||
#if ENABLE_ASSERTION_LOW_LAYERS
|
||||
ASSERT(capacity <= Capacity);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCE_INLINE void Relocate(int32 capacity, int32 oldCount, int32 newCount)
|
||||
FORCE_INLINE void Relocate(const int32 capacity, int32 oldCount, int32 newCount)
|
||||
{
|
||||
#if ENABLE_ASSERTION_LOW_LAYERS
|
||||
ASSERT(capacity <= Capacity);
|
||||
@@ -104,7 +104,7 @@ public:
|
||||
return _data;
|
||||
}
|
||||
|
||||
FORCE_INLINE int32 CalculateCapacityGrow(int32 capacity, int32 minCapacity) const
|
||||
FORCE_INLINE int32 CalculateCapacityGrow(int32 capacity, const int32 minCapacity) const
|
||||
{
|
||||
if (capacity < minCapacity)
|
||||
capacity = minCapacity;
|
||||
@@ -129,21 +129,21 @@ public:
|
||||
return capacity;
|
||||
}
|
||||
|
||||
FORCE_INLINE void Allocate(int32 capacity)
|
||||
FORCE_INLINE void Allocate(const int32 capacity)
|
||||
{
|
||||
#if ENABLE_ASSERTION_LOW_LAYERS
|
||||
ASSERT(!_data);
|
||||
#endif
|
||||
_data = (T*)Allocator::Allocate(capacity * sizeof(T));
|
||||
_data = static_cast<T*>(Allocator::Allocate(capacity * sizeof(T)));
|
||||
#if !BUILD_RELEASE
|
||||
if (!_data)
|
||||
OUT_OF_MEMORY;
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCE_INLINE void Relocate(int32 capacity, int32 oldCount, int32 newCount)
|
||||
FORCE_INLINE void Relocate(const int32 capacity, int32 oldCount, int32 newCount)
|
||||
{
|
||||
T* newData = capacity != 0 ? (T*)Allocator::Allocate(capacity * sizeof(T)) : nullptr;
|
||||
T* newData = capacity != 0 ? static_cast<T*>(Allocator::Allocate(capacity * sizeof(T))) : nullptr;
|
||||
#if !BUILD_RELEASE
|
||||
if (!newData && capacity != 0)
|
||||
OUT_OF_MEMORY;
|
||||
@@ -203,12 +203,12 @@ public:
|
||||
|
||||
FORCE_INLINE T* Get()
|
||||
{
|
||||
return _useOther ? _other.Get() : (T*)_data;
|
||||
return _useOther ? _other.Get() : reinterpret_cast<T*>(_data);
|
||||
}
|
||||
|
||||
FORCE_INLINE const T* Get() const
|
||||
{
|
||||
return _useOther ? _other.Get() : (T*)_data;
|
||||
return _useOther ? _other.Get() : reinterpret_cast<const T*>(_data);
|
||||
}
|
||||
|
||||
FORCE_INLINE int32 CalculateCapacityGrow(int32 capacity, int32 minCapacity) const
|
||||
@@ -227,13 +227,15 @@ public:
|
||||
|
||||
FORCE_INLINE void Relocate(int32 capacity, int32 oldCount, int32 newCount)
|
||||
{
|
||||
T* data = reinterpret_cast<T*>(_data);
|
||||
|
||||
// Check if the new allocation will fit into inlined storage
|
||||
if (capacity <= Capacity)
|
||||
{
|
||||
if (_useOther)
|
||||
{
|
||||
// Move the items from other allocation to the inlined storage
|
||||
Memory::MoveItems((T*)_data, _other.Get(), newCount);
|
||||
Memory::MoveItems(data, _other.Get(), newCount);
|
||||
|
||||
// Free the other allocation
|
||||
Memory::DestructItems(_other.Get(), oldCount);
|
||||
@@ -255,8 +257,8 @@ public:
|
||||
_useOther = true;
|
||||
|
||||
// Move the items from the inlined storage to the other allocation
|
||||
Memory::MoveItems(_other.Get(), (T*)_data, newCount);
|
||||
Memory::DestructItems((T*)_data, oldCount);
|
||||
Memory::MoveItems(_other.Get(), data, newCount);
|
||||
Memory::DestructItems(data, oldCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -277,4 +279,4 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
typedef HeapAllocation DefaultAllocation;
|
||||
using DefaultAllocation = HeapAllocation;
|
||||
|
||||
@@ -624,6 +624,8 @@ void NetworkManager::Stop()
|
||||
|
||||
State = NetworkConnectionState::Disconnected;
|
||||
Mode = NetworkManagerMode::Offline;
|
||||
LastUpdateTime = 0;
|
||||
|
||||
StateChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -1322,6 +1322,14 @@ void NetworkReplicator::MapObjectId(Guid& objectId)
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkReplicator::AddObjectIdMapping(const ScriptingObject* obj, const Guid& objectId)
|
||||
{
|
||||
CHECK(obj);
|
||||
const Guid id = obj->GetID();
|
||||
NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Remap object ID={} into object {}:{}", objectId, id.ToString(), obj->GetType().ToString());
|
||||
IdsRemappingTable[objectId] = id;
|
||||
}
|
||||
|
||||
ScriptingObject* NetworkReplicator::ResolveForeignObject(Guid objectId)
|
||||
{
|
||||
if (const auto& object = ResolveObject(objectId))
|
||||
|
||||
@@ -122,6 +122,13 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="objectId">The network object identifier to map. Contains result ID once the method completes.</param>
|
||||
API_FUNCTION() static void MapObjectId(API_PARAM(Ref) Guid& objectId);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new mapping for object identifier. Can be used to link locally-spawned object with across different clients.
|
||||
/// </summary>
|
||||
/// <param name="obj">The network object.</param>
|
||||
/// <param name="objectId">The network object identifier to use (eg. defined by server or global/static).</param>
|
||||
API_FUNCTION() static void AddObjectIdMapping(const ScriptingObject* obj, API_PARAM(Ref) const Guid& objectId);
|
||||
|
||||
/// <summary>
|
||||
/// Resolves foreign Guid into a local ScriptingObject
|
||||
|
||||
@@ -2801,7 +2801,14 @@ float PhysicsBackend::ComputeShapeSqrDistanceToPoint(void* shape, const Vector3&
|
||||
{
|
||||
auto shapePhysX = (PxShape*)shape;
|
||||
const PxTransform trans(C2P(position), C2P(orientation));
|
||||
#if USE_LARGE_WORLDS
|
||||
PxVec3 closestPointPx;
|
||||
float result = PxGeometryQuery::pointDistance(C2P(point), shapePhysX->getGeometry(), trans, &closestPointPx);
|
||||
*closestPoint = P2C(closestPointPx);
|
||||
return result;
|
||||
#else
|
||||
return PxGeometryQuery::pointDistance(C2P(point), shapePhysX->getGeometry(), trans, (PxVec3*)closestPoint);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool PhysicsBackend::RayCastShape(void* shape, const Vector3& position, const Quaternion& orientation, const Vector3& origin, const Vector3& direction, float& resultHitDistance, float maxDistance)
|
||||
@@ -3440,39 +3447,13 @@ PxVehicleAntiRollBarData CreatePxPxVehicleAntiRollBarData(const WheeledVehicle::
|
||||
return antiRollBar;
|
||||
}
|
||||
|
||||
bool SortWheelsFrontToBack(WheeledVehicle::Wheel const& a, WheeledVehicle::Wheel const& b)
|
||||
bool SortWheelsFrontToBack(WheeledVehicle::Wheel* const& a, WheeledVehicle::Wheel* const& b)
|
||||
{
|
||||
return a.Collider && b.Collider && a.Collider->GetLocalPosition().Z > b.Collider->GetLocalPosition().Z;
|
||||
return a->Collider && b->Collider && a->Collider->GetLocalPosition().Z > b->Collider->GetLocalPosition().Z;
|
||||
}
|
||||
|
||||
void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
|
||||
{
|
||||
// Physx vehicles needs to have all wheels sorted to apply controls correctly.
|
||||
// Its needs to know what wheels are on front to turn wheel to correctly side
|
||||
// and needs to know wheel side to apply throttle to correctly direction for each track when using tanks.
|
||||
// Anti roll bars needs to have all wheels sorted to get correctly wheel index too.
|
||||
if (actor->_driveType != WheeledVehicle::DriveTypes::NoDrive)
|
||||
{
|
||||
Sorting::QuickSort(actor->_wheels.Get(), actor->_wheels.Count(), SortWheelsFrontToBack);
|
||||
|
||||
// Sort wheels by side
|
||||
if (actor->_driveType == WheeledVehicle::DriveTypes::Tank)
|
||||
{
|
||||
for (int32 i = 0; i < actor->_wheels.Count() - 1; i += 2)
|
||||
{
|
||||
auto a = actor->_wheels[i];
|
||||
auto b = actor->_wheels[i + 1];
|
||||
if (!a.Collider || !b.Collider)
|
||||
continue;
|
||||
if (a.Collider->GetLocalPosition().X > b.Collider->GetLocalPosition().X)
|
||||
{
|
||||
actor->_wheels[i] = b;
|
||||
actor->_wheels[i + 1] = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get wheels
|
||||
Array<WheeledVehicle::Wheel*, FixedAllocation<PX_MAX_NB_WHEELS>> wheels;
|
||||
for (auto& wheel : actor->_wheels)
|
||||
@@ -3503,6 +3484,33 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor)
|
||||
// No woman, no cry
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Physx vehicles needs to have all wheels sorted to apply controls correctly.
|
||||
// Its needs to know what wheels are on front to turn wheel to correctly side
|
||||
// and needs to know wheel side to apply throttle to correctly direction for each track when using tanks.
|
||||
// Anti roll bars needs to have all wheels sorted to get correctly wheel index too.
|
||||
if (actor->_driveType != WheeledVehicle::DriveTypes::NoDrive)
|
||||
{
|
||||
Sorting::QuickSort(wheels.Get(), wheels.Count(), SortWheelsFrontToBack);
|
||||
|
||||
// Sort wheels by side
|
||||
if (actor->_driveType == WheeledVehicle::DriveTypes::Tank)
|
||||
{
|
||||
for (int32 i = 0; i < wheels.Count() - 1; i += 2)
|
||||
{
|
||||
auto a = wheels[i];
|
||||
auto b = wheels[i + 1];
|
||||
if (!a->Collider || !b->Collider)
|
||||
continue;
|
||||
if (a->Collider->GetLocalPosition().X > b->Collider->GetLocalPosition().X)
|
||||
{
|
||||
wheels[i] = b;
|
||||
wheels[i + 1] = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actor->_wheelsData.Resize(wheels.Count());
|
||||
auto actorPhysX = (PxRigidDynamic*)actor->GetPhysicsActor();
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ class RenderListBuffer
|
||||
{
|
||||
friend RenderListBuffer;
|
||||
public:
|
||||
typedef T ItemType;
|
||||
typedef typename AllocationType::template Data<T> AllocationData;
|
||||
using ItemType = T;
|
||||
using AllocationData = typename AllocationType::template Data<T>;
|
||||
|
||||
private:
|
||||
volatile int64 _count;
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
/// Initializes a new instance of the <see cref="RenderListBuffer"/> class.
|
||||
/// </summary>
|
||||
/// <param name="capacity">The initial capacity.</param>
|
||||
RenderListBuffer(int32 capacity)
|
||||
explicit RenderListBuffer(const int32 capacity)
|
||||
: _count(0)
|
||||
, _capacity(capacity)
|
||||
{
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="data">The initial data.</param>
|
||||
/// <param name="length">The amount of items.</param>
|
||||
RenderListBuffer(const T* data, int32 length)
|
||||
RenderListBuffer(const T* data, const int32 length)
|
||||
{
|
||||
ASSERT(length >= 0);
|
||||
_count = _capacity = length;
|
||||
@@ -76,7 +76,7 @@ public:
|
||||
if (_capacity > 0)
|
||||
{
|
||||
_allocation.Allocate(_capacity);
|
||||
Memory::ConstructItems(_allocation.Get(), other.Get(), (int32)other._count);
|
||||
Memory::ConstructItems(_allocation.Get(), other.Get(), static_cast<int32>(other._count));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
Memory::DestructItems(_allocation.Get(), (int32)_count);
|
||||
Memory::DestructItems(_allocation.Get(), static_cast<int32>(_count));
|
||||
if (_capacity < other.Count())
|
||||
{
|
||||
_allocation.Free();
|
||||
@@ -110,7 +110,7 @@ public:
|
||||
_allocation.Allocate(_capacity);
|
||||
}
|
||||
_count = other.Count();
|
||||
Memory::ConstructItems(_allocation.Get(), other.Get(), (int32)_count);
|
||||
Memory::ConstructItems(_allocation.Get(), other.Get(), static_cast<int32>(_count));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -124,7 +124,7 @@ public:
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
Memory::DestructItems(_allocation.Get(), (int32)_count);
|
||||
Memory::DestructItems(_allocation.Get(), static_cast<int32>(_count));
|
||||
_allocation.Free();
|
||||
_count = other._count;
|
||||
_capacity = other._capacity;
|
||||
@@ -140,7 +140,7 @@ public:
|
||||
/// </summary>
|
||||
~RenderListBuffer()
|
||||
{
|
||||
Memory::DestructItems(_allocation.Get(), (int32)_count);
|
||||
Memory::DestructItems(_allocation.Get(), static_cast<int32>(_count));
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -149,7 +149,7 @@ public:
|
||||
/// </summary>
|
||||
FORCE_INLINE int32 Count() const
|
||||
{
|
||||
return (int32)Platform::AtomicRead((volatile int64*)&_count);
|
||||
return static_cast<int32>(Platform::AtomicRead((volatile int64*)&_count));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -157,7 +157,7 @@ public:
|
||||
/// </summary>
|
||||
FORCE_INLINE int32 Capacity() const
|
||||
{
|
||||
return (int32)Platform::AtomicRead((volatile int64*)&_capacity);
|
||||
return static_cast<int32>(Platform::AtomicRead((volatile int64*)&_capacity));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -188,7 +188,7 @@ public:
|
||||
/// Gets or sets the item at the given index.
|
||||
/// </summary>
|
||||
/// <returns>The reference to the item.</returns>
|
||||
FORCE_INLINE T& operator[](int32 index)
|
||||
FORCE_INLINE T& operator[](const int32 index)
|
||||
{
|
||||
ASSERT(index >= 0 && index < Count());
|
||||
return _allocation.Get()[index];
|
||||
@@ -198,7 +198,7 @@ public:
|
||||
/// Gets the item at the given index.
|
||||
/// </summary>
|
||||
/// <returns>The reference to the item.</returns>
|
||||
FORCE_INLINE const T& operator[](int32 index) const
|
||||
FORCE_INLINE const T& operator[](const int32 index) const
|
||||
{
|
||||
ASSERT(index >= 0 && index < Count());
|
||||
return _allocation.Get()[index];
|
||||
@@ -232,7 +232,7 @@ public:
|
||||
void Clear()
|
||||
{
|
||||
_locker.Lock();
|
||||
Memory::DestructItems(_allocation.Get(), (int32)_count);
|
||||
Memory::DestructItems(_allocation.Get(), static_cast<int32>(_count));
|
||||
_count = 0;
|
||||
_locker.Unlock();
|
||||
}
|
||||
@@ -242,14 +242,14 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="capacity">The new capacity.</param>
|
||||
/// <param name="preserveContents">True if preserve collection data when changing its size, otherwise collection after resize will be empty.</param>
|
||||
void SetCapacity(const int32 capacity, bool preserveContents = true)
|
||||
void SetCapacity(const int32 capacity, const bool preserveContents = true)
|
||||
{
|
||||
if (capacity == Capacity())
|
||||
return;
|
||||
_locker.Lock();
|
||||
ASSERT(capacity >= 0);
|
||||
const int32 count = preserveContents ? ((int32)_count < capacity ? (int32)_count : capacity) : 0;
|
||||
_allocation.Relocate(capacity, (int32)_count, count);
|
||||
const int32 count = preserveContents ? (static_cast<int32>(_count) < capacity ? static_cast<int32>(_count) : capacity) : 0;
|
||||
_allocation.Relocate(capacity, static_cast<int32>(_count), count);
|
||||
Platform::AtomicStore(&_capacity, capacity);
|
||||
Platform::AtomicStore(&_count, count);
|
||||
_locker.Unlock();
|
||||
@@ -260,17 +260,17 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="size">The new collection size.</param>
|
||||
/// <param name="preserveContents">True if preserve collection data when changing its size, otherwise collection after resize might not contain the previous data.</param>
|
||||
void Resize(int32 size, bool preserveContents = true)
|
||||
void Resize(const int32 size, const bool preserveContents = true)
|
||||
{
|
||||
_locker.Lock();
|
||||
if (_count > size)
|
||||
{
|
||||
Memory::DestructItems(_allocation.Get() + size, (int32)_count - size);
|
||||
Memory::DestructItems(_allocation.Get() + size, static_cast<int32>(_count) - size);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnsureCapacity(size, preserveContents);
|
||||
Memory::ConstructItems(_allocation.Get() + _count, size - (int32)_count);
|
||||
Memory::ConstructItems(_allocation.Get() + _count, size - static_cast<int32>(_count));
|
||||
}
|
||||
_count = size;
|
||||
_locker.Unlock();
|
||||
@@ -280,14 +280,14 @@ public:
|
||||
/// Ensures the collection has given capacity (or more).
|
||||
/// </summary>
|
||||
/// <param name="minCapacity">The minimum capacity.</param>
|
||||
void EnsureCapacity(int32 minCapacity)
|
||||
void EnsureCapacity(const int32 minCapacity)
|
||||
{
|
||||
_locker.Lock();
|
||||
int32 capacity = (int32)Platform::AtomicRead(&_capacity);
|
||||
int32 capacity = static_cast<int32>(Platform::AtomicRead(&_capacity));
|
||||
if (capacity < minCapacity)
|
||||
{
|
||||
capacity = _allocation.CalculateCapacityGrow(capacity, minCapacity);
|
||||
const int32 count = (int32)_count;
|
||||
const int32 count = static_cast<int32>(_count);
|
||||
_allocation.Relocate(capacity, count, count);
|
||||
Platform::AtomicStore(&_capacity, capacity);
|
||||
}
|
||||
@@ -324,8 +324,8 @@ private:
|
||||
int32 AddOne()
|
||||
{
|
||||
Platform::InterlockedIncrement(&_threadsAdding);
|
||||
int32 count = (int32)Platform::AtomicRead(&_count);
|
||||
int32 capacity = (int32)Platform::AtomicRead(&_capacity);
|
||||
int32 count = static_cast<int32>(Platform::AtomicRead(&_count));
|
||||
int32 capacity = static_cast<int32>(Platform::AtomicRead(&_capacity));
|
||||
const int32 minCapacity = GetMinCapacity(count);
|
||||
if (minCapacity > capacity || Platform::AtomicRead(&_threadsResizing)) // Resize if not enough space or someone else is already doing it (don't add mid-resizing)
|
||||
{
|
||||
@@ -340,7 +340,7 @@ private:
|
||||
|
||||
// Thread-safe resizing
|
||||
_locker.Lock();
|
||||
capacity = (int32)Platform::AtomicRead(&_capacity);
|
||||
capacity = static_cast<int32>(Platform::AtomicRead(&_capacity));
|
||||
if (capacity < minCapacity)
|
||||
{
|
||||
if (Platform::AtomicRead(&_threadsAdding))
|
||||
@@ -350,7 +350,7 @@ private:
|
||||
goto RETRY;
|
||||
}
|
||||
capacity = _allocation.CalculateCapacityGrow(capacity, minCapacity);
|
||||
count = (int32)Platform::AtomicRead(&_count);
|
||||
count = static_cast<int32>(Platform::AtomicRead(&_count));
|
||||
_allocation.Relocate(capacity, count, count);
|
||||
Platform::AtomicStore(&_capacity, capacity);
|
||||
}
|
||||
@@ -362,10 +362,10 @@ private:
|
||||
// Let other thread enter resizing-area
|
||||
_locker.Unlock();
|
||||
}
|
||||
return (int32)Platform::InterlockedIncrement(&_count) - 1;
|
||||
return static_cast<int32>(Platform::InterlockedIncrement(&_count)) - 1;
|
||||
}
|
||||
|
||||
FORCE_INLINE static int32 GetMinCapacity(int32 count)
|
||||
FORCE_INLINE static int32 GetMinCapacity(const int32 count)
|
||||
{
|
||||
// Ensure there is a slack for others threads to reduce resize counts in highly multi-threaded environment
|
||||
constexpr int32 slack = PLATFORM_THREADS_LIMIT * 8;
|
||||
|
||||
@@ -172,6 +172,15 @@ public:
|
||||
return str.Length();
|
||||
}
|
||||
|
||||
// Test trailing return type
|
||||
API_FUNCTION() auto TestTrailingReturn(int32 number) -> float
|
||||
{
|
||||
return static_cast<float>(number);
|
||||
}
|
||||
|
||||
// Test nameless arguments
|
||||
API_FUNCTION() void TestNamelessArguments(int32, float, bool){}
|
||||
|
||||
int32 TestInterfaceMethod(const String& str) override
|
||||
{
|
||||
return str.Length();
|
||||
|
||||
@@ -99,8 +99,8 @@ namespace FlaxEngine.GUI
|
||||
private float _scale = 1.0f;
|
||||
private float _scaleFactor = 1.0f;
|
||||
private float _physicalUnitSize = 1.0f;
|
||||
private Float2 _resolutionMin = new Float2(640, 480);
|
||||
private Float2 _resolutionMax = new Float2(7680, 4320);
|
||||
private Float2 _resolutionMin = new Float2(1f, 1f);
|
||||
private Float2 _resolutionMax = new Float2(7680f, 4320f);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current UI scale. Computed based on the setup when performing layout.
|
||||
@@ -246,10 +246,11 @@ namespace FlaxEngine.GUI
|
||||
#endif
|
||||
public LinearCurve<float> ResolutionCurve = new LinearCurve<float>(new[]
|
||||
{
|
||||
new LinearCurve<float>.Keyframe(480, 0.444f), // 480p
|
||||
new LinearCurve<float>.Keyframe(720, 0.666f), // 720p
|
||||
new LinearCurve<float>.Keyframe(1080, 1.0f), // 1080p
|
||||
new LinearCurve<float>.Keyframe(8640, 8.0f), // 8640p
|
||||
new LinearCurve<float>.Keyframe(0f, 0f), // 0p
|
||||
new LinearCurve<float>.Keyframe(480f, 0.444f), // 480p
|
||||
new LinearCurve<float>.Keyframe(720f, 0.666f), // 720p
|
||||
new LinearCurve<float>.Keyframe(1080f, 1.0f), // 1080p
|
||||
new LinearCurve<float>.Keyframe(8640f, 8.0f), // 8640p
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
@@ -335,7 +336,7 @@ namespace FlaxEngine.GUI
|
||||
scale = min / value;
|
||||
else if (value > max)
|
||||
scale = max / value;
|
||||
if (ResolutionCurve != null && ResolutionCurve.Keyframes?.Length != 0)
|
||||
if (ResolutionCurve != null && ResolutionCurve.Keyframes?.Length != 0f)
|
||||
{
|
||||
ResolutionCurve.Evaluate(out var curveScale, value, false);
|
||||
scale *= curveScale;
|
||||
@@ -364,13 +365,13 @@ namespace FlaxEngine.GUI
|
||||
dpi = 25.4f;
|
||||
break;
|
||||
case PhysicalUnitMode.Inches:
|
||||
dpi = 1;
|
||||
dpi = 1f;
|
||||
break;
|
||||
case PhysicalUnitMode.Points:
|
||||
dpi = 72;
|
||||
dpi = 72f;
|
||||
break;
|
||||
case PhysicalUnitMode.Picas:
|
||||
dpi = 6;
|
||||
dpi = 6f;
|
||||
break;
|
||||
}
|
||||
return dpi;
|
||||
|
||||
BIN
Source/Platforms/DotNet/Microsoft.VisualStudio.Setup.Configuration.Interop.dll
(Stored with Git LFS)
BIN
Source/Platforms/DotNet/Microsoft.VisualStudio.Setup.Configuration.Interop.dll
(Stored with Git LFS)
Binary file not shown.
@@ -390,7 +390,22 @@ namespace Flax.Build.Bindings
|
||||
|
||||
// Read parameter type and name
|
||||
currentParam.Type = ParseType(ref context);
|
||||
currentParam.Name = context.Tokenizer.ExpectToken(TokenType.Identifier).Value;
|
||||
token = context.Tokenizer.NextToken();
|
||||
if (token.Type == TokenType.Identifier)
|
||||
{
|
||||
currentParam.Name = token.Value;
|
||||
}
|
||||
// Support nameless arguments. assume optional usage
|
||||
else
|
||||
{
|
||||
context.Tokenizer.PreviousToken();
|
||||
if (string.IsNullOrEmpty(currentParam.Attributes))
|
||||
currentParam.Attributes = "Optional";
|
||||
else
|
||||
currentParam.Attributes += ", Optional";
|
||||
currentParam.Name = $"namelessArg{parameters.Count}";
|
||||
}
|
||||
|
||||
if (currentParam.IsOut && (currentParam.Type.IsPtr || currentParam.Type.IsRef) && currentParam.Type.Type.EndsWith("*"))
|
||||
{
|
||||
// Pointer to value passed as output pointer
|
||||
@@ -831,6 +846,7 @@ namespace Flax.Build.Bindings
|
||||
}
|
||||
|
||||
// Read return type
|
||||
// Handle if "auto" later
|
||||
desc.ReturnType = ParseType(ref context);
|
||||
|
||||
// Read name
|
||||
@@ -841,15 +857,21 @@ namespace Flax.Build.Bindings
|
||||
// Read parameters
|
||||
desc.Parameters.AddRange(ParseFunctionParameters(ref context));
|
||||
|
||||
// Read ';' or 'const' or 'override' or '= 0' or '{'
|
||||
// Read ';' or 'const' or 'override' or '= 0' or '{' or '-'
|
||||
while (true)
|
||||
{
|
||||
var token = context.Tokenizer.ExpectAnyTokens(new[] { TokenType.SemiColon, TokenType.LeftCurlyBrace, TokenType.Equal, TokenType.Identifier });
|
||||
var token = context.Tokenizer.ExpectAnyTokens(new[] { TokenType.SemiColon, TokenType.LeftCurlyBrace, TokenType.Equal, TokenType.Sub, TokenType.Identifier });
|
||||
if (token.Type == TokenType.Equal)
|
||||
{
|
||||
context.Tokenizer.SkipUntil(TokenType.SemiColon);
|
||||
break;
|
||||
}
|
||||
// Support auto FunctionName() -> Type
|
||||
else if (token.Type == TokenType.Sub && desc.ReturnType.ToString() == "auto")
|
||||
{
|
||||
context.Tokenizer.SkipUntil(TokenType.GreaterThan);
|
||||
desc.ReturnType = ParseType(ref context);
|
||||
}
|
||||
else if (token.Type == TokenType.Identifier)
|
||||
{
|
||||
switch (token.Value)
|
||||
|
||||
@@ -335,6 +335,12 @@ namespace Flax.Build
|
||||
var referenceTargets = GetProjectTargets(reference.Project);
|
||||
foreach (var referenceTarget in referenceTargets)
|
||||
{
|
||||
// Skip referenced targets that don't meet this configuration specs (eg. Editor target should skip Android platform)
|
||||
if (!referenceTarget.Platforms.Contains(configurationData.Platform))
|
||||
continue;
|
||||
if (!referenceTarget.Architectures.Contains(configurationData.Architecture))
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
var referenceBuildOptions = GetBuildOptions(referenceTarget, configurationData.TargetBuildOptions.Platform, configurationData.TargetBuildOptions.Toolchain, configurationData.Architecture, configurationData.Configuration, reference.Project.ProjectFolderPath);
|
||||
|
||||
@@ -143,6 +143,7 @@ namespace Flax.Build.Projects.VisualStudioCode
|
||||
var buildToolWorkspace = Environment.CurrentDirectory;
|
||||
var buildToolPath = Path.ChangeExtension(Utilities.MakePathRelativeTo(typeof(Builder).Assembly.Location, solution.WorkspaceRootPath), null);
|
||||
var rules = Builder.GenerateRulesAssembly();
|
||||
var mainProject = solution.MainProject ?? solution.Projects.FirstOrDefault(x => x.Name == Globals.Project.Name);
|
||||
|
||||
// Create tasks file
|
||||
using (var json = new JsonWriter())
|
||||
@@ -159,10 +160,10 @@ namespace Flax.Build.Projects.VisualStudioCode
|
||||
continue;
|
||||
|
||||
// Skip duplicate build tasks
|
||||
if (project.Name == "FlaxEngine" || (solution.MainProject.Name != "Flax" && solution.MainProject != project))
|
||||
if (project.Name == "FlaxEngine" || (mainProject != null && mainProject.Name != "Flax" && mainProject != project))
|
||||
continue;
|
||||
|
||||
bool defaultTask = project == solution.MainProject;
|
||||
bool defaultTask = project == mainProject;
|
||||
foreach (var configuration in project.Configurations)
|
||||
{
|
||||
var target = configuration.Target;
|
||||
@@ -301,7 +302,7 @@ namespace Flax.Build.Projects.VisualStudioCode
|
||||
json.BeginArray("configurations");
|
||||
{
|
||||
var cppProject = solution.Projects.FirstOrDefault(x => x.BaseName == solution.Name || x.Name == solution.Name);
|
||||
var mainProjectModule = solution.MainProject?.Targets.Length != 0 ? solution.MainProject.Targets[0].Modules[0] : null;
|
||||
var mainProjectModule = mainProject != null && mainProject.Targets?.Length != 0 ? mainProject.Targets[0]?.Modules[0] : null;
|
||||
var csharpProject = mainProjectModule != null ? solution.Projects.FirstOrDefault(x => x.BaseName == mainProjectModule || x.Name == mainProjectModule) : null;
|
||||
|
||||
if (cppProject != null)
|
||||
@@ -533,10 +534,9 @@ namespace Flax.Build.Projects.VisualStudioCode
|
||||
json.BeginRootObject();
|
||||
json.BeginArray("configurations");
|
||||
json.BeginObject();
|
||||
var project = solution.MainProject ?? solution.Projects.FirstOrDefault(x => x.Name == Globals.Project.Name);
|
||||
if (project != null)
|
||||
if (mainProject != null)
|
||||
{
|
||||
json.AddField("name", project.Name);
|
||||
json.AddField("name", mainProject.Name);
|
||||
|
||||
var targetPlatform = Platform.BuildPlatform.Target;
|
||||
var configuration = TargetConfiguration.Development;
|
||||
@@ -544,10 +544,10 @@ namespace Flax.Build.Projects.VisualStudioCode
|
||||
|
||||
var includePaths = new HashSet<string>();
|
||||
var preprocessorDefinitions = new HashSet<string>();
|
||||
foreach (var e in project.Defines)
|
||||
foreach (var e in mainProject.Defines)
|
||||
preprocessorDefinitions.Add(e);
|
||||
|
||||
foreach (var target in project.Targets)
|
||||
foreach (var target in mainProject.Targets)
|
||||
{
|
||||
var platform = Platform.GetPlatform(targetPlatform);
|
||||
if (platform.HasRequiredSDKsInstalled && target.Platforms.Contains(targetPlatform))
|
||||
|
||||
Reference in New Issue
Block a user