Merge remote-tracking branch 'origin/master' into visject_grid_snap
This commit is contained in:
@@ -36,7 +36,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
return;
|
return;
|
||||||
var gizmos = gizmoOwner.Gizmos;
|
var gizmos = gizmoOwner.Gizmos;
|
||||||
_gizmoMode = new ClothPaintingGizmoMode();
|
_gizmoMode = new ClothPaintingGizmoMode();
|
||||||
|
|
||||||
var projectCache = Editor.Instance.ProjectCache;
|
var projectCache = Editor.Instance.ProjectCache;
|
||||||
if (projectCache.TryGetCustomData("ClothGizmoPaintValue", out var cachedPaintValue))
|
if (projectCache.TryGetCustomData("ClothGizmoPaintValue", out var cachedPaintValue))
|
||||||
_gizmoMode.PaintValue = JsonSerializer.Deserialize<float>(cachedPaintValue);
|
_gizmoMode.PaintValue = JsonSerializer.Deserialize<float>(cachedPaintValue);
|
||||||
@@ -48,7 +48,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
_gizmoMode.BrushSize = JsonSerializer.Deserialize<float>(cachedBrushSize);
|
_gizmoMode.BrushSize = JsonSerializer.Deserialize<float>(cachedBrushSize);
|
||||||
if (projectCache.TryGetCustomData("ClothGizmoBrushStrength", out var cachedBrushStrength))
|
if (projectCache.TryGetCustomData("ClothGizmoBrushStrength", out var cachedBrushStrength))
|
||||||
_gizmoMode.BrushStrength = JsonSerializer.Deserialize<float>(cachedBrushStrength);
|
_gizmoMode.BrushStrength = JsonSerializer.Deserialize<float>(cachedBrushStrength);
|
||||||
|
|
||||||
gizmos.AddMode(_gizmoMode);
|
gizmos.AddMode(_gizmoMode);
|
||||||
_prevMode = gizmos.ActiveMode;
|
_prevMode = gizmos.ActiveMode;
|
||||||
gizmos.ActiveMode = _gizmoMode;
|
gizmos.ActiveMode = _gizmoMode;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace FlaxEditor.CustomEditors.Elements
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// [Deprecated on 26.05.2022, expires on 26.05.2024]
|
/// [Deprecated on 26.05.2022, expires on 26.05.2024]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[System.Obsolete("Deprecated in 1.4")]
|
[System.Obsolete("Deprecated in 1.4, use ValueBox instead")]
|
||||||
public DoubleValueBox DoubleValue => ValueBox;
|
public DoubleValueBox DoubleValue => ValueBox;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace FlaxEditor.CustomEditors.Elements
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// [Deprecated on 26.05.2022, expires on 26.05.2024]
|
/// [Deprecated on 26.05.2022, expires on 26.05.2024]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[System.Obsolete("Deprecated in 1.4, ValueBox instead")]
|
[System.Obsolete("Deprecated in 1.4, use ValueBox instead")]
|
||||||
public FloatValueBox FloatValue => ValueBox;
|
public FloatValueBox FloatValue => ValueBox;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -364,7 +364,7 @@ namespace FlaxEditor
|
|||||||
{
|
{
|
||||||
foreach (var preview in activePreviews)
|
foreach (var preview in activePreviews)
|
||||||
{
|
{
|
||||||
if (preview == loadingPreview ||
|
if (preview == loadingPreview ||
|
||||||
(preview.Instance != null && (preview.Instance == control || preview.Instance.HasActorInHierarchy(control))))
|
(preview.Instance != null && (preview.Instance == control || preview.Instance.HasActorInHierarchy(control))))
|
||||||
{
|
{
|
||||||
// Link it to the prefab preview to see it in the editor
|
// Link it to the prefab preview to see it in the editor
|
||||||
|
|||||||
@@ -482,8 +482,8 @@ namespace FlaxEditor.GUI
|
|||||||
Focus();
|
Focus();
|
||||||
});
|
});
|
||||||
if (_selected != null)
|
if (_selected != null)
|
||||||
{
|
{
|
||||||
var selectedAssetName = Path.GetFileNameWithoutExtension(_selected.Path);
|
var selectedAssetName = Path.GetFileNameWithoutExtension(_selected.Path);
|
||||||
popup.ScrollToAndHighlightItemByName(selectedAssetName);
|
popup.ScrollToAndHighlightItemByName(selectedAssetName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
// Hide parent CM popups and set itself as child
|
// Hide parent CM popups and set itself as child
|
||||||
parentContextMenu.ShowChild(ContextMenu, PointToParent(ParentContextMenu, new Float2(Width, 0)));
|
parentContextMenu.ShowChild(ContextMenu, PointToParent(ParentContextMenu, new Float2(Width, 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool OnMouseUp(Float2 location, MouseButton button)
|
public override bool OnMouseUp(Float2 location, MouseButton button)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -293,7 +293,7 @@ namespace FlaxEditor.GUI.Dialogs
|
|||||||
if (Root != null)
|
if (Root != null)
|
||||||
{
|
{
|
||||||
bool shiftDown = Root.GetKey(KeyboardKeys.Shift);
|
bool shiftDown = Root.GetKey(KeyboardKeys.Shift);
|
||||||
Root.Navigate(shiftDown ? NavDirection.Previous : NavDirection.Next);
|
Root.Navigate(shiftDown ? NavDirection.Previous : NavDirection.Next);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace FlaxEditor.GUI.Input
|
|||||||
: this(false, 0, 0)
|
: this(false, 0, 0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Init search box
|
/// Init search box
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -28,7 +28,7 @@ namespace FlaxEditor.GUI.Input
|
|||||||
: base(isMultiline, x, y, width)
|
: base(isMultiline, x, y, width)
|
||||||
{
|
{
|
||||||
WatermarkText = "Search...";
|
WatermarkText = "Search...";
|
||||||
|
|
||||||
ClearSearchButton = new Button
|
ClearSearchButton = new Button
|
||||||
{
|
{
|
||||||
Parent = this,
|
Parent = this,
|
||||||
|
|||||||
@@ -182,6 +182,7 @@ namespace FlaxEditor.GUI.Input
|
|||||||
}
|
}
|
||||||
SlidingEnd?.Invoke();
|
SlidingEnd?.Invoke();
|
||||||
Defocus();
|
Defocus();
|
||||||
|
Parent?.Focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ namespace FlaxEditor.GUI
|
|||||||
{
|
{
|
||||||
DoubleClick?.Invoke();
|
DoubleClick?.Invoke();
|
||||||
RowDoubleClick?.Invoke(this);
|
RowDoubleClick?.Invoke(this);
|
||||||
|
|
||||||
return base.OnMouseDoubleClick(location, button);
|
return base.OnMouseDoubleClick(location, button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ namespace FlaxEditor.Modules
|
|||||||
hint = "Too long name.";
|
hint = "Too long name.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.IsFolder && shortName.EndsWith("."))
|
if (item.IsFolder && shortName.EndsWith("."))
|
||||||
{
|
{
|
||||||
hint = "Name cannot end with '.'";
|
hint = "Name cannot end with '.'";
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ namespace FlaxEditor.Modules
|
|||||||
return;
|
return;
|
||||||
var actorsList = new List<Actor>();
|
var actorsList = new List<Actor>();
|
||||||
Utilities.Utils.GetActorsTree(actorsList, actor);
|
Utilities.Utils.GetActorsTree(actorsList, actor);
|
||||||
|
|
||||||
var actions = new IUndoAction[actorsList.Count];
|
var actions = new IUndoAction[actorsList.Count];
|
||||||
for (int i = 0; i < actorsList.Count; i++)
|
for (int i = 0; i < actorsList.Count; i++)
|
||||||
actions[i] = BreakPrefabLinkAction.Linked(actorsList[i]);
|
actions[i] = BreakPrefabLinkAction.Linked(actorsList[i]);
|
||||||
|
|||||||
@@ -453,7 +453,7 @@ namespace FlaxEditor.Modules
|
|||||||
{
|
{
|
||||||
Editor.Windows.SceneWin.Focus();
|
Editor.Windows.SceneWin.Focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// fix scene window layout
|
// fix scene window layout
|
||||||
Editor.Windows.SceneWin.PerformLayout();
|
Editor.Windows.SceneWin.PerformLayout();
|
||||||
Editor.Windows.SceneWin.PerformLayout();
|
Editor.Windows.SceneWin.PerformLayout();
|
||||||
@@ -520,7 +520,7 @@ namespace FlaxEditor.Modules
|
|||||||
Undo.AddAction(new MultiUndoAction(pasteAction, selectAction));
|
Undo.AddAction(new MultiUndoAction(pasteAction, selectAction));
|
||||||
OnSelectionChanged();
|
OnSelectionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scroll to new selected node while pasting
|
// Scroll to new selected node while pasting
|
||||||
Editor.Windows.SceneWin.ScrollToSelectedNode();
|
Editor.Windows.SceneWin.ScrollToSelectedNode();
|
||||||
}
|
}
|
||||||
@@ -620,7 +620,7 @@ namespace FlaxEditor.Modules
|
|||||||
Undo.AddAction(new MultiUndoAction(undoActions));
|
Undo.AddAction(new MultiUndoAction(undoActions));
|
||||||
OnSelectionChanged();
|
OnSelectionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scroll to new selected node while duplicating
|
// Scroll to new selected node while duplicating
|
||||||
Editor.Windows.SceneWin.ScrollToSelectedNode();
|
Editor.Windows.SceneWin.ScrollToSelectedNode();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -332,7 +332,7 @@ namespace FlaxEditor.Modules
|
|||||||
continue;
|
continue;
|
||||||
scenes.Add(s);
|
scenes.Add(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
// In play-mode Editor mocks the level streaming script
|
// In play-mode Editor mocks the level streaming script
|
||||||
if (Editor.IsPlayMode)
|
if (Editor.IsPlayMode)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ namespace FlaxEditor.Modules.SourceCodeEditing
|
|||||||
|
|
||||||
private static bool CheckFunc(ScriptType scriptType)
|
private static bool CheckFunc(ScriptType scriptType)
|
||||||
{
|
{
|
||||||
if (scriptType.IsStatic ||
|
if (scriptType.IsStatic ||
|
||||||
scriptType.IsGenericType ||
|
scriptType.IsGenericType ||
|
||||||
!scriptType.IsPublic ||
|
!scriptType.IsPublic ||
|
||||||
scriptType.HasAttribute(typeof(HideInEditorAttribute), true) ||
|
scriptType.HasAttribute(typeof(HideInEditorAttribute), true) ||
|
||||||
scriptType.HasAttribute(typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute), false))
|
scriptType.HasAttribute(typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute), false))
|
||||||
return false;
|
return false;
|
||||||
var managedType = TypeUtils.GetType(scriptType);
|
var managedType = TypeUtils.GetType(scriptType);
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ namespace FlaxEditor.Modules
|
|||||||
else
|
else
|
||||||
text = "Ready";
|
text = "Ready";
|
||||||
|
|
||||||
if(ProgressVisible)
|
if (ProgressVisible)
|
||||||
{
|
{
|
||||||
color = Style.Current.Statusbar.Loading;
|
color = Style.Current.Statusbar.Loading;
|
||||||
}
|
}
|
||||||
@@ -402,7 +402,7 @@ namespace FlaxEditor.Modules
|
|||||||
{
|
{
|
||||||
UpdateStatusBar();
|
UpdateStatusBar();
|
||||||
}
|
}
|
||||||
else if(ProgressVisible)
|
else if (ProgressVisible)
|
||||||
{
|
{
|
||||||
UpdateStatusBar();
|
UpdateStatusBar();
|
||||||
}
|
}
|
||||||
@@ -557,7 +557,7 @@ namespace FlaxEditor.Modules
|
|||||||
cm.AddButton("Game Settings", () =>
|
cm.AddButton("Game Settings", () =>
|
||||||
{
|
{
|
||||||
var item = Editor.ContentDatabase.Find(GameSettings.GameSettingsAssetPath);
|
var item = Editor.ContentDatabase.Find(GameSettings.GameSettingsAssetPath);
|
||||||
if(item != null)
|
if (item != null)
|
||||||
Editor.ContentEditing.Open(item);
|
Editor.ContentEditing.Open(item);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace FlaxEditor.Progress
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handler">The calling handler.</param>
|
/// <param name="handler">The calling handler.</param>
|
||||||
public delegate void ProgressDelegate(ProgressHandler handler);
|
public delegate void ProgressDelegate(ProgressHandler handler);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Progress failed handler event delegate
|
/// Progress failed handler event delegate
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -127,7 +127,7 @@ namespace FlaxEditor.Progress
|
|||||||
{
|
{
|
||||||
if (!_isActive)
|
if (!_isActive)
|
||||||
throw new InvalidOperationException("Already ended.");
|
throw new InvalidOperationException("Already ended.");
|
||||||
|
|
||||||
_isActive = false;
|
_isActive = false;
|
||||||
_progress = 0;
|
_progress = 0;
|
||||||
_infoText = string.Empty;
|
_infoText = string.Empty;
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
/// <seealso cref="FlaxEditor.Surface.SurfaceNode" />
|
/// <seealso cref="FlaxEditor.Surface.SurfaceNode" />
|
||||||
public class Sample : SurfaceNode
|
public class Sample : SurfaceNode
|
||||||
{
|
{
|
||||||
|
private AssetSelect _assetSelect;
|
||||||
|
private Box _assetBox;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Sample(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch)
|
public Sample(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch)
|
||||||
: base(id, context, nodeArch, groupArch)
|
: base(id, context, nodeArch, groupArch)
|
||||||
@@ -54,16 +57,42 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
base.OnSurfaceLoaded(action);
|
base.OnSurfaceLoaded(action);
|
||||||
|
|
||||||
if (Surface != null)
|
if (Surface != null)
|
||||||
|
{
|
||||||
|
_assetSelect = GetChild<AssetSelect>();
|
||||||
|
if (TryGetBox(8, out var box))
|
||||||
|
{
|
||||||
|
_assetBox = box;
|
||||||
|
_assetSelect.Visible = !_assetBox.HasAnyConnection;
|
||||||
|
}
|
||||||
UpdateTitle();
|
UpdateTitle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateTitle()
|
private void UpdateTitle()
|
||||||
{
|
{
|
||||||
var asset = Editor.Instance.ContentDatabase.Find((Guid)Values[0]);
|
var asset = Editor.Instance.ContentDatabase.Find((Guid)Values[0]);
|
||||||
Title = asset?.ShortName ?? "Animation";
|
if (_assetBox != null)
|
||||||
|
Title = _assetBox.HasAnyConnection || asset == null ? "Animation" : asset.ShortName;
|
||||||
|
else
|
||||||
|
Title = asset?.ShortName ?? "Animation";
|
||||||
|
|
||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
Resize(Mathf.Max(230, style.FontLarge.MeasureText(Title).X + 30), 160);
|
Resize(Mathf.Max(230, style.FontLarge.MeasureText(Title).X + 30), 160);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void ConnectionTick(Box box)
|
||||||
|
{
|
||||||
|
base.ConnectionTick(box);
|
||||||
|
|
||||||
|
if (_assetBox == null)
|
||||||
|
return;
|
||||||
|
if (box.ID != _assetBox.ID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_assetSelect.Visible = !box.HasAnyConnection;
|
||||||
|
UpdateTitle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -305,7 +334,8 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
NodeElementArchetype.Factory.Input(0, "Speed", true, typeof(float), 5, 1),
|
NodeElementArchetype.Factory.Input(0, "Speed", true, typeof(float), 5, 1),
|
||||||
NodeElementArchetype.Factory.Input(1, "Loop", true, typeof(bool), 6, 2),
|
NodeElementArchetype.Factory.Input(1, "Loop", true, typeof(bool), 6, 2),
|
||||||
NodeElementArchetype.Factory.Input(2, "Start Position", true, typeof(float), 7, 3),
|
NodeElementArchetype.Factory.Input(2, "Start Position", true, typeof(float), 7, 3),
|
||||||
NodeElementArchetype.Factory.Asset(0, Surface.Constants.LayoutOffsetY * 3, 0, typeof(FlaxEngine.Animation)),
|
NodeElementArchetype.Factory.Input(3, "Animation Asset", true, typeof(FlaxEngine.Animation), 8),
|
||||||
|
NodeElementArchetype.Factory.Asset(0, Surface.Constants.LayoutOffsetY * 4, 0, typeof(FlaxEngine.Animation)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new NodeArchetype
|
new NodeArchetype
|
||||||
|
|||||||
@@ -510,7 +510,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
|
|
||||||
for (var i = 0; i < elements.Length; i++)
|
for (var i = 0; i < elements.Length; i++)
|
||||||
{
|
{
|
||||||
if(elements[i].Type != NodeElementType.Output)
|
if (elements[i].Type != NodeElementType.Output)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (VisjectSurface.FullCastCheck(elements[i].ConnectionsType, inputType, hint))
|
if (VisjectSurface.FullCastCheck(elements[i].ConnectionsType, inputType, hint))
|
||||||
@@ -533,7 +533,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
|
|
||||||
for (var i = 0; i < elements.Length; i++)
|
for (var i = 0; i < elements.Length; i++)
|
||||||
{
|
{
|
||||||
if(elements[i].Type != NodeElementType.Input)
|
if (elements[i].Type != NodeElementType.Input)
|
||||||
continue;
|
continue;
|
||||||
if (VisjectSurface.FullCastCheck(elements[i].ConnectionsType, outputType, hint))
|
if (VisjectSurface.FullCastCheck(elements[i].ConnectionsType, outputType, hint))
|
||||||
return true;
|
return true;
|
||||||
@@ -725,7 +725,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override bool UseNormalMaps => false;
|
protected override bool UseNormalMaps => false;
|
||||||
|
|
||||||
internal new static bool IsOutputCompatible(NodeArchetype nodeArch, ScriptType inputType, ConnectionsHint hint, VisjectSurfaceContext context)
|
internal new static bool IsOutputCompatible(NodeArchetype nodeArch, ScriptType inputType, ConnectionsHint hint, VisjectSurfaceContext context)
|
||||||
{
|
{
|
||||||
if (inputType == ScriptType.Object)
|
if (inputType == ScriptType.Object)
|
||||||
@@ -743,7 +743,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
|
|
||||||
for (var i = 0; i < elements.Length; i++)
|
for (var i = 0; i < elements.Length; i++)
|
||||||
{
|
{
|
||||||
if(elements[i].Type != NodeElementType.Output)
|
if (elements[i].Type != NodeElementType.Output)
|
||||||
continue;
|
continue;
|
||||||
if (VisjectSurface.FullCastCheck(elements[i].ConnectionsType, inputType, hint))
|
if (VisjectSurface.FullCastCheck(elements[i].ConnectionsType, inputType, hint))
|
||||||
return true;
|
return true;
|
||||||
@@ -765,7 +765,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
|
|
||||||
for (var i = 0; i < elements.Length; i++)
|
for (var i = 0; i < elements.Length; i++)
|
||||||
{
|
{
|
||||||
if(elements[i].Type != NodeElementType.Input)
|
if (elements[i].Type != NodeElementType.Input)
|
||||||
continue;
|
continue;
|
||||||
if (VisjectSurface.FullCastCheck(elements[i].ConnectionsType, outputType, hint))
|
if (VisjectSurface.FullCastCheck(elements[i].ConnectionsType, outputType, hint))
|
||||||
return true;
|
return true;
|
||||||
@@ -789,7 +789,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override bool UseNormalMaps => false;
|
protected override bool UseNormalMaps => false;
|
||||||
|
|
||||||
internal new static bool IsOutputCompatible(NodeArchetype nodeArch, ScriptType inputType, ConnectionsHint hint, VisjectSurfaceContext context)
|
internal new static bool IsOutputCompatible(NodeArchetype nodeArch, ScriptType inputType, ConnectionsHint hint, VisjectSurfaceContext context)
|
||||||
{
|
{
|
||||||
if (inputType == ScriptType.Object)
|
if (inputType == ScriptType.Object)
|
||||||
@@ -987,7 +987,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
_combobox.Width = Width - 50;
|
_combobox.Width = Width - 50;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool IsOutputCompatible(NodeArchetype nodeArch, ScriptType inputType, ConnectionsHint hint, VisjectSurfaceContext context)
|
internal static bool IsOutputCompatible(NodeArchetype nodeArch, ScriptType inputType, ConnectionsHint hint, VisjectSurfaceContext context)
|
||||||
{
|
{
|
||||||
return inputType == ScriptType.Void;
|
return inputType == ScriptType.Void;
|
||||||
@@ -997,7 +997,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
{
|
{
|
||||||
if (outputType == ScriptType.Void)
|
if (outputType == ScriptType.Void)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
SurfaceParameter parameter = context.GetParameter((Guid)nodeArch.DefaultValues[0]);
|
SurfaceParameter parameter = context.GetParameter((Guid)nodeArch.DefaultValues[0]);
|
||||||
ScriptType type = parameter?.Type ?? ScriptType.Null;
|
ScriptType type = parameter?.Type ?? ScriptType.Null;
|
||||||
|
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ namespace FlaxEditor.Surface
|
|||||||
|
|
||||||
if (_connectionInstigator is Archetypes.Tools.RerouteNode)
|
if (_connectionInstigator is Archetypes.Tools.RerouteNode)
|
||||||
{
|
{
|
||||||
if (endPos.X < startPos.X && _lastInstigatorUnderMouse is null or Box { IsOutput: true})
|
if (endPos.X < startPos.X && _lastInstigatorUnderMouse is null or Box { IsOutput: true })
|
||||||
{
|
{
|
||||||
actualStartPos = endPos;
|
actualStartPos = endPos;
|
||||||
actualEndPos = startPos;
|
actualEndPos = startPos;
|
||||||
|
|||||||
@@ -150,6 +150,12 @@ namespace FlaxEditor.Tools.Terrain
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Increase or decrease brush size with scroll
|
||||||
|
if (Input.GetKey(KeyboardKeys.Shift))
|
||||||
|
{
|
||||||
|
Mode.CurrentBrush.Size += dt * Mode.CurrentBrush.Size * Input.Mouse.ScrollDelta * 5f;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if no terrain is selected
|
// Check if no terrain is selected
|
||||||
var terrain = SelectedTerrain;
|
var terrain = SelectedTerrain;
|
||||||
if (!terrain)
|
if (!terrain)
|
||||||
|
|||||||
@@ -158,6 +158,12 @@ namespace FlaxEditor.Tools.Terrain
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Increase or decrease brush size with scroll
|
||||||
|
if (Input.GetKey(KeyboardKeys.Shift))
|
||||||
|
{
|
||||||
|
Mode.CurrentBrush.Size += dt * Mode.CurrentBrush.Size * Input.Mouse.ScrollDelta * 5f;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if selected terrain was changed during painting
|
// Check if selected terrain was changed during painting
|
||||||
if (terrain != _paintTerrain && IsPainting)
|
if (terrain != _paintTerrain && IsPainting)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -49,7 +49,16 @@ namespace FlaxEditor.Actions
|
|||||||
_scriptTypeName = script.TypeName;
|
_scriptTypeName = script.TypeName;
|
||||||
_prefabId = script.PrefabID;
|
_prefabId = script.PrefabID;
|
||||||
_prefabObjectId = script.PrefabObjectID;
|
_prefabObjectId = script.PrefabObjectID;
|
||||||
_scriptData = FlaxEngine.Json.JsonSerializer.Serialize(script);
|
try
|
||||||
|
{
|
||||||
|
_scriptData = FlaxEngine.Json.JsonSerializer.Serialize(script);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_scriptData = null;
|
||||||
|
Debug.LogError("Failed to serialize script data for Undo due to exception");
|
||||||
|
Debug.LogException(ex);
|
||||||
|
}
|
||||||
_parentId = script.Actor.ID;
|
_parentId = script.Actor.ID;
|
||||||
_orderInParent = script.OrderInParent;
|
_orderInParent = script.OrderInParent;
|
||||||
_enabled = script.Enabled;
|
_enabled = script.Enabled;
|
||||||
|
|||||||
@@ -1119,7 +1119,12 @@ namespace FlaxEditor.Viewport
|
|||||||
var win = (WindowRootControl)Root;
|
var win = (WindowRootControl)Root;
|
||||||
|
|
||||||
// Get current mouse position in the view
|
// Get current mouse position in the view
|
||||||
_viewMousePos = PointFromWindow(win.MousePosition);
|
{
|
||||||
|
// When the window is not focused, the position in window does not return sane values
|
||||||
|
Float2 pos = PointFromWindow(win.MousePosition);
|
||||||
|
if (!float.IsInfinity(pos.LengthSquared))
|
||||||
|
_viewMousePos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
// Update input
|
// Update input
|
||||||
var window = win.Window;
|
var window = win.Window;
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ namespace FlaxEditor.Viewport.Previews
|
|||||||
case DrawModes.Fill:
|
case DrawModes.Fill:
|
||||||
clipsInView = 1.0f;
|
clipsInView = 1.0f;
|
||||||
clipWidth = width;
|
clipWidth = width;
|
||||||
samplesPerIndex = (uint)(samplesPerChannel / width);
|
samplesPerIndex = (uint)(samplesPerChannel / width) * info.NumChannels;
|
||||||
break;
|
break;
|
||||||
case DrawModes.Single:
|
case DrawModes.Single:
|
||||||
clipsInView = Mathf.Min(clipsInView, 1.0f);
|
clipsInView = Mathf.Min(clipsInView, 1.0f);
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ namespace FlaxEditor
|
|||||||
if (_highlightMaterial == null
|
if (_highlightMaterial == null
|
||||||
|| (_highlights.Count == 0 && _highlightTriangles.Count == 0)
|
|| (_highlights.Count == 0 && _highlightTriangles.Count == 0)
|
||||||
|| renderContext.View.Pass == DrawPass.Depth
|
|| renderContext.View.Pass == DrawPass.Depth
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
Profiler.BeginEvent("ViewportDebugDrawData.OnDraw");
|
Profiler.BeginEvent("ViewportDebugDrawData.OnDraw");
|
||||||
|
|
||||||
|
|||||||
@@ -335,6 +335,22 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool OnKeyDown(KeyboardKeys key)
|
||||||
|
{
|
||||||
|
if (base.OnKeyDown(key))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (key == KeyboardKeys.Spacebar)
|
||||||
|
{
|
||||||
|
if (_previewSource?.State == AudioSource.States.Playing)
|
||||||
|
OnPause();
|
||||||
|
else
|
||||||
|
OnPlay();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool UseLayoutData => true;
|
public override bool UseLayoutData => true;
|
||||||
|
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
{
|
{
|
||||||
OnPasteAction(pasteAction);
|
OnPasteAction(pasteAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scroll to new selected node
|
// Scroll to new selected node
|
||||||
ScrollToSelectedNode();
|
ScrollToSelectedNode();
|
||||||
}
|
}
|
||||||
@@ -183,7 +183,7 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
{
|
{
|
||||||
OnPasteAction(pasteAction);
|
OnPasteAction(pasteAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scroll to new selected node
|
// Scroll to new selected node
|
||||||
ScrollToSelectedNode();
|
ScrollToSelectedNode();
|
||||||
}
|
}
|
||||||
@@ -334,7 +334,7 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
}, action2.ActionString);
|
}, action2.ActionString);
|
||||||
action.Do();
|
action.Do();
|
||||||
Undo.AddAction(action);
|
Undo.AddAction(action);
|
||||||
|
|
||||||
_treePanel.PerformLayout();
|
_treePanel.PerformLayout();
|
||||||
_treePanel.PerformLayout();
|
_treePanel.PerformLayout();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
InputActions.Add(options => options.Rename, Rename);
|
InputActions.Add(options => options.Rename, Rename);
|
||||||
InputActions.Add(options => options.FocusSelection, _viewport.FocusSelection);
|
InputActions.Add(options => options.FocusSelection, _viewport.FocusSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables or disables vertical and horizontal scrolling on the tree panel.
|
/// Enables or disables vertical and horizontal scrolling on the tree panel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -257,7 +257,7 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
{
|
{
|
||||||
if (base.OnMouseUp(location, button))
|
if (base.OnMouseUp(location, button))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (button == MouseButton.Right && _treePanel.ContainsPoint(ref location))
|
if (button == MouseButton.Right && _treePanel.ContainsPoint(ref location))
|
||||||
{
|
{
|
||||||
_tree.Deselect();
|
_tree.Deselect();
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ namespace FlaxEditor.Windows.Profiler
|
|||||||
_tableRep.IsLayoutLocked = true;
|
_tableRep.IsLayoutLocked = true;
|
||||||
RecycleTableRows(_tableRpc, _tableRowsCache);
|
RecycleTableRows(_tableRpc, _tableRowsCache);
|
||||||
RecycleTableRows(_tableRep, _tableRowsCache);
|
RecycleTableRows(_tableRep, _tableRowsCache);
|
||||||
|
|
||||||
var events = _events.Get(selectedFrame);
|
var events = _events.Get(selectedFrame);
|
||||||
var rowCount = Int2.Zero;
|
var rowCount = Int2.Zero;
|
||||||
if (events != null && events.Length != 0)
|
if (events != null && events.Length != 0)
|
||||||
@@ -186,7 +186,7 @@ namespace FlaxEditor.Windows.Profiler
|
|||||||
_tableRep.Visible = rowCount.Y != 0;
|
_tableRep.Visible = rowCount.Y != 0;
|
||||||
_tableRpc.Children.Sort(SortRows);
|
_tableRpc.Children.Sort(SortRows);
|
||||||
_tableRep.Children.Sort(SortRows);
|
_tableRep.Children.Sort(SortRows);
|
||||||
|
|
||||||
_tableRpc.UnlockChildrenRecursive();
|
_tableRpc.UnlockChildrenRecursive();
|
||||||
_tableRpc.PerformLayout();
|
_tableRpc.PerformLayout();
|
||||||
_tableRep.UnlockChildrenRecursive();
|
_tableRep.UnlockChildrenRecursive();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#include "AnimGraph.h"
|
#include "AnimGraph.h"
|
||||||
|
#include "Engine/Core/Types/VariantValueCast.h"
|
||||||
#include "Engine/Content/Assets/Animation.h"
|
#include "Engine/Content/Assets/Animation.h"
|
||||||
#include "Engine/Content/Assets/SkeletonMask.h"
|
#include "Engine/Content/Assets/SkeletonMask.h"
|
||||||
#include "Engine/Content/Assets/AnimationGraphFunction.h"
|
#include "Engine/Content/Assets/AnimationGraphFunction.h"
|
||||||
@@ -530,7 +531,7 @@ void AnimGraphExecutor::UpdateStateTransitions(AnimGraphContext& context, const
|
|||||||
transitionData.Position = 0;
|
transitionData.Position = 0;
|
||||||
transitionData.Length = ZeroTolerance;
|
transitionData.Length = ZeroTolerance;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool useDefaultRule = EnumHasAnyFlags(transition.Flags, AnimGraphStateTransition::FlagTypes::UseDefaultRule);
|
const bool useDefaultRule = EnumHasAnyFlags(transition.Flags, AnimGraphStateTransition::FlagTypes::UseDefaultRule);
|
||||||
if (transition.RuleGraph && !useDefaultRule)
|
if (transition.RuleGraph && !useDefaultRule)
|
||||||
{
|
{
|
||||||
@@ -750,9 +751,16 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
|||||||
// Animation
|
// Animation
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
const auto anim = node->Assets[0].As<Animation>();
|
auto anim = node->Assets[0].As<Animation>();
|
||||||
auto& bucket = context.Data->State[node->BucketIndex].Animation;
|
auto& bucket = context.Data->State[node->BucketIndex].Animation;
|
||||||
|
|
||||||
|
// Override animation when animation reference box is connected
|
||||||
|
auto animationAssetBox = node->TryGetBox(8);
|
||||||
|
if (animationAssetBox && animationAssetBox->HasConnection())
|
||||||
|
{
|
||||||
|
anim = TVariantValueCast<Animation*>::Cast(tryGetValue(animationAssetBox, Value::Null));
|
||||||
|
}
|
||||||
|
|
||||||
switch (box->ID)
|
switch (box->ID)
|
||||||
{
|
{
|
||||||
// Animation
|
// Animation
|
||||||
|
|||||||
@@ -187,7 +187,6 @@ float AudioSource::GetTime() const
|
|||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
|
||||||
float time = AudioBackend::Source::GetCurrentBufferTime(this);
|
float time = AudioBackend::Source::GetCurrentBufferTime(this);
|
||||||
ASSERT(time >= 0.0f && time <= Clip->GetLength());
|
|
||||||
|
|
||||||
if (UseStreaming())
|
if (UseStreaming())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,7 +27,15 @@
|
|||||||
#define MAX_INPUT_CHANNELS 2
|
#define MAX_INPUT_CHANNELS 2
|
||||||
#define MAX_OUTPUT_CHANNELS 8
|
#define MAX_OUTPUT_CHANNELS 8
|
||||||
#define MAX_CHANNELS_MATRIX_SIZE (MAX_INPUT_CHANNELS*MAX_OUTPUT_CHANNELS)
|
#define MAX_CHANNELS_MATRIX_SIZE (MAX_INPUT_CHANNELS*MAX_OUTPUT_CHANNELS)
|
||||||
|
#if ENABLE_ASSERTION
|
||||||
|
#define XAUDIO2_CHECK_ERROR(method) \
|
||||||
|
if (hr != 0) \
|
||||||
|
{ \
|
||||||
|
LOG(Error, "XAudio2 method {0} failed with error 0x{1:X} (at line {2})", TEXT(#method), (uint32)hr, __LINE__ - 1); \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define XAUDIO2_CHECK_ERROR(method)
|
||||||
|
#endif
|
||||||
#define FLAX_COORD_SCALE 0.01f // units are meters
|
#define FLAX_COORD_SCALE 0.01f // units are meters
|
||||||
#define FLAX_DST_TO_XAUDIO(x) x * FLAX_COORD_SCALE
|
#define FLAX_DST_TO_XAUDIO(x) x * FLAX_COORD_SCALE
|
||||||
#define FLAX_POS_TO_XAUDIO(vec) X3DAUDIO_VECTOR(vec.X * FLAX_COORD_SCALE, vec.Y * FLAX_COORD_SCALE, vec.Z * FLAX_COORD_SCALE)
|
#define FLAX_POS_TO_XAUDIO(vec) X3DAUDIO_VECTOR(vec.X * FLAX_COORD_SCALE, vec.Y * FLAX_COORD_SCALE, vec.Z * FLAX_COORD_SCALE)
|
||||||
@@ -104,7 +112,9 @@ namespace XAudio2
|
|||||||
|
|
||||||
COM_DECLSPEC_NOTHROW void STDMETHODCALLTYPE OnVoiceError(THIS_ void* pBufferContext, HRESULT Error) override
|
COM_DECLSPEC_NOTHROW void STDMETHODCALLTYPE OnVoiceError(THIS_ void* pBufferContext, HRESULT Error) override
|
||||||
{
|
{
|
||||||
|
#if ENABLE_ASSERTION
|
||||||
LOG(Warning, "IXAudio2VoiceCallback::OnVoiceError! Error: 0x{0:x}", Error);
|
LOG(Warning, "IXAudio2VoiceCallback::OnVoiceError! Error: 0x{0:x}", Error);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -121,7 +131,8 @@ namespace XAudio2
|
|||||||
XAUDIO2_SEND_DESCRIPTOR Destination;
|
XAUDIO2_SEND_DESCRIPTOR Destination;
|
||||||
float Pitch;
|
float Pitch;
|
||||||
float Pan;
|
float Pan;
|
||||||
float StartTime;
|
float StartTimeForQueueBuffer;
|
||||||
|
float LastBufferStartTime;
|
||||||
float DopplerFactor;
|
float DopplerFactor;
|
||||||
uint64 LastBufferStartSamplesPlayed;
|
uint64 LastBufferStartSamplesPlayed;
|
||||||
int32 BuffersProcessed;
|
int32 BuffersProcessed;
|
||||||
@@ -145,7 +156,8 @@ namespace XAudio2
|
|||||||
Destination.pOutputVoice = nullptr;
|
Destination.pOutputVoice = nullptr;
|
||||||
Pitch = 1.0f;
|
Pitch = 1.0f;
|
||||||
Pan = 0.0f;
|
Pan = 0.0f;
|
||||||
StartTime = 0.0f;
|
StartTimeForQueueBuffer = 0.0f;
|
||||||
|
LastBufferStartTime = 0.0f;
|
||||||
IsDirty = false;
|
IsDirty = false;
|
||||||
Is3D = false;
|
Is3D = false;
|
||||||
IsPlaying = false;
|
IsPlaying = false;
|
||||||
@@ -255,18 +267,18 @@ namespace XAudio2
|
|||||||
buffer.pAudioData = aBuffer->Data.Get();
|
buffer.pAudioData = aBuffer->Data.Get();
|
||||||
buffer.AudioBytes = aBuffer->Data.Count();
|
buffer.AudioBytes = aBuffer->Data.Count();
|
||||||
|
|
||||||
if (aSource->StartTime > ZeroTolerance)
|
if (aSource->StartTimeForQueueBuffer > ZeroTolerance)
|
||||||
{
|
{
|
||||||
buffer.PlayBegin = (UINT32)(aSource->StartTime * (aBuffer->Info.SampleRate * aBuffer->Info.NumChannels));
|
// Offset start position when playing buffer with a custom time offset
|
||||||
buffer.PlayLength = aBuffer->Info.NumSamples / aBuffer->Info.NumChannels - buffer.PlayBegin;
|
const uint32 bytesPerSample = aBuffer->Info.BitDepth / 8 * aBuffer->Info.NumChannels;
|
||||||
aSource->StartTime = 0;
|
buffer.PlayBegin = (UINT32)(aSource->StartTimeForQueueBuffer * aBuffer->Info.SampleRate);
|
||||||
|
buffer.PlayLength = (buffer.AudioBytes / bytesPerSample) - buffer.PlayBegin;
|
||||||
|
aSource->LastBufferStartTime = aSource->StartTimeForQueueBuffer;
|
||||||
|
aSource->StartTimeForQueueBuffer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const HRESULT hr = aSource->Voice->SubmitSourceBuffer(&buffer);
|
const HRESULT hr = aSource->Voice->SubmitSourceBuffer(&buffer);
|
||||||
if (FAILED(hr))
|
XAUDIO2_CHECK_ERROR(SubmitSourceBuffer);
|
||||||
{
|
|
||||||
LOG(Warning, "XAudio2: Failed to submit source buffer (error: 0x{0:x})", hr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceCallback::OnBufferEnd(void* pBufferContext)
|
void VoiceCallback::OnBufferEnd(void* pBufferContext)
|
||||||
@@ -375,7 +387,7 @@ void AudioBackendXAudio2::Source_OnAdd(AudioSource* source)
|
|||||||
const auto& header = clip->AudioHeader;
|
const auto& header = clip->AudioHeader;
|
||||||
auto& format = aSource->Format;
|
auto& format = aSource->Format;
|
||||||
format.wFormatTag = WAVE_FORMAT_PCM;
|
format.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
format.nChannels = source->Is3D() ? 1 : header.Info.NumChannels; // 3d audio is always mono (AudioClip auto-converts before buffer write)
|
format.nChannels = clip->Is3D() ? 1 : header.Info.NumChannels; // 3d audio is always mono (AudioClip auto-converts before buffer write)
|
||||||
format.nSamplesPerSec = header.Info.SampleRate;
|
format.nSamplesPerSec = header.Info.SampleRate;
|
||||||
format.wBitsPerSample = header.Info.BitDepth;
|
format.wBitsPerSample = header.Info.BitDepth;
|
||||||
format.nBlockAlign = (WORD)(format.nChannels * (format.wBitsPerSample / 8));
|
format.nBlockAlign = (WORD)(format.nChannels * (format.wBitsPerSample / 8));
|
||||||
@@ -391,12 +403,10 @@ void AudioBackendXAudio2::Source_OnAdd(AudioSource* source)
|
|||||||
1,
|
1,
|
||||||
&aSource->Destination
|
&aSource->Destination
|
||||||
};
|
};
|
||||||
const HRESULT hr = XAudio2::Instance->CreateSourceVoice(&aSource->Voice, &aSource->Format, 0, 2.0f, &aSource->Callback, &sendList);
|
HRESULT hr = XAudio2::Instance->CreateSourceVoice(&aSource->Voice, &aSource->Format, 0, 2.0f, &aSource->Callback, &sendList);
|
||||||
|
XAUDIO2_CHECK_ERROR(CreateSourceVoice);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
|
||||||
LOG(Error, "Failed to create XAudio2 voice. Error: 0x{0:x}", hr);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare source state
|
// Prepare source state
|
||||||
aSource->Callback.Source = source;
|
aSource->Callback.Source = source;
|
||||||
@@ -410,7 +420,8 @@ void AudioBackendXAudio2::Source_OnAdd(AudioSource* source)
|
|||||||
aSource->DopplerFactor = source->GetDopplerFactor();
|
aSource->DopplerFactor = source->GetDopplerFactor();
|
||||||
aSource->UpdateTransform(source);
|
aSource->UpdateTransform(source);
|
||||||
aSource->UpdateVelocity(source);
|
aSource->UpdateVelocity(source);
|
||||||
aSource->Voice->SetVolume(source->GetVolume());
|
hr = aSource->Voice->SetVolume(source->GetVolume());
|
||||||
|
XAUDIO2_CHECK_ERROR(SetVolume);
|
||||||
|
|
||||||
// 0 is invalid ID so shift them
|
// 0 is invalid ID so shift them
|
||||||
sourceID++;
|
sourceID++;
|
||||||
@@ -451,7 +462,8 @@ void AudioBackendXAudio2::Source_VolumeChanged(AudioSource* source)
|
|||||||
auto aSource = XAudio2::GetSource(source);
|
auto aSource = XAudio2::GetSource(source);
|
||||||
if (aSource && aSource->Voice)
|
if (aSource && aSource->Voice)
|
||||||
{
|
{
|
||||||
aSource->Voice->SetVolume(source->GetVolume());
|
const HRESULT hr = aSource->Voice->SetVolume(source->GetVolume());
|
||||||
|
XAUDIO2_CHECK_ERROR(SetVolume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,12 +506,18 @@ void AudioBackendXAudio2::Source_IsLoopingChanged(AudioSource* source)
|
|||||||
XAudio2::Buffer* aBuffer = XAudio2::Buffers[bufferId - 1];
|
XAudio2::Buffer* aBuffer = XAudio2::Buffers[bufferId - 1];
|
||||||
XAudio2::Locker.Unlock();
|
XAudio2::Locker.Unlock();
|
||||||
|
|
||||||
|
HRESULT hr;
|
||||||
const bool isPlaying = source->IsActuallyPlayingSth();
|
const bool isPlaying = source->IsActuallyPlayingSth();
|
||||||
if (isPlaying)
|
if (isPlaying)
|
||||||
aSource->Voice->Stop();
|
{
|
||||||
|
hr = aSource->Voice->Stop();
|
||||||
|
XAUDIO2_CHECK_ERROR(Stop);
|
||||||
|
}
|
||||||
|
|
||||||
aSource->Voice->FlushSourceBuffers();
|
hr = aSource->Voice->FlushSourceBuffers();
|
||||||
|
XAUDIO2_CHECK_ERROR(FlushSourceBuffers);
|
||||||
aSource->LastBufferStartSamplesPlayed = 0;
|
aSource->LastBufferStartSamplesPlayed = 0;
|
||||||
|
aSource->LastBufferStartTime = 0;
|
||||||
aSource->BuffersProcessed = 0;
|
aSource->BuffersProcessed = 0;
|
||||||
|
|
||||||
XAUDIO2_BUFFER buffer = { 0 };
|
XAUDIO2_BUFFER buffer = { 0 };
|
||||||
@@ -512,12 +530,15 @@ void AudioBackendXAudio2::Source_IsLoopingChanged(AudioSource* source)
|
|||||||
const UINT32 totalSamples = aBuffer->Info.NumSamples / aBuffer->Info.NumChannels;
|
const UINT32 totalSamples = aBuffer->Info.NumSamples / aBuffer->Info.NumChannels;
|
||||||
buffer.PlayBegin = state.SamplesPlayed % totalSamples;
|
buffer.PlayBegin = state.SamplesPlayed % totalSamples;
|
||||||
buffer.PlayLength = totalSamples - buffer.PlayBegin;
|
buffer.PlayLength = totalSamples - buffer.PlayBegin;
|
||||||
aSource->StartTime = 0;
|
aSource->StartTimeForQueueBuffer = 0;
|
||||||
|
|
||||||
XAudio2::QueueBuffer(aSource, source, bufferId, buffer);
|
XAudio2::QueueBuffer(aSource, source, bufferId, buffer);
|
||||||
|
|
||||||
if (isPlaying)
|
if (isPlaying)
|
||||||
aSource->Voice->Start();
|
{
|
||||||
|
hr = aSource->Voice->Start();
|
||||||
|
XAUDIO2_CHECK_ERROR(Start);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioBackendXAudio2::Source_SpatialSetupChanged(AudioSource* source)
|
void AudioBackendXAudio2::Source_SpatialSetupChanged(AudioSource* source)
|
||||||
@@ -572,7 +593,8 @@ void AudioBackendXAudio2::Source_Play(AudioSource* source)
|
|||||||
if (aSource && aSource->Voice && !aSource->IsPlaying)
|
if (aSource && aSource->Voice && !aSource->IsPlaying)
|
||||||
{
|
{
|
||||||
// Play
|
// Play
|
||||||
aSource->Voice->Start();
|
const HRESULT hr = aSource->Voice->Start();
|
||||||
|
XAUDIO2_CHECK_ERROR(Start);
|
||||||
aSource->IsPlaying = true;
|
aSource->IsPlaying = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -583,7 +605,8 @@ void AudioBackendXAudio2::Source_Pause(AudioSource* source)
|
|||||||
if (aSource && aSource->Voice && aSource->IsPlaying)
|
if (aSource && aSource->Voice && aSource->IsPlaying)
|
||||||
{
|
{
|
||||||
// Pause
|
// Pause
|
||||||
aSource->Voice->Stop();
|
const HRESULT hr = aSource->Voice->Stop();
|
||||||
|
XAUDIO2_CHECK_ERROR(Stop);
|
||||||
aSource->IsPlaying = false;
|
aSource->IsPlaying = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -593,14 +616,18 @@ void AudioBackendXAudio2::Source_Stop(AudioSource* source)
|
|||||||
auto aSource = XAudio2::GetSource(source);
|
auto aSource = XAudio2::GetSource(source);
|
||||||
if (aSource && aSource->Voice)
|
if (aSource && aSource->Voice)
|
||||||
{
|
{
|
||||||
aSource->StartTime = 0.0f;
|
aSource->StartTimeForQueueBuffer = 0.0f;
|
||||||
|
aSource->LastBufferStartTime = 0.0f;
|
||||||
|
|
||||||
// Pause
|
// Pause
|
||||||
aSource->Voice->Stop();
|
HRESULT hr = aSource->Voice->Stop();
|
||||||
|
XAUDIO2_CHECK_ERROR(Stop);
|
||||||
aSource->IsPlaying = false;
|
aSource->IsPlaying = false;
|
||||||
|
|
||||||
// Unset streaming buffers to rewind
|
// Unset streaming buffers to rewind
|
||||||
aSource->Voice->FlushSourceBuffers();
|
hr = aSource->Voice->FlushSourceBuffers();
|
||||||
|
XAUDIO2_CHECK_ERROR(FlushSourceBuffers);
|
||||||
|
Platform::Sleep(10); // TODO: find a better way to handle case when VoiceCallback::OnBufferEnd is called after source was stopped thus BuffersProcessed != 0, probably via buffers contexts ptrs
|
||||||
aSource->BuffersProcessed = 0;
|
aSource->BuffersProcessed = 0;
|
||||||
aSource->Callback.PeekSamples();
|
aSource->Callback.PeekSamples();
|
||||||
}
|
}
|
||||||
@@ -612,7 +639,7 @@ void AudioBackendXAudio2::Source_SetCurrentBufferTime(AudioSource* source, float
|
|||||||
if (aSource)
|
if (aSource)
|
||||||
{
|
{
|
||||||
// Store start time so next buffer submitted will start from here (assumes audio is stopped)
|
// Store start time so next buffer submitted will start from here (assumes audio is stopped)
|
||||||
aSource->StartTime = value;
|
aSource->StartTimeForQueueBuffer = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -628,8 +655,9 @@ float AudioBackendXAudio2::Source_GetCurrentBufferTime(const AudioSource* source
|
|||||||
aSource->Voice->GetState(&state);
|
aSource->Voice->GetState(&state);
|
||||||
const uint32 numChannels = clipInfo.NumChannels;
|
const uint32 numChannels = clipInfo.NumChannels;
|
||||||
const uint32 totalSamples = clipInfo.NumSamples / numChannels;
|
const uint32 totalSamples = clipInfo.NumSamples / numChannels;
|
||||||
|
const uint32 sampleRate = clipInfo.SampleRate;// / clipInfo.NumChannels;
|
||||||
state.SamplesPlayed -= aSource->LastBufferStartSamplesPlayed % totalSamples; // Offset by the last buffer start to get time relative to its begin
|
state.SamplesPlayed -= aSource->LastBufferStartSamplesPlayed % totalSamples; // Offset by the last buffer start to get time relative to its begin
|
||||||
time = aSource->StartTime + (state.SamplesPlayed % totalSamples) / static_cast<float>(Math::Max(1U, clipInfo.SampleRate));
|
time = aSource->LastBufferStartTime + (state.SamplesPlayed % totalSamples) / static_cast<float>(Math::Max(1U, sampleRate));
|
||||||
}
|
}
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
@@ -697,10 +725,7 @@ void AudioBackendXAudio2::Source_DequeueProcessedBuffers(AudioSource* source)
|
|||||||
if (aSource && aSource->Voice)
|
if (aSource && aSource->Voice)
|
||||||
{
|
{
|
||||||
const HRESULT hr = aSource->Voice->FlushSourceBuffers();
|
const HRESULT hr = aSource->Voice->FlushSourceBuffers();
|
||||||
if (FAILED(hr))
|
XAUDIO2_CHECK_ERROR(FlushSourceBuffers);
|
||||||
{
|
|
||||||
LOG(Warning, "XAudio2: FlushSourceBuffers failed. Error: 0x{0:x}", hr);
|
|
||||||
}
|
|
||||||
aSource->BuffersProcessed = 0;
|
aSource->BuffersProcessed = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -749,8 +774,7 @@ void AudioBackendXAudio2::Buffer_Write(uint32 bufferId, byte* samples, const Aud
|
|||||||
XAudio2::Buffer* aBuffer = XAudio2::Buffers[bufferId - 1];
|
XAudio2::Buffer* aBuffer = XAudio2::Buffers[bufferId - 1];
|
||||||
XAudio2::Locker.Unlock();
|
XAudio2::Locker.Unlock();
|
||||||
|
|
||||||
const uint32 bytesPerSample = info.BitDepth / 8;
|
const uint32 samplesLength = info.NumSamples * info.BitDepth / 8;
|
||||||
const int32 samplesLength = info.NumSamples * bytesPerSample;
|
|
||||||
|
|
||||||
aBuffer->Info = info;
|
aBuffer->Info = info;
|
||||||
aBuffer->Data.Set(samples, samplesLength);
|
aBuffer->Data.Set(samples, samplesLength);
|
||||||
@@ -779,7 +803,8 @@ void AudioBackendXAudio2::Base_SetVolume(float value)
|
|||||||
{
|
{
|
||||||
if (XAudio2::MasteringVoice)
|
if (XAudio2::MasteringVoice)
|
||||||
{
|
{
|
||||||
XAudio2::MasteringVoice->SetVolume(value);
|
const HRESULT hr = XAudio2::MasteringVoice->SetVolume(value);
|
||||||
|
XAUDIO2_CHECK_ERROR(SetVolume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public:
|
|||||||
/// <param name="g">The green channel value.</param>
|
/// <param name="g">The green channel value.</param>
|
||||||
/// <param name="b">The blue channel value.</param>
|
/// <param name="b">The blue channel value.</param>
|
||||||
/// <param name="a">The alpha channel value.</param>
|
/// <param name="a">The alpha channel value.</param>
|
||||||
Color(float r, float g, float b, float a = 1)
|
FORCE_INLINE Color(float r, float g, float b, float a = 1)
|
||||||
: R(r)
|
: R(r)
|
||||||
, G(g)
|
, G(g)
|
||||||
, B(b)
|
, B(b)
|
||||||
@@ -203,7 +203,7 @@ public:
|
|||||||
return Color(R - b.R, G - b.G, B - b.B, A - b.A);
|
return Color(R - b.R, G - b.G, B - b.B, A - b.A);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color operator*(const Color& b) const
|
FORCE_INLINE Color operator*(const Color& b) const
|
||||||
{
|
{
|
||||||
return Color(R * b.R, G * b.G, B * b.B, A * b.A);
|
return Color(R * b.R, G * b.G, B * b.B, A * b.A);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#include "Half.h"
|
#include "Half.h"
|
||||||
#include "Rectangle.h"
|
|
||||||
#include "Vector2.h"
|
|
||||||
#include "Vector3.h"
|
|
||||||
#include "Vector4.h"
|
#include "Vector4.h"
|
||||||
|
#include "Rectangle.h"
|
||||||
#include "Color.h"
|
#include "Color.h"
|
||||||
|
|
||||||
static_assert(sizeof(Half) == 2, "Invalid Half type size.");
|
static_assert(sizeof(Half) == 2, "Invalid Half type size.");
|
||||||
@@ -16,12 +14,47 @@ Half2 Half2::Zero(0.0f, 0.0f);
|
|||||||
Half3 Half3::Zero(0.0f, 0.0f, 0.0f);
|
Half3 Half3::Zero(0.0f, 0.0f, 0.0f);
|
||||||
Half4 Half4::Zero(0.0f, 0.0f, 0.0f, 0.0f);
|
Half4 Half4::Zero(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
Half2::Half2(const Float2& v)
|
#if !USE_SSE_HALF_CONVERSION
|
||||||
|
|
||||||
|
Half Float16Compressor::Compress(float value)
|
||||||
{
|
{
|
||||||
X = Float16Compressor::Compress(v.X);
|
Bits v, s;
|
||||||
Y = Float16Compressor::Compress(v.Y);
|
v.f = value;
|
||||||
|
uint32 sign = v.si & signN;
|
||||||
|
v.si ^= sign;
|
||||||
|
sign >>= shiftSign; // logical shift
|
||||||
|
s.si = mulN;
|
||||||
|
s.si = static_cast<int32>(s.f * v.f); // correct subnormals
|
||||||
|
v.si ^= (s.si ^ v.si) & -(minN > v.si);
|
||||||
|
v.si ^= (infN ^ v.si) & -((infN > v.si) & (v.si > maxN));
|
||||||
|
v.si ^= (nanN ^ v.si) & -((nanN > v.si) & (v.si > infN));
|
||||||
|
v.ui >>= shift; // logical shift
|
||||||
|
v.si ^= ((v.si - maxD) ^ v.si) & -(v.si > maxC);
|
||||||
|
v.si ^= ((v.si - minD) ^ v.si) & -(v.si > subC);
|
||||||
|
return v.ui | sign;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Float16Compressor::Decompress(Half value)
|
||||||
|
{
|
||||||
|
Bits v;
|
||||||
|
v.ui = value;
|
||||||
|
int32 sign = v.si & signC;
|
||||||
|
v.si ^= sign;
|
||||||
|
sign <<= shiftSign;
|
||||||
|
v.si ^= ((v.si + minD) ^ v.si) & -(v.si > subC);
|
||||||
|
v.si ^= ((v.si + maxD) ^ v.si) & -(v.si > maxC);
|
||||||
|
Bits s;
|
||||||
|
s.si = mulC;
|
||||||
|
s.f *= v.si;
|
||||||
|
const int32 mask = -(norC > v.si);
|
||||||
|
v.si <<= shift;
|
||||||
|
v.si ^= (s.si ^ v.si) & mask;
|
||||||
|
v.si |= sign;
|
||||||
|
return v.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
Float2 Half2::ToFloat2() const
|
Float2 Half2::ToFloat2() const
|
||||||
{
|
{
|
||||||
return Float2(
|
return Float2(
|
||||||
@@ -30,13 +63,6 @@ Float2 Half2::ToFloat2() const
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Half3::Half3(const Float3& v)
|
|
||||||
{
|
|
||||||
X = Float16Compressor::Compress(v.X);
|
|
||||||
Y = Float16Compressor::Compress(v.Y);
|
|
||||||
Z = Float16Compressor::Compress(v.Z);
|
|
||||||
}
|
|
||||||
|
|
||||||
Float3 Half3::ToFloat3() const
|
Float3 Half3::ToFloat3() const
|
||||||
{
|
{
|
||||||
return Float3(
|
return Float3(
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Math.h"
|
#include "Math.h"
|
||||||
|
#include "Vector2.h"
|
||||||
|
#include "Vector3.h"
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Half-precision 16 bit floating point number consisting of a sign bit, a 5 bit biased exponent, and a 10 bit mantissa
|
/// Half-precision 16 bit floating point number consisting of a sign bit, a 5 bit biased exponent, and a 10 bit mantissa
|
||||||
@@ -45,54 +47,23 @@ class FLAXENGINE_API Float16Compressor
|
|||||||
static const int32 minD = minC - subC - 1;
|
static const int32 minD = minC - subC - 1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Half Compress(const float value)
|
|
||||||
{
|
|
||||||
#if USE_SSE_HALF_CONVERSION
|
#if USE_SSE_HALF_CONVERSION
|
||||||
|
FORCE_INLINE static Half Compress(float value)
|
||||||
|
{
|
||||||
__m128 value1 = _mm_set_ss(value);
|
__m128 value1 = _mm_set_ss(value);
|
||||||
__m128i value2 = _mm_cvtps_ph(value1, 0);
|
__m128i value2 = _mm_cvtps_ph(value1, 0);
|
||||||
return static_cast<Half>(_mm_cvtsi128_si32(value2));
|
return static_cast<Half>(_mm_cvtsi128_si32(value2));
|
||||||
#else
|
|
||||||
Bits v, s;
|
|
||||||
v.f = value;
|
|
||||||
uint32 sign = v.si & signN;
|
|
||||||
v.si ^= sign;
|
|
||||||
sign >>= shiftSign; // logical shift
|
|
||||||
s.si = mulN;
|
|
||||||
s.si = static_cast<int32>(s.f * v.f); // correct subnormals
|
|
||||||
v.si ^= (s.si ^ v.si) & -(minN > v.si);
|
|
||||||
v.si ^= (infN ^ v.si) & -((infN > v.si) & (v.si > maxN));
|
|
||||||
v.si ^= (nanN ^ v.si) & -((nanN > v.si) & (v.si > infN));
|
|
||||||
v.ui >>= shift; // logical shift
|
|
||||||
v.si ^= ((v.si - maxD) ^ v.si) & -(v.si > maxC);
|
|
||||||
v.si ^= ((v.si - minD) ^ v.si) & -(v.si > subC);
|
|
||||||
return v.ui | sign;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
FORCE_INLINE static float Decompress(Half value)
|
||||||
static float Decompress(const Half value)
|
|
||||||
{
|
{
|
||||||
#if USE_SSE_HALF_CONVERSION
|
|
||||||
__m128i value1 = _mm_cvtsi32_si128(static_cast<int>(value));
|
__m128i value1 = _mm_cvtsi32_si128(static_cast<int>(value));
|
||||||
__m128 value2 = _mm_cvtph_ps(value1);
|
__m128 value2 = _mm_cvtph_ps(value1);
|
||||||
return _mm_cvtss_f32(value2);
|
return _mm_cvtss_f32(value2);
|
||||||
#else
|
|
||||||
Bits v;
|
|
||||||
v.ui = value;
|
|
||||||
int32 sign = v.si & signC;
|
|
||||||
v.si ^= sign;
|
|
||||||
sign <<= shiftSign;
|
|
||||||
v.si ^= ((v.si + minD) ^ v.si) & -(v.si > subC);
|
|
||||||
v.si ^= ((v.si + maxD) ^ v.si) & -(v.si > maxC);
|
|
||||||
Bits s;
|
|
||||||
s.si = mulC;
|
|
||||||
s.f *= v.si;
|
|
||||||
const int32 mask = -(norC > v.si);
|
|
||||||
v.si <<= shift;
|
|
||||||
v.si ^= (s.si ^ v.si) & mask;
|
|
||||||
v.si |= sign;
|
|
||||||
return v.f;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static Half Compress(float value);
|
||||||
|
static float Decompress(Half value);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -128,7 +99,7 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="x">X component</param>
|
/// <param name="x">X component</param>
|
||||||
/// <param name="y">Y component</param>
|
/// <param name="y">Y component</param>
|
||||||
Half2(Half x, Half y)
|
FORCE_INLINE Half2(Half x, Half y)
|
||||||
: X(x)
|
: X(x)
|
||||||
, Y(y)
|
, Y(y)
|
||||||
{
|
{
|
||||||
@@ -139,7 +110,7 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="x">X component</param>
|
/// <param name="x">X component</param>
|
||||||
/// <param name="y">Y component</param>
|
/// <param name="y">Y component</param>
|
||||||
Half2(float x, float y)
|
FORCE_INLINE Half2(float x, float y)
|
||||||
{
|
{
|
||||||
X = Float16Compressor::Compress(x);
|
X = Float16Compressor::Compress(x);
|
||||||
Y = Float16Compressor::Compress(y);
|
Y = Float16Compressor::Compress(y);
|
||||||
@@ -149,7 +120,11 @@ public:
|
|||||||
/// Init
|
/// Init
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="v">X and Y components</param>
|
/// <param name="v">X and Y components</param>
|
||||||
Half2(const Float2& v);
|
FORCE_INLINE Half2(const Float2& v)
|
||||||
|
{
|
||||||
|
X = Float16Compressor::Compress(v.X);
|
||||||
|
Y = Float16Compressor::Compress(v.Y);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Float2 ToFloat2() const;
|
Float2 ToFloat2() const;
|
||||||
@@ -185,21 +160,26 @@ public:
|
|||||||
public:
|
public:
|
||||||
Half3() = default;
|
Half3() = default;
|
||||||
|
|
||||||
Half3(Half x, Half y, Half z)
|
FORCE_INLINE Half3(Half x, Half y, Half z)
|
||||||
: X(x)
|
: X(x)
|
||||||
, Y(y)
|
, Y(y)
|
||||||
, Z(z)
|
, Z(z)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Half3(const float x, const float y, const float z)
|
FORCE_INLINE Half3(float x, float y, float z)
|
||||||
{
|
{
|
||||||
X = Float16Compressor::Compress(x);
|
X = Float16Compressor::Compress(x);
|
||||||
Y = Float16Compressor::Compress(y);
|
Y = Float16Compressor::Compress(y);
|
||||||
Z = Float16Compressor::Compress(z);
|
Z = Float16Compressor::Compress(z);
|
||||||
}
|
}
|
||||||
|
|
||||||
Half3(const Float3& v);
|
FORCE_INLINE Half3(const Float3& v)
|
||||||
|
{
|
||||||
|
X = Float16Compressor::Compress(v.X);
|
||||||
|
Y = Float16Compressor::Compress(v.Y);
|
||||||
|
Z = Float16Compressor::Compress(v.Z);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Float3 ToFloat3() const;
|
Float3 ToFloat3() const;
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include "Collections/Dictionary.h"
|
#include "Collections/Dictionary.h"
|
||||||
#include "Engine/Engine/Time.h"
|
#include "Engine/Engine/Time.h"
|
||||||
#include "Engine/Engine/EngineService.h"
|
#include "Engine/Engine/EngineService.h"
|
||||||
#include "Engine/Threading/Threading.h"
|
|
||||||
#include "Engine/Profiler/ProfilerCPU.h"
|
#include "Engine/Profiler/ProfilerCPU.h"
|
||||||
#include "Engine/Scripting/ScriptingObject.h"
|
#include "Engine/Scripting/ScriptingObject.h"
|
||||||
|
|
||||||
@@ -14,16 +13,15 @@ const Char* HertzSizesData[] = { TEXT("Hz"), TEXT("KHz"), TEXT("MHz"), TEXT("GHz
|
|||||||
Span<const Char*> Utilities::Private::BytesSizes(BytesSizesData, ARRAY_COUNT(BytesSizesData));
|
Span<const Char*> Utilities::Private::BytesSizes(BytesSizesData, ARRAY_COUNT(BytesSizesData));
|
||||||
Span<const Char*> Utilities::Private::HertzSizes(HertzSizesData, ARRAY_COUNT(HertzSizesData));
|
Span<const Char*> Utilities::Private::HertzSizes(HertzSizesData, ARRAY_COUNT(HertzSizesData));
|
||||||
|
|
||||||
namespace ObjectsRemovalServiceImpl
|
namespace
|
||||||
{
|
{
|
||||||
CriticalSection PoolLocker;
|
CriticalSection PoolLocker;
|
||||||
DateTime LastUpdate;
|
DateTime LastUpdate;
|
||||||
float LastUpdateGameTime;
|
float LastUpdateGameTime;
|
||||||
Dictionary<Object*, float> Pool(8192);
|
Dictionary<Object*, float> Pool(8192);
|
||||||
|
uint64 PoolCounter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace ObjectsRemovalServiceImpl;
|
|
||||||
|
|
||||||
class ObjectsRemoval : public EngineService
|
class ObjectsRemoval : public EngineService
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -64,6 +62,7 @@ void ObjectsRemovalService::Add(Object* obj, float timeToLive, bool useGameTime)
|
|||||||
|
|
||||||
PoolLocker.Lock();
|
PoolLocker.Lock();
|
||||||
Pool[obj] = timeToLive;
|
Pool[obj] = timeToLive;
|
||||||
|
PoolCounter++;
|
||||||
PoolLocker.Unlock();
|
PoolLocker.Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +71,7 @@ void ObjectsRemovalService::Flush(float dt, float gameDelta)
|
|||||||
PROFILE_CPU();
|
PROFILE_CPU();
|
||||||
|
|
||||||
PoolLocker.Lock();
|
PoolLocker.Lock();
|
||||||
|
PoolCounter = 0;
|
||||||
|
|
||||||
// Update timeouts and delete objects that timed out
|
// Update timeouts and delete objects that timed out
|
||||||
for (auto i = Pool.Begin(); i.IsNotEnd(); ++i)
|
for (auto i = Pool.Begin(); i.IsNotEnd(); ++i)
|
||||||
@@ -90,6 +90,24 @@ void ObjectsRemovalService::Flush(float dt, float gameDelta)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If any object was added to the pool while removing objects (by this thread) then retry removing any nested objects (but without delta time)
|
||||||
|
if (PoolCounter != 0)
|
||||||
|
{
|
||||||
|
RETRY:
|
||||||
|
PoolCounter = 0;
|
||||||
|
for (auto i = Pool.Begin(); i.IsNotEnd(); ++i)
|
||||||
|
{
|
||||||
|
if (i->Value <= 0.0f)
|
||||||
|
{
|
||||||
|
Object* obj = i->Key;
|
||||||
|
Pool.Remove(i);
|
||||||
|
obj->OnDeleteObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (PoolCounter != 0)
|
||||||
|
goto RETRY;
|
||||||
|
}
|
||||||
|
|
||||||
PoolLocker.Unlock();
|
PoolLocker.Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +139,7 @@ void ObjectsRemoval::Dispose()
|
|||||||
|
|
||||||
// Delete all remaining objects
|
// Delete all remaining objects
|
||||||
{
|
{
|
||||||
ScopeLock lock(PoolLocker);
|
PoolLocker.Lock();
|
||||||
for (auto i = Pool.Begin(); i.IsNotEnd(); ++i)
|
for (auto i = Pool.Begin(); i.IsNotEnd(); ++i)
|
||||||
{
|
{
|
||||||
Object* obj = i->Key;
|
Object* obj = i->Key;
|
||||||
@@ -129,6 +147,7 @@ void ObjectsRemoval::Dispose()
|
|||||||
obj->OnDeleteObject();
|
obj->OnDeleteObject();
|
||||||
}
|
}
|
||||||
Pool.Clear();
|
Pool.Clear();
|
||||||
|
PoolLocker.Unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -857,36 +857,25 @@ namespace FlaxEngine.Interop
|
|||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
internal static void FieldGetValueReference(ManagedHandle fieldOwnerHandle, ManagedHandle fieldHandle, IntPtr valuePtr)
|
internal static void FieldGetValueReference(ManagedHandle fieldOwnerHandle, ManagedHandle fieldHandle, int fieldOffset, IntPtr valuePtr)
|
||||||
{
|
{
|
||||||
object fieldOwner = fieldOwnerHandle.Target;
|
object fieldOwner = fieldOwnerHandle.Target;
|
||||||
|
IntPtr fieldRef;
|
||||||
|
#if USE_AOT
|
||||||
FieldHolder field = Unsafe.As<FieldHolder>(fieldHandle.Target);
|
FieldHolder field = Unsafe.As<FieldHolder>(fieldHandle.Target);
|
||||||
|
fieldRef = IntPtr.Zero;
|
||||||
|
Debug.LogError("Not supported FieldGetValueReference");
|
||||||
|
#else
|
||||||
if (fieldOwner.GetType().IsValueType)
|
if (fieldOwner.GetType().IsValueType)
|
||||||
{
|
{
|
||||||
ref IntPtr fieldRef = ref FieldHelper.GetValueTypeFieldReference<object, IntPtr>(field.fieldOffset, ref fieldOwner);
|
fieldRef = FieldHelper.GetValueTypeFieldReference<object, IntPtr>(fieldOffset, ref fieldOwner);
|
||||||
Unsafe.Write<IntPtr>(valuePtr.ToPointer(), fieldRef);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ref IntPtr fieldRef = ref FieldHelper.GetReferenceTypeFieldReference<object, IntPtr>(field.fieldOffset, ref fieldOwner);
|
fieldRef = FieldHelper.GetReferenceTypeFieldReference<object, IntPtr>(fieldOffset, ref fieldOwner);
|
||||||
Unsafe.Write<IntPtr>(valuePtr.ToPointer(), fieldRef);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
|
||||||
internal static void FieldGetValueReferenceWithOffset(ManagedHandle fieldOwnerHandle, int fieldOffset, IntPtr valuePtr)
|
|
||||||
{
|
|
||||||
object fieldOwner = fieldOwnerHandle.Target;
|
|
||||||
if (fieldOwner.GetType().IsValueType)
|
|
||||||
{
|
|
||||||
ref IntPtr fieldRef = ref FieldHelper.GetValueTypeFieldReference<object, IntPtr>(fieldOffset, ref fieldOwner);
|
|
||||||
Unsafe.Write<IntPtr>(valuePtr.ToPointer(), fieldRef);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ref IntPtr fieldRef = ref FieldHelper.GetReferenceTypeFieldReference<object, IntPtr>(fieldOffset, ref fieldOwner);
|
|
||||||
Unsafe.Write<IntPtr>(valuePtr.ToPointer(), fieldRef);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
Unsafe.Write<IntPtr>(valuePtr.ToPointer(), fieldRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly]
|
[UnmanagedCallersOnly]
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ namespace FlaxEngine.Interop
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !USE_AOT
|
||||||
// Cache offsets to frequently accessed fields of FlaxEngine.Object
|
// Cache offsets to frequently accessed fields of FlaxEngine.Object
|
||||||
private static int unmanagedPtrFieldOffset = IntPtr.Size + (Unsafe.Read<int>((typeof(FlaxEngine.Object).GetField("__unmanagedPtr", BindingFlags.Instance | BindingFlags.NonPublic).FieldHandle.Value + 4 + IntPtr.Size).ToPointer()) & 0xFFFFFF);
|
private static int unmanagedPtrFieldOffset = IntPtr.Size + (Unsafe.Read<int>((typeof(FlaxEngine.Object).GetField("__unmanagedPtr", BindingFlags.Instance | BindingFlags.NonPublic).FieldHandle.Value + 4 + IntPtr.Size).ToPointer()) & 0xFFFFFF);
|
||||||
private static int internalIdFieldOffset = IntPtr.Size + (Unsafe.Read<int>((typeof(FlaxEngine.Object).GetField("__internalId", BindingFlags.Instance | BindingFlags.NonPublic).FieldHandle.Value + 4 + IntPtr.Size).ToPointer()) & 0xFFFFFF);
|
private static int internalIdFieldOffset = IntPtr.Size + (Unsafe.Read<int>((typeof(FlaxEngine.Object).GetField("__internalId", BindingFlags.Instance | BindingFlags.NonPublic).FieldHandle.Value + 4 + IntPtr.Size).ToPointer()) & 0xFFFFFF);
|
||||||
@@ -150,6 +151,7 @@ namespace FlaxEngine.Interop
|
|||||||
object obj = typeHolder.CreateScriptingObject(unmanagedPtr, idPtr);
|
object obj = typeHolder.CreateScriptingObject(unmanagedPtr, idPtr);
|
||||||
return ManagedHandle.Alloc(obj);
|
return ManagedHandle.Alloc(obj);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
internal static void* NativeAlloc(int byteCount)
|
internal static void* NativeAlloc(int byteCount)
|
||||||
{
|
{
|
||||||
@@ -429,6 +431,9 @@ namespace FlaxEngine.Interop
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal static int GetFieldOffset(FieldInfo field, Type type)
|
internal static int GetFieldOffset(FieldInfo field, Type type)
|
||||||
{
|
{
|
||||||
|
if (field.IsLiteral)
|
||||||
|
return 0;
|
||||||
|
|
||||||
// Get the address of the field, source: https://stackoverflow.com/a/56512720
|
// Get the address of the field, source: https://stackoverflow.com/a/56512720
|
||||||
int fieldOffset = Unsafe.Read<int>((field.FieldHandle.Value + 4 + IntPtr.Size).ToPointer()) & 0xFFFFFF;
|
int fieldOffset = Unsafe.Read<int>((field.FieldHandle.Value + 4 + IntPtr.Size).ToPointer()) & 0xFFFFFF;
|
||||||
if (!type.IsValueType)
|
if (!type.IsValueType)
|
||||||
@@ -436,6 +441,23 @@ namespace FlaxEngine.Interop
|
|||||||
return fieldOffset;
|
return fieldOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if USE_AOT
|
||||||
|
/// <summary>
|
||||||
|
/// Helper utility to set field of the referenced value via reflection.
|
||||||
|
/// </summary>
|
||||||
|
internal static void SetReferenceTypeField<T>(FieldInfo field, ref T fieldOwner, object fieldValue)
|
||||||
|
{
|
||||||
|
if (typeof(T).IsValueType)
|
||||||
|
{
|
||||||
|
// Value types need setting via boxed object to properly propagate value
|
||||||
|
object fieldOwnerBoxed = fieldOwner;
|
||||||
|
field.SetValue(fieldOwnerBoxed, fieldValue);
|
||||||
|
fieldOwner = (T)fieldOwnerBoxed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
field.SetValue(fieldOwner, fieldValue);
|
||||||
|
}
|
||||||
|
#else
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a reference to the value of the field.
|
/// Returns a reference to the value of the field.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -462,6 +484,7 @@ namespace FlaxEngine.Interop
|
|||||||
byte* fieldPtr = (byte*)Unsafe.As<T, IntPtr>(ref fieldOwner) + fieldOffset;
|
byte* fieldPtr = (byte*)Unsafe.As<T, IntPtr>(ref fieldOwner) + fieldOffset;
|
||||||
return ref Unsafe.AsRef<TField>(fieldPtr);
|
return ref Unsafe.AsRef<TField>(fieldPtr);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -735,29 +758,49 @@ namespace FlaxEngine.Interop
|
|||||||
|
|
||||||
private static void ToManagedFieldPointerValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct
|
private static void ToManagedFieldPointerValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct
|
||||||
{
|
{
|
||||||
|
#if USE_AOT
|
||||||
|
IntPtr fieldValue = Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer());
|
||||||
|
FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue);
|
||||||
|
#else
|
||||||
ref IntPtr fieldValueRef = ref FieldHelper.GetValueTypeFieldReference<T, IntPtr>(fieldOffset, ref fieldOwner);
|
ref IntPtr fieldValueRef = ref FieldHelper.GetValueTypeFieldReference<T, IntPtr>(fieldOffset, ref fieldOwner);
|
||||||
fieldValueRef = Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer());
|
fieldValueRef = Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer());
|
||||||
|
#endif
|
||||||
fieldSize = IntPtr.Size;
|
fieldSize = IntPtr.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ToManagedFieldPointerReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
private static void ToManagedFieldPointerReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
||||||
{
|
{
|
||||||
|
#if USE_AOT
|
||||||
|
IntPtr fieldValue = Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer());
|
||||||
|
FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue);
|
||||||
|
#else
|
||||||
ref IntPtr fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference<T, IntPtr>(fieldOffset, ref fieldOwner);
|
ref IntPtr fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference<T, IntPtr>(fieldOffset, ref fieldOwner);
|
||||||
fieldValueRef = Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer());
|
fieldValueRef = Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer());
|
||||||
|
#endif
|
||||||
fieldSize = IntPtr.Size;
|
fieldSize = IntPtr.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ToNativeFieldPointerValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct
|
private static void ToNativeFieldPointerValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct
|
||||||
{
|
{
|
||||||
ref IntPtr fieldValueRef = ref FieldHelper.GetValueTypeFieldReference<T, IntPtr>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
Unsafe.Write<IntPtr>(nativeFieldPtr.ToPointer(), fieldValueRef);
|
object boxed = field.GetValue(fieldOwner);
|
||||||
|
IntPtr fieldValue = new IntPtr(Pointer.Unbox(boxed));
|
||||||
|
#else
|
||||||
|
IntPtr fieldValue = FieldHelper.GetValueTypeFieldReference<T, IntPtr>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
Unsafe.Write<IntPtr>(nativeFieldPtr.ToPointer(), fieldValue);
|
||||||
fieldSize = IntPtr.Size;
|
fieldSize = IntPtr.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ToNativeFieldPointerReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
private static void ToNativeFieldPointerReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
||||||
{
|
{
|
||||||
ref IntPtr fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference<T, IntPtr>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
Unsafe.Write<IntPtr>(nativeFieldPtr.ToPointer(), fieldValueRef);
|
object boxed = field.GetValue(fieldOwner);
|
||||||
|
IntPtr fieldValue = new IntPtr(Pointer.Unbox(boxed));
|
||||||
|
#else
|
||||||
|
IntPtr fieldValue = FieldHelper.GetReferenceTypeFieldReference<T, IntPtr>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
Unsafe.Write<IntPtr>(nativeFieldPtr.ToPointer(), fieldValue);
|
||||||
fieldSize = IntPtr.Size;
|
fieldSize = IntPtr.Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -799,8 +842,15 @@ namespace FlaxEngine.Interop
|
|||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
ref TField fieldValueRef = ref FieldHelper.GetValueTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField>.ToManaged(ref fieldValueRef, nativeFieldPtr, false);
|
TField fieldValue = default;
|
||||||
|
#else
|
||||||
|
ref TField fieldValue = ref FieldHelper.GetValueTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField>.ToManaged(ref fieldValue, nativeFieldPtr, false);
|
||||||
|
#if USE_AOT
|
||||||
|
FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void ToManagedFieldReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
internal static void ToManagedFieldReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
||||||
@@ -813,8 +863,15 @@ namespace FlaxEngine.Interop
|
|||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
ref TField fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField>.ToManaged(ref fieldValueRef, nativeFieldPtr, false);
|
TField fieldValue = default;
|
||||||
|
#else
|
||||||
|
ref TField fieldValue = ref FieldHelper.GetReferenceTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField>.ToManaged(ref fieldValue, nativeFieldPtr, false);
|
||||||
|
#if USE_AOT
|
||||||
|
FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void ToManagedFieldArrayValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct
|
internal static void ToManagedFieldArrayValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct
|
||||||
@@ -825,8 +882,15 @@ namespace FlaxEngine.Interop
|
|||||||
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
|
|
||||||
ref TField[] fieldValueRef = ref FieldHelper.GetValueTypeFieldReference<T, TField[]>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField[]>.ToManaged(ref fieldValueRef, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
TField[] fieldValue = (TField[])field.GetValue(fieldOwner);
|
||||||
|
#else
|
||||||
|
ref TField[] fieldValue = ref FieldHelper.GetValueTypeFieldReference<T, TField[]>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField[]>.ToManaged(ref fieldValue, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
||||||
|
#if USE_AOT
|
||||||
|
FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void ToManagedFieldArrayReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
internal static void ToManagedFieldArrayReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
||||||
@@ -837,8 +901,15 @@ namespace FlaxEngine.Interop
|
|||||||
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
|
|
||||||
ref TField[] fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference<T, TField[]>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField[]>.ToManaged(ref fieldValueRef, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
TField[] fieldValue = null;
|
||||||
|
#else
|
||||||
|
ref TField[] fieldValue = ref FieldHelper.GetReferenceTypeFieldReference<T, TField[]>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField[]>.ToManaged(ref fieldValue, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
||||||
|
#if USE_AOT
|
||||||
|
FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void ToNativeFieldValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct
|
internal static void ToNativeFieldValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct
|
||||||
@@ -852,11 +923,11 @@ namespace FlaxEngine.Interop
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if USE_AOT
|
#if USE_AOT
|
||||||
TField fieldValueRef = (TField)field.GetValue(fieldOwner);
|
TField fieldValue = (TField)field.GetValue(fieldOwner);
|
||||||
#else
|
#else
|
||||||
ref TField fieldValueRef = ref FieldHelper.GetValueTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
ref TField fieldValue = ref FieldHelper.GetValueTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
||||||
#endif
|
#endif
|
||||||
MarshalHelper<TField>.ToNative(ref fieldValueRef, nativeFieldPtr);
|
MarshalHelper<TField>.ToNative(ref fieldValue, nativeFieldPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void ToNativeFieldReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
internal static void ToNativeFieldReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
||||||
@@ -870,11 +941,11 @@ namespace FlaxEngine.Interop
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if USE_AOT
|
#if USE_AOT
|
||||||
TField fieldValueRef = (TField)field.GetValue(fieldOwner);
|
TField fieldValue = (TField)field.GetValue(fieldOwner);
|
||||||
#else
|
#else
|
||||||
ref TField fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
ref TField fieldValue = ref FieldHelper.GetReferenceTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
||||||
#endif
|
#endif
|
||||||
MarshalHelper<TField>.ToNative(ref fieldValueRef, nativeFieldPtr);
|
MarshalHelper<TField>.ToNative(ref fieldValue, nativeFieldPtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -904,8 +975,15 @@ namespace FlaxEngine.Interop
|
|||||||
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
|
|
||||||
ref TField fieldValueRef = ref FieldHelper.GetValueTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField>.ToManaged(ref fieldValueRef, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
TField fieldValue = null;
|
||||||
|
#else
|
||||||
|
ref TField fieldValue = ref FieldHelper.GetValueTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField>.ToManaged(ref fieldValue, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
||||||
|
#if USE_AOT
|
||||||
|
FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void ToManagedFieldReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
internal static void ToManagedFieldReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
||||||
@@ -915,8 +993,15 @@ namespace FlaxEngine.Interop
|
|||||||
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
|
|
||||||
ref TField fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField>.ToManaged(ref fieldValueRef, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
TField fieldValue = default;
|
||||||
|
#else
|
||||||
|
ref TField fieldValue = ref FieldHelper.GetReferenceTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField>.ToManaged(ref fieldValue, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
||||||
|
#if USE_AOT
|
||||||
|
FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void ToManagedFieldArrayValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct
|
internal static void ToManagedFieldArrayValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct
|
||||||
@@ -926,8 +1011,15 @@ namespace FlaxEngine.Interop
|
|||||||
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
|
|
||||||
ref TField[] fieldValueRef = ref FieldHelper.GetValueTypeFieldReference<T, TField[]>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField[]>.ToManaged(ref fieldValueRef, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
TField[] fieldValue = null;
|
||||||
|
#else
|
||||||
|
ref TField[] fieldValue = ref FieldHelper.GetValueTypeFieldReference<T, TField[]>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField[]>.ToManaged(ref fieldValue, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
||||||
|
#if USE_AOT
|
||||||
|
FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void ToManagedFieldArrayReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
internal static void ToManagedFieldArrayReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
||||||
@@ -937,8 +1029,15 @@ namespace FlaxEngine.Interop
|
|||||||
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
|
|
||||||
ref TField[] fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference<T, TField[]>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField[]>.ToManaged(ref fieldValueRef, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
TField[] fieldValue = null;
|
||||||
|
#else
|
||||||
|
ref TField[] fieldValue = ref FieldHelper.GetReferenceTypeFieldReference<T, TField[]>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField[]>.ToManaged(ref fieldValue, Unsafe.Read<IntPtr>(nativeFieldPtr.ToPointer()), false);
|
||||||
|
#if USE_AOT
|
||||||
|
FieldHelper.SetReferenceTypeField(field, ref fieldOwner, fieldValue);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void ToNativeFieldValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct
|
internal static void ToNativeFieldValueType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : struct
|
||||||
@@ -948,8 +1047,12 @@ namespace FlaxEngine.Interop
|
|||||||
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
|
|
||||||
ref TField fieldValueRef = ref FieldHelper.GetValueTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField>.ToNative(ref fieldValueRef, nativeFieldPtr);
|
TField fieldValue = (TField)field.GetValue(fieldOwner);
|
||||||
|
#else
|
||||||
|
ref TField fieldValue = ref FieldHelper.GetValueTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField>.ToNative(ref fieldValue, nativeFieldPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void ToNativeFieldReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
internal static void ToNativeFieldReferenceType(FieldInfo field, int fieldOffset, ref T fieldOwner, IntPtr nativeFieldPtr, out int fieldSize) // where T : class
|
||||||
@@ -959,8 +1062,12 @@ namespace FlaxEngine.Interop
|
|||||||
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
nativeFieldPtr = EnsureAlignment(nativeFieldPtr, IntPtr.Size);
|
||||||
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
fieldSize += (nativeFieldPtr - fieldStartPtr).ToInt32();
|
||||||
|
|
||||||
ref TField fieldValueRef = ref FieldHelper.GetReferenceTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
#if USE_AOT
|
||||||
MarshalHelper<TField>.ToNative(ref fieldValueRef, nativeFieldPtr);
|
TField fieldValue = (TField)field.GetValue(fieldOwner);
|
||||||
|
#else
|
||||||
|
ref TField fieldValue = ref FieldHelper.GetReferenceTypeFieldReference<T, TField>(fieldOffset, ref fieldOwner);
|
||||||
|
#endif
|
||||||
|
MarshalHelper<TField>.ToNative(ref fieldValue, nativeFieldPtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1044,7 +1151,7 @@ namespace FlaxEngine.Interop
|
|||||||
var fields = MarshalHelper<T>.marshallableFields;
|
var fields = MarshalHelper<T>.marshallableFields;
|
||||||
var offsets = MarshalHelper<T>.marshallableFieldOffsets;
|
var offsets = MarshalHelper<T>.marshallableFieldOffsets;
|
||||||
var marshallers = MarshalHelper<T>.toNativeFieldMarshallers;
|
var marshallers = MarshalHelper<T>.toNativeFieldMarshallers;
|
||||||
for (int i = 0; i < MarshalHelper<T>.marshallableFields.Length; i++)
|
for (int i = 0; i < fields.Length; i++)
|
||||||
{
|
{
|
||||||
marshallers[i](fields[i], offsets[i], ref managedValue, nativePtr, out int fieldSize);
|
marshallers[i](fields[i], offsets[i], ref managedValue, nativePtr, out int fieldSize);
|
||||||
nativePtr += fieldSize;
|
nativePtr += fieldSize;
|
||||||
@@ -1306,11 +1413,13 @@ namespace FlaxEngine.Interop
|
|||||||
return RuntimeHelpers.GetUninitializedObject(wrappedType);
|
return RuntimeHelpers.GetUninitializedObject(wrappedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !USE_AOT
|
||||||
internal object CreateScriptingObject(IntPtr unmanagedPtr, IntPtr idPtr)
|
internal object CreateScriptingObject(IntPtr unmanagedPtr, IntPtr idPtr)
|
||||||
{
|
{
|
||||||
object obj = CreateObject();
|
object obj = RuntimeHelpers.GetUninitializedObject(wrappedType);
|
||||||
if (obj is Object)
|
if (obj is Object)
|
||||||
{
|
{
|
||||||
|
// TODO: use UnsafeAccessorAttribute on .NET 8 and use this path on all platforms (including non-Desktop, see MCore::ScriptingObject::CreateScriptingObject)
|
||||||
{
|
{
|
||||||
ref IntPtr fieldRef = ref FieldHelper.GetReferenceTypeFieldReference<IntPtr>(unmanagedPtrFieldOffset, ref obj);
|
ref IntPtr fieldRef = ref FieldHelper.GetReferenceTypeFieldReference<IntPtr>(unmanagedPtrFieldOffset, ref obj);
|
||||||
fieldRef = unmanagedPtr;
|
fieldRef = unmanagedPtr;
|
||||||
@@ -1331,8 +1440,9 @@ namespace FlaxEngine.Interop
|
|||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public static implicit operator Type(TypeHolder holder) => holder?.type ?? null;
|
public static implicit operator Type(TypeHolder holder) => holder?.type;
|
||||||
public bool Equals(TypeHolder other) => type == other.type;
|
public bool Equals(TypeHolder other) => type == other.type;
|
||||||
public bool Equals(Type other) => type == other;
|
public bool Equals(Type other) => type == other;
|
||||||
public override int GetHashCode() => type.GetHashCode();
|
public override int GetHashCode() => type.GetHashCode();
|
||||||
|
|||||||
@@ -259,6 +259,11 @@ API_STRUCT() struct GPULimits
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD() bool HasDepthAsSRV;
|
API_FIELD() bool HasDepthAsSRV;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if device supports depth buffer clipping (see GPUPipelineState::Description::DepthClipEnable).
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD() bool HasDepthClip;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if device supports depth buffer texture as a readonly depth buffer (can be sampled in the shader while performing depth-test).
|
/// True if device supports depth buffer texture as a readonly depth buffer (can be sampled in the shader while performing depth-test).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ namespace FlaxEngine
|
|||||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||||
[Obsolete("Deprecated in 1.4")]
|
[Obsolete("Deprecated in 1.4, use overload with Float3 and Float2 parameters")]
|
||||||
public void UpdateMesh(Vector3[] vertices, int[] triangles, Vector3[] normals = null, Vector3[] tangents = null, Vector2[] uv = null, Color32[] colors = null)
|
public void UpdateMesh(Vector3[] vertices, int[] triangles, Vector3[] normals = null, Vector3[] tangents = null, Vector2[] uv = null, Color32[] colors = null)
|
||||||
{
|
{
|
||||||
UpdateMesh(Utils.ConvertCollection(vertices), triangles, Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv), colors);
|
UpdateMesh(Utils.ConvertCollection(vertices), triangles, Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv), colors);
|
||||||
@@ -357,7 +357,7 @@ namespace FlaxEngine
|
|||||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||||
[Obsolete("Deprecated in 1.4")]
|
[Obsolete("Deprecated in 1.4, use overload with Float3 and Float2 parameters")]
|
||||||
public void UpdateMesh(List<Vector3> vertices, List<int> triangles, List<Vector3> normals = null, List<Vector3> tangents = null, List<Vector2> uv = null, List<Color32> colors = null)
|
public void UpdateMesh(List<Vector3> vertices, List<int> triangles, List<Vector3> normals = null, List<Vector3> tangents = null, List<Vector2> uv = null, List<Color32> colors = null)
|
||||||
{
|
{
|
||||||
UpdateMesh(Utils.ConvertCollection(vertices), triangles, Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv), colors);
|
UpdateMesh(Utils.ConvertCollection(vertices), triangles, Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv), colors);
|
||||||
@@ -375,7 +375,7 @@ namespace FlaxEngine
|
|||||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||||
[Obsolete("Deprecated in 1.4")]
|
[Obsolete("Deprecated in 1.4, use overload with Float3 and Float2 parameters")]
|
||||||
public void UpdateMesh(Vector3[] vertices, uint[] triangles, Vector3[] normals = null, Vector3[] tangents = null, Vector2[] uv = null, Color32[] colors = null)
|
public void UpdateMesh(Vector3[] vertices, uint[] triangles, Vector3[] normals = null, Vector3[] tangents = null, Vector2[] uv = null, Color32[] colors = null)
|
||||||
{
|
{
|
||||||
UpdateMesh(Utils.ConvertCollection(vertices), triangles, Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv), colors);
|
UpdateMesh(Utils.ConvertCollection(vertices), triangles, Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv), colors);
|
||||||
@@ -393,7 +393,7 @@ namespace FlaxEngine
|
|||||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||||
[Obsolete("Deprecated in 1.4")]
|
[Obsolete("Deprecated in 1.4, use overload with Float3 and Float2 parameters")]
|
||||||
public void UpdateMesh(List<Vector3> vertices, List<uint> triangles, List<Vector3> normals = null, List<Vector3> tangents = null, List<Vector2> uv = null, List<Color32> colors = null)
|
public void UpdateMesh(List<Vector3> vertices, List<uint> triangles, List<Vector3> normals = null, List<Vector3> tangents = null, List<Vector2> uv = null, List<Color32> colors = null)
|
||||||
{
|
{
|
||||||
UpdateMesh(Utils.ConvertCollection(vertices), triangles, Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv), colors);
|
UpdateMesh(Utils.ConvertCollection(vertices), triangles, Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv), colors);
|
||||||
@@ -411,7 +411,7 @@ namespace FlaxEngine
|
|||||||
/// <param name="tangents">The tangent vectors (per vertex). Use null to compute them from normal vectors.</param>
|
/// <param name="tangents">The tangent vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||||
[Obsolete("Deprecated in 1.4")]
|
[Obsolete("Deprecated in 1.4, use overload with Float3 and Float2 parameters")]
|
||||||
public void UpdateMesh(Vector3[] vertices, ushort[] triangles, Vector3[] normals = null, Vector3[] tangents = null, Vector2[] uv = null, Color32[] colors = null)
|
public void UpdateMesh(Vector3[] vertices, ushort[] triangles, Vector3[] normals = null, Vector3[] tangents = null, Vector2[] uv = null, Color32[] colors = null)
|
||||||
{
|
{
|
||||||
UpdateMesh(Utils.ConvertCollection(vertices), triangles, Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv), colors);
|
UpdateMesh(Utils.ConvertCollection(vertices), triangles, Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv), colors);
|
||||||
@@ -429,7 +429,7 @@ namespace FlaxEngine
|
|||||||
/// <param name="tangents">The tangent vectors (per vertex). Use null to compute them from normal vectors.</param>
|
/// <param name="tangents">The tangent vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||||
[Obsolete("Deprecated in 1.4")]
|
[Obsolete("Deprecated in 1.4, use overload with Float3 and Float2 parameters")]
|
||||||
public void UpdateMesh(List<Vector3> vertices, List<ushort> triangles, List<Vector3> normals = null, List<Vector3> tangents = null, List<Vector2> uv = null, List<Color32> colors = null)
|
public void UpdateMesh(List<Vector3> vertices, List<ushort> triangles, List<Vector3> normals = null, List<Vector3> tangents = null, List<Vector2> uv = null, List<Color32> colors = null)
|
||||||
{
|
{
|
||||||
UpdateMesh(Utils.ConvertCollection(vertices), triangles, Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv), colors);
|
UpdateMesh(Utils.ConvertCollection(vertices), triangles, Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv), colors);
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ namespace FlaxEngine
|
|||||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||||
[Obsolete("Deprecated in 1.4")]
|
[Obsolete("Deprecated in 1.4, use overload with Float3 and Float2 parameters")]
|
||||||
public void UpdateMesh(Vector3[] vertices, int[] triangles, Int4[] blendIndices, Vector4[] blendWeights, Vector3[] normals = null, Vector3[] tangents = null, Vector2[] uv = null)
|
public void UpdateMesh(Vector3[] vertices, int[] triangles, Int4[] blendIndices, Vector4[] blendWeights, Vector3[] normals = null, Vector3[] tangents = null, Vector2[] uv = null)
|
||||||
{
|
{
|
||||||
UpdateMesh(Utils.ConvertCollection(vertices), triangles, blendIndices, Utils.ConvertCollection(blendWeights), Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv));
|
UpdateMesh(Utils.ConvertCollection(vertices), triangles, blendIndices, Utils.ConvertCollection(blendWeights), Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv));
|
||||||
@@ -235,7 +235,7 @@ namespace FlaxEngine
|
|||||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||||
[Obsolete("Deprecated in 1.4")]
|
[Obsolete("Deprecated in 1.4, use overload with Float3 and Float2 parameters")]
|
||||||
public void UpdateMesh(Vector3[] vertices, uint[] triangles, Int4[] blendIndices, Vector4[] blendWeights, Vector3[] normals = null, Vector3[] tangents = null, Vector2[] uv = null)
|
public void UpdateMesh(Vector3[] vertices, uint[] triangles, Int4[] blendIndices, Vector4[] blendWeights, Vector3[] normals = null, Vector3[] tangents = null, Vector2[] uv = null)
|
||||||
{
|
{
|
||||||
UpdateMesh(Utils.ConvertCollection(vertices), triangles, blendIndices, Utils.ConvertCollection(blendWeights), Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv));
|
UpdateMesh(Utils.ConvertCollection(vertices), triangles, blendIndices, Utils.ConvertCollection(blendWeights), Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv));
|
||||||
@@ -254,7 +254,7 @@ namespace FlaxEngine
|
|||||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||||
/// <param name="tangents">The tangent vectors (per vertex). Use null to compute them from normal vectors.</param>
|
/// <param name="tangents">The tangent vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||||
[Obsolete("Deprecated in 1.4")]
|
[Obsolete("Deprecated in 1.4, use overload with Float3 and Float2 parameters")]
|
||||||
public void UpdateMesh(Vector3[] vertices, ushort[] triangles, Int4[] blendIndices, Vector4[] blendWeights, Vector3[] normals = null, Vector3[] tangents = null, Vector2[] uv = null)
|
public void UpdateMesh(Vector3[] vertices, ushort[] triangles, Int4[] blendIndices, Vector4[] blendWeights, Vector3[] normals = null, Vector3[] tangents = null, Vector2[] uv = null)
|
||||||
{
|
{
|
||||||
UpdateMesh(Utils.ConvertCollection(vertices), triangles, blendIndices, Utils.ConvertCollection(blendWeights), Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv));
|
UpdateMesh(Utils.ConvertCollection(vertices), triangles, blendIndices, Utils.ConvertCollection(blendWeights), Utils.ConvertCollection(normals), Utils.ConvertCollection(tangents), Utils.ConvertCollection(uv));
|
||||||
|
|||||||
@@ -359,6 +359,7 @@ bool GPUDeviceDX11::Init()
|
|||||||
limits.HasAppendConsumeBuffers = true;
|
limits.HasAppendConsumeBuffers = true;
|
||||||
limits.HasSeparateRenderTargetBlendState = true;
|
limits.HasSeparateRenderTargetBlendState = true;
|
||||||
limits.HasDepthAsSRV = true;
|
limits.HasDepthAsSRV = true;
|
||||||
|
limits.HasDepthClip = true;
|
||||||
limits.HasReadOnlyDepth = true;
|
limits.HasReadOnlyDepth = true;
|
||||||
limits.HasMultisampleDepthAsSRV = true;
|
limits.HasMultisampleDepthAsSRV = true;
|
||||||
limits.HasTypedUAVLoad = featureDataD3D11Options2.TypedUAVLoadAdditionalFormats != 0;
|
limits.HasTypedUAVLoad = featureDataD3D11Options2.TypedUAVLoadAdditionalFormats != 0;
|
||||||
@@ -382,6 +383,7 @@ bool GPUDeviceDX11::Init()
|
|||||||
limits.HasAppendConsumeBuffers = false;
|
limits.HasAppendConsumeBuffers = false;
|
||||||
limits.HasSeparateRenderTargetBlendState = false;
|
limits.HasSeparateRenderTargetBlendState = false;
|
||||||
limits.HasDepthAsSRV = false;
|
limits.HasDepthAsSRV = false;
|
||||||
|
limits.HasDepthClip = true;
|
||||||
limits.HasReadOnlyDepth = createdFeatureLevel == D3D_FEATURE_LEVEL_10_1;
|
limits.HasReadOnlyDepth = createdFeatureLevel == D3D_FEATURE_LEVEL_10_1;
|
||||||
limits.HasMultisampleDepthAsSRV = false;
|
limits.HasMultisampleDepthAsSRV = false;
|
||||||
limits.HasTypedUAVLoad = false;
|
limits.HasTypedUAVLoad = false;
|
||||||
|
|||||||
@@ -381,6 +381,7 @@ bool GPUDeviceDX12::Init()
|
|||||||
limits.HasAppendConsumeBuffers = true;
|
limits.HasAppendConsumeBuffers = true;
|
||||||
limits.HasSeparateRenderTargetBlendState = true;
|
limits.HasSeparateRenderTargetBlendState = true;
|
||||||
limits.HasDepthAsSRV = true;
|
limits.HasDepthAsSRV = true;
|
||||||
|
limits.HasDepthClip = true;
|
||||||
limits.HasReadOnlyDepth = true;
|
limits.HasReadOnlyDepth = true;
|
||||||
limits.HasMultisampleDepthAsSRV = true;
|
limits.HasMultisampleDepthAsSRV = true;
|
||||||
limits.HasTypedUAVLoad = options.TypedUAVLoadAdditionalFormats != 0;
|
limits.HasTypedUAVLoad = options.TypedUAVLoadAdditionalFormats != 0;
|
||||||
|
|||||||
@@ -50,18 +50,7 @@ bool GPUDeviceNull::Init()
|
|||||||
// Init device limits
|
// Init device limits
|
||||||
{
|
{
|
||||||
auto& limits = Limits;
|
auto& limits = Limits;
|
||||||
limits.HasCompute = false;
|
Platform::MemoryClear(&limits, sizeof(limits));
|
||||||
limits.HasTessellation = false;
|
|
||||||
limits.HasGeometryShaders = false;
|
|
||||||
limits.HasInstancing = false;
|
|
||||||
limits.HasVolumeTextureRendering = false;
|
|
||||||
limits.HasDrawIndirect = false;
|
|
||||||
limits.HasAppendConsumeBuffers = false;
|
|
||||||
limits.HasSeparateRenderTargetBlendState = false;
|
|
||||||
limits.HasDepthAsSRV = false;
|
|
||||||
limits.HasReadOnlyDepth = false;
|
|
||||||
limits.HasMultisampleDepthAsSRV = false;
|
|
||||||
limits.HasTypedUAVLoad = false;
|
|
||||||
limits.MaximumMipLevelsCount = 14;
|
limits.MaximumMipLevelsCount = 14;
|
||||||
limits.MaximumTexture1DSize = 8192;
|
limits.MaximumTexture1DSize = 8192;
|
||||||
limits.MaximumTexture1DArraySize = 512;
|
limits.MaximumTexture1DArraySize = 512;
|
||||||
@@ -70,11 +59,8 @@ bool GPUDeviceNull::Init()
|
|||||||
limits.MaximumTexture3DSize = 2048;
|
limits.MaximumTexture3DSize = 2048;
|
||||||
limits.MaximumTextureCubeSize = 16384;
|
limits.MaximumTextureCubeSize = 16384;
|
||||||
limits.MaximumSamplerAnisotropy = 1;
|
limits.MaximumSamplerAnisotropy = 1;
|
||||||
|
|
||||||
for (int32 i = 0; i < static_cast<int32>(PixelFormat::MAX); i++)
|
for (int32 i = 0; i < static_cast<int32>(PixelFormat::MAX); i++)
|
||||||
{
|
|
||||||
FeaturesPerFormat[i] = FormatFeatures(static_cast<PixelFormat>(i), MSAALevel::None, FormatSupport::None);
|
FeaturesPerFormat[i] = FormatFeatures(static_cast<PixelFormat>(i), MSAALevel::None, FormatSupport::None);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create main context
|
// Create main context
|
||||||
|
|||||||
@@ -1210,16 +1210,16 @@ void GPUContextVulkan::ResolveMultisample(GPUTexture* sourceMultisampleTexture,
|
|||||||
|
|
||||||
void GPUContextVulkan::DrawInstanced(uint32 verticesCount, uint32 instanceCount, int32 startInstance, int32 startVertex)
|
void GPUContextVulkan::DrawInstanced(uint32 verticesCount, uint32 instanceCount, int32 startInstance, int32 startVertex)
|
||||||
{
|
{
|
||||||
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
|
|
||||||
OnDrawCall();
|
OnDrawCall();
|
||||||
|
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
|
||||||
vkCmdDraw(cmdBuffer->GetHandle(), verticesCount, instanceCount, startVertex, startInstance);
|
vkCmdDraw(cmdBuffer->GetHandle(), verticesCount, instanceCount, startVertex, startInstance);
|
||||||
RENDER_STAT_DRAW_CALL(verticesCount * instanceCount, verticesCount * instanceCount / 3);
|
RENDER_STAT_DRAW_CALL(verticesCount * instanceCount, verticesCount * instanceCount / 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPUContextVulkan::DrawIndexedInstanced(uint32 indicesCount, uint32 instanceCount, int32 startInstance, int32 startVertex, int32 startIndex)
|
void GPUContextVulkan::DrawIndexedInstanced(uint32 indicesCount, uint32 instanceCount, int32 startInstance, int32 startVertex, int32 startIndex)
|
||||||
{
|
{
|
||||||
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
|
|
||||||
OnDrawCall();
|
OnDrawCall();
|
||||||
|
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
|
||||||
vkCmdDrawIndexed(cmdBuffer->GetHandle(), indicesCount, instanceCount, startIndex, startVertex, startInstance);
|
vkCmdDrawIndexed(cmdBuffer->GetHandle(), indicesCount, instanceCount, startIndex, startVertex, startInstance);
|
||||||
RENDER_STAT_DRAW_CALL(0, indicesCount / 3 * instanceCount);
|
RENDER_STAT_DRAW_CALL(0, indicesCount / 3 * instanceCount);
|
||||||
}
|
}
|
||||||
@@ -1227,10 +1227,9 @@ void GPUContextVulkan::DrawIndexedInstanced(uint32 indicesCount, uint32 instance
|
|||||||
void GPUContextVulkan::DrawInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs)
|
void GPUContextVulkan::DrawInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs)
|
||||||
{
|
{
|
||||||
ASSERT(bufferForArgs && EnumHasAnyFlags(bufferForArgs->GetFlags(), GPUBufferFlags::Argument));
|
ASSERT(bufferForArgs && EnumHasAnyFlags(bufferForArgs->GetFlags(), GPUBufferFlags::Argument));
|
||||||
|
OnDrawCall();
|
||||||
auto bufferForArgsVK = (GPUBufferVulkan*)bufferForArgs;
|
auto bufferForArgsVK = (GPUBufferVulkan*)bufferForArgs;
|
||||||
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
|
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
|
||||||
OnDrawCall();
|
|
||||||
vkCmdDrawIndirect(cmdBuffer->GetHandle(), bufferForArgsVK->GetHandle(), (VkDeviceSize)offsetForArgs, 1, sizeof(VkDrawIndirectCommand));
|
vkCmdDrawIndirect(cmdBuffer->GetHandle(), bufferForArgsVK->GetHandle(), (VkDeviceSize)offsetForArgs, 1, sizeof(VkDrawIndirectCommand));
|
||||||
RENDER_STAT_DRAW_CALL(0, 0);
|
RENDER_STAT_DRAW_CALL(0, 0);
|
||||||
}
|
}
|
||||||
@@ -1238,10 +1237,9 @@ void GPUContextVulkan::DrawInstancedIndirect(GPUBuffer* bufferForArgs, uint32 of
|
|||||||
void GPUContextVulkan::DrawIndexedInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs)
|
void GPUContextVulkan::DrawIndexedInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs)
|
||||||
{
|
{
|
||||||
ASSERT(bufferForArgs && EnumHasAnyFlags(bufferForArgs->GetFlags(), GPUBufferFlags::Argument));
|
ASSERT(bufferForArgs && EnumHasAnyFlags(bufferForArgs->GetFlags(), GPUBufferFlags::Argument));
|
||||||
|
OnDrawCall();
|
||||||
auto bufferForArgsVK = (GPUBufferVulkan*)bufferForArgs;
|
auto bufferForArgsVK = (GPUBufferVulkan*)bufferForArgs;
|
||||||
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
|
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
|
||||||
OnDrawCall();
|
|
||||||
vkCmdDrawIndexedIndirect(cmdBuffer->GetHandle(), bufferForArgsVK->GetHandle(), (VkDeviceSize)offsetForArgs, 1, sizeof(VkDrawIndexedIndirectCommand));
|
vkCmdDrawIndexedIndirect(cmdBuffer->GetHandle(), bufferForArgsVK->GetHandle(), (VkDeviceSize)offsetForArgs, 1, sizeof(VkDrawIndexedIndirectCommand));
|
||||||
RENDER_STAT_DRAW_CALL(0, 0);
|
RENDER_STAT_DRAW_CALL(0, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1704,6 +1704,7 @@ bool GPUDeviceVulkan::Init()
|
|||||||
limits.HasDrawIndirect = PhysicalDeviceLimits.maxDrawIndirectCount >= 1;
|
limits.HasDrawIndirect = PhysicalDeviceLimits.maxDrawIndirectCount >= 1;
|
||||||
limits.HasAppendConsumeBuffers = false; // TODO: add Append Consume buffers support for Vulkan
|
limits.HasAppendConsumeBuffers = false; // TODO: add Append Consume buffers support for Vulkan
|
||||||
limits.HasSeparateRenderTargetBlendState = true;
|
limits.HasSeparateRenderTargetBlendState = true;
|
||||||
|
limits.HasDepthClip = PhysicalDeviceFeatures.depthClamp;
|
||||||
limits.HasDepthAsSRV = true;
|
limits.HasDepthAsSRV = true;
|
||||||
limits.HasReadOnlyDepth = true;
|
limits.HasReadOnlyDepth = true;
|
||||||
limits.HasMultisampleDepthAsSRV = !!PhysicalDeviceFeatures.sampleRateShading;
|
limits.HasMultisampleDepthAsSRV = !!PhysicalDeviceFeatures.sampleRateShading;
|
||||||
|
|||||||
@@ -340,7 +340,7 @@ bool GPUPipelineStateVulkan::Init(const Description& desc)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_descRasterization.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
_descRasterization.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
||||||
_descRasterization.depthClampEnable = !desc.DepthClipEnable;
|
_descRasterization.depthClampEnable = !desc.DepthClipEnable && _device->Limits.HasDepthClip;
|
||||||
_descRasterization.lineWidth = 1.0f;
|
_descRasterization.lineWidth = 1.0f;
|
||||||
_desc.pRasterizationState = &_descRasterization;
|
_desc.pRasterizationState = &_descRasterization;
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ void GPUTimerQueryVulkan::Interrupt(CmdBufferVulkan* cmdBuffer)
|
|||||||
if (!_interrupted)
|
if (!_interrupted)
|
||||||
{
|
{
|
||||||
_interrupted = true;
|
_interrupted = true;
|
||||||
WriteTimestamp(cmdBuffer, _queries[_queryIndex].End);
|
WriteTimestamp(cmdBuffer, _queries[_queryIndex].End, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ void GPUTimerQueryVulkan::Resume(CmdBufferVulkan* cmdBuffer)
|
|||||||
e.End.Pool = nullptr;
|
e.End.Pool = nullptr;
|
||||||
|
|
||||||
_interrupted = false;
|
_interrupted = false;
|
||||||
WriteTimestamp(cmdBuffer, e.Begin);
|
WriteTimestamp(cmdBuffer, e.Begin, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
||||||
|
|
||||||
_queries.Add(e);
|
_queries.Add(e);
|
||||||
_queryIndex++;
|
_queryIndex++;
|
||||||
@@ -56,13 +56,13 @@ bool GPUTimerQueryVulkan::GetResult(Query& query)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPUTimerQueryVulkan::WriteTimestamp(CmdBufferVulkan* cmdBuffer, Query& query) const
|
void GPUTimerQueryVulkan::WriteTimestamp(CmdBufferVulkan* cmdBuffer, Query& query, VkPipelineStageFlagBits stage) const
|
||||||
{
|
{
|
||||||
auto pool = _device->FindAvailableTimestampQueryPool();
|
auto pool = _device->FindAvailableTimestampQueryPool();
|
||||||
uint32 index;
|
uint32 index;
|
||||||
pool->AcquireQuery(index);
|
pool->AcquireQuery(index);
|
||||||
|
|
||||||
vkCmdWriteTimestamp(cmdBuffer->GetHandle(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, pool->GetHandle(), index);
|
vkCmdWriteTimestamp(cmdBuffer->GetHandle(), stage, pool->GetHandle(), index);
|
||||||
pool->MarkQueryAsStarted(index);
|
pool->MarkQueryAsStarted(index);
|
||||||
|
|
||||||
query.Pool = pool;
|
query.Pool = pool;
|
||||||
@@ -168,7 +168,7 @@ void GPUTimerQueryVulkan::Begin()
|
|||||||
|
|
||||||
_queryIndex = 0;
|
_queryIndex = 0;
|
||||||
_interrupted = false;
|
_interrupted = false;
|
||||||
WriteTimestamp(cmdBuffer, e.Begin);
|
WriteTimestamp(cmdBuffer, e.Begin, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
||||||
context->GetCmdBufferManager()->OnQueryBegin(this);
|
context->GetCmdBufferManager()->OnQueryBegin(this);
|
||||||
|
|
||||||
ASSERT(_queries.IsEmpty());
|
ASSERT(_queries.IsEmpty());
|
||||||
@@ -193,7 +193,7 @@ void GPUTimerQueryVulkan::End()
|
|||||||
|
|
||||||
if (!_interrupted)
|
if (!_interrupted)
|
||||||
{
|
{
|
||||||
WriteTimestamp(cmdBuffer, _queries[_queryIndex].End);
|
WriteTimestamp(cmdBuffer, _queries[_queryIndex].End, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
|
||||||
}
|
}
|
||||||
context->GetCmdBufferManager()->OnQueryEnd(this);
|
context->GetCmdBufferManager()->OnQueryEnd(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
bool GetResult(Query& query);
|
bool GetResult(Query& query);
|
||||||
void WriteTimestamp(CmdBufferVulkan* cmdBuffer, Query& query) const;
|
void WriteTimestamp(CmdBufferVulkan* cmdBuffer, Query& query, VkPipelineStageFlagBits stage) const;
|
||||||
bool TryGetResult();
|
bool TryGetResult();
|
||||||
bool UseQueries();
|
bool UseQueries();
|
||||||
|
|
||||||
|
|||||||
@@ -258,18 +258,32 @@ void NetworkReplicationService::Dispose()
|
|||||||
|
|
||||||
NetworkReplicationService NetworkReplicationServiceInstance;
|
NetworkReplicationService NetworkReplicationServiceInstance;
|
||||||
|
|
||||||
void INetworkSerializable_Serialize(void* instance, NetworkStream* stream, void* tag)
|
void INetworkSerializable_Native_Serialize(void* instance, NetworkStream* stream, void* tag)
|
||||||
{
|
{
|
||||||
const int16 vtableOffset = (int16)(intptr)tag;
|
const int16 vtableOffset = (int16)(intptr)tag;
|
||||||
((INetworkSerializable*)((byte*)instance + vtableOffset))->Serialize(stream);
|
((INetworkSerializable*)((byte*)instance + vtableOffset))->Serialize(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void INetworkSerializable_Deserialize(void* instance, NetworkStream* stream, void* tag)
|
void INetworkSerializable_Native_Deserialize(void* instance, NetworkStream* stream, void* tag)
|
||||||
{
|
{
|
||||||
const int16 vtableOffset = (int16)(intptr)tag;
|
const int16 vtableOffset = (int16)(intptr)tag;
|
||||||
((INetworkSerializable*)((byte*)instance + vtableOffset))->Deserialize(stream);
|
((INetworkSerializable*)((byte*)instance + vtableOffset))->Deserialize(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void INetworkSerializable_Script_Serialize(void* instance, NetworkStream* stream, void* tag)
|
||||||
|
{
|
||||||
|
auto obj = (ScriptingObject*)instance;
|
||||||
|
auto interface = ScriptingObject::ToInterface<INetworkSerializable>(obj);
|
||||||
|
interface->Serialize(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void INetworkSerializable_Script_Deserialize(void* instance, NetworkStream* stream, void* tag)
|
||||||
|
{
|
||||||
|
auto obj = (ScriptingObject*)instance;
|
||||||
|
auto interface = ScriptingObject::ToInterface<INetworkSerializable>(obj);
|
||||||
|
interface->Deserialize(stream);
|
||||||
|
}
|
||||||
|
|
||||||
NetworkReplicatedObject* ResolveObject(Guid objectId)
|
NetworkReplicatedObject* ResolveObject(Guid objectId)
|
||||||
{
|
{
|
||||||
auto it = Objects.Find(objectId);
|
auto it = Objects.Find(objectId);
|
||||||
@@ -1064,9 +1078,21 @@ bool NetworkReplicator::InvokeSerializer(const ScriptingTypeHandle& typeHandle,
|
|||||||
const ScriptingType::InterfaceImplementation* interface = type.GetInterface(INetworkSerializable::TypeInitializer);
|
const ScriptingType::InterfaceImplementation* interface = type.GetInterface(INetworkSerializable::TypeInitializer);
|
||||||
if (interface)
|
if (interface)
|
||||||
{
|
{
|
||||||
serializer.Methods[0] = INetworkSerializable_Serialize;
|
if (interface->IsNative)
|
||||||
serializer.Methods[1] = INetworkSerializable_Deserialize;
|
{
|
||||||
serializer.Tags[0] = serializer.Tags[1] = (void*)(intptr)interface->VTableOffset; // Pass VTableOffset to the callback
|
// Native interface (implemented in C++)
|
||||||
|
serializer.Methods[0] = INetworkSerializable_Native_Serialize;
|
||||||
|
serializer.Methods[1] = INetworkSerializable_Native_Deserialize;
|
||||||
|
serializer.Tags[0] = serializer.Tags[1] = (void*)(intptr)interface->VTableOffset; // Pass VTableOffset to the callback
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Generic interface (implemented in C# or elsewhere)
|
||||||
|
ASSERT(type.Type == ScriptingTypes::Script);
|
||||||
|
serializer.Methods[0] = INetworkSerializable_Script_Serialize;
|
||||||
|
serializer.Methods[1] = INetworkSerializable_Script_Deserialize;
|
||||||
|
serializer.Tags[0] = serializer.Tags[1] = nullptr;
|
||||||
|
}
|
||||||
SerializersTable.Add(typeHandle, serializer);
|
SerializersTable.Add(typeHandle, serializer);
|
||||||
}
|
}
|
||||||
else if (const ScriptingTypeHandle baseTypeHandle = typeHandle.GetType().GetBaseType())
|
else if (const ScriptingTypeHandle baseTypeHandle = typeHandle.GetType().GetBaseType())
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace FlaxEngine
|
|||||||
/// <param name="convexFlags">The convex mesh generation flags.</param>
|
/// <param name="convexFlags">The convex mesh generation flags.</param>
|
||||||
/// <param name="convexVertexLimit">The convex mesh vertex limit. Use values in range [8;255]</param>
|
/// <param name="convexVertexLimit">The convex mesh vertex limit. Use values in range [8;255]</param>
|
||||||
/// <returns>True if failed, otherwise false.</returns>
|
/// <returns>True if failed, otherwise false.</returns>
|
||||||
[Obsolete("Deprecated in 1.4")]
|
[Obsolete("Deprecated in 1.4, use overload with Float3 and Float2 parameters")]
|
||||||
public bool CookCollision(CollisionDataType type, Vector3[] vertices, uint[] triangles, ConvexMeshGenerationFlags convexFlags = ConvexMeshGenerationFlags.None, int convexVertexLimit = 255)
|
public bool CookCollision(CollisionDataType type, Vector3[] vertices, uint[] triangles, ConvexMeshGenerationFlags convexFlags = ConvexMeshGenerationFlags.None, int convexVertexLimit = 255)
|
||||||
{
|
{
|
||||||
if (vertices == null)
|
if (vertices == null)
|
||||||
@@ -43,7 +43,7 @@ namespace FlaxEngine
|
|||||||
/// <param name="convexFlags">The convex mesh generation flags.</param>
|
/// <param name="convexFlags">The convex mesh generation flags.</param>
|
||||||
/// <param name="convexVertexLimit">The convex mesh vertex limit. Use values in range [8;255]</param>
|
/// <param name="convexVertexLimit">The convex mesh vertex limit. Use values in range [8;255]</param>
|
||||||
/// <returns>True if failed, otherwise false.</returns>
|
/// <returns>True if failed, otherwise false.</returns>
|
||||||
[Obsolete("Deprecated in 1.4")]
|
[Obsolete("Deprecated in 1.4, use overload with Float3 and Float2 parameters")]
|
||||||
public bool CookCollision(CollisionDataType type, Vector3[] vertices, int[] triangles, ConvexMeshGenerationFlags convexFlags = ConvexMeshGenerationFlags.None, int convexVertexLimit = 255)
|
public bool CookCollision(CollisionDataType type, Vector3[] vertices, int[] triangles, ConvexMeshGenerationFlags convexFlags = ConvexMeshGenerationFlags.None, int convexVertexLimit = 255)
|
||||||
{
|
{
|
||||||
if (vertices == null)
|
if (vertices == null)
|
||||||
@@ -60,7 +60,7 @@ namespace FlaxEngine
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vertexBuffer">The output vertex buffer.</param>
|
/// <param name="vertexBuffer">The output vertex buffer.</param>
|
||||||
/// <param name="indexBuffer">The output index buffer.</param>
|
/// <param name="indexBuffer">The output index buffer.</param>
|
||||||
[Obsolete("Deprecated in 1.4")]
|
[Obsolete("Deprecated in 1.4, use overload with Float3 and Float2 parameters")]
|
||||||
public void ExtractGeometry(out Vector3[] vertexBuffer, out int[] indexBuffer)
|
public void ExtractGeometry(out Vector3[] vertexBuffer, out int[] indexBuffer)
|
||||||
{
|
{
|
||||||
ExtractGeometry(out Float3[] tmp, out indexBuffer);
|
ExtractGeometry(out Float3[] tmp, out indexBuffer);
|
||||||
|
|||||||
@@ -69,7 +69,30 @@ bool LinuxFileSystem::ShowOpenFileDialog(Window* parentWindow, const StringView&
|
|||||||
}
|
}
|
||||||
FILE* f = popen(cmd, "r");
|
FILE* f = popen(cmd, "r");
|
||||||
char buf[2048];
|
char buf[2048];
|
||||||
fgets(buf, ARRAY_COUNT(buf), f);
|
char* writePointer = buf;
|
||||||
|
int remainingCapacity = ARRAY_COUNT(buf);
|
||||||
|
// make sure we read all output from kdialog
|
||||||
|
while (remainingCapacity > 0 && fgets(writePointer, remainingCapacity, f))
|
||||||
|
{
|
||||||
|
int r = strlen(writePointer);
|
||||||
|
writePointer += r;
|
||||||
|
remainingCapacity -= r;
|
||||||
|
}
|
||||||
|
if (remainingCapacity <= 0)
|
||||||
|
{
|
||||||
|
LOG(Error, "You selected more files than an internal buffer can hold. Try selecting fewer files at a time.");
|
||||||
|
// in case of an overflow we miss the closing null byte, add it after the rightmost linefeed
|
||||||
|
while (*writePointer != '\n')
|
||||||
|
{
|
||||||
|
writePointer--;
|
||||||
|
if (writePointer == buf)
|
||||||
|
{
|
||||||
|
*buf = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*(++writePointer) = 0;
|
||||||
|
}
|
||||||
int result = pclose(f);
|
int result = pclose(f);
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -108,8 +108,7 @@ WindowsWindow::WindowsWindow(const CreateWindowSettings& settings)
|
|||||||
style |= WS_BORDER | WS_CAPTION | WS_DLGFRAME | WS_SYSMENU | WS_THICKFRAME | WS_GROUP;
|
style |= WS_BORDER | WS_CAPTION | WS_DLGFRAME | WS_SYSMENU | WS_THICKFRAME | WS_GROUP;
|
||||||
#elif WINDOWS_USE_NEWER_BORDER_LESS
|
#elif WINDOWS_USE_NEWER_BORDER_LESS
|
||||||
if (settings.IsRegularWindow)
|
if (settings.IsRegularWindow)
|
||||||
style |= WS_THICKFRAME | WS_SYSMENU;
|
style |= WS_THICKFRAME | WS_SYSMENU | WS_CAPTION;
|
||||||
style |= WS_CAPTION;
|
|
||||||
#endif
|
#endif
|
||||||
exStyle |= WS_EX_WINDOWEDGE;
|
exStyle |= WS_EX_WINDOWEDGE;
|
||||||
}
|
}
|
||||||
@@ -220,12 +219,6 @@ void WindowsWindow::Show()
|
|||||||
if (!_settings.HasBorder)
|
if (!_settings.HasBorder)
|
||||||
{
|
{
|
||||||
SetWindowPos(_handle, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER);
|
SetWindowPos(_handle, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER);
|
||||||
if (!_settings.IsRegularWindow && _settings.ShowAfterFirstPaint && _settings.StartPosition == WindowStartPosition::Manual)
|
|
||||||
{
|
|
||||||
int32 x = Math::TruncToInt(_settings.Position.X);
|
|
||||||
int32 y = Math::TruncToInt(_settings.Position.Y);
|
|
||||||
SetWindowPos(_handle, nullptr, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "Engine/Graphics/PixelFormatExtensions.h"
|
#include "Engine/Graphics/PixelFormatExtensions.h"
|
||||||
#include "Engine/Content/Content.h"
|
#include "Engine/Content/Content.h"
|
||||||
#include "Engine/Graphics/GPUContext.h"
|
#include "Engine/Graphics/GPUContext.h"
|
||||||
|
#include "Engine/Scripting/Enums.h"
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
#include "Engine/Renderer/Lightmaps.h"
|
#include "Engine/Renderer/Lightmaps.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -86,11 +87,12 @@ bool ShadowsPass::Init()
|
|||||||
const auto formatFeaturesTexture = GPUDevice::Instance->GetFormatFeatures(formatTexture);
|
const auto formatFeaturesTexture = GPUDevice::Instance->GetFormatFeatures(formatTexture);
|
||||||
_supportsShadows = EnumHasAllFlags(formatFeaturesDepth.Support, FormatSupport::DepthStencil | FormatSupport::Texture2D)
|
_supportsShadows = EnumHasAllFlags(formatFeaturesDepth.Support, FormatSupport::DepthStencil | FormatSupport::Texture2D)
|
||||||
&& EnumHasAllFlags(formatFeaturesTexture.Support, FormatSupport::ShaderSample | FormatSupport::ShaderSampleComparison);
|
&& EnumHasAllFlags(formatFeaturesTexture.Support, FormatSupport::ShaderSample | FormatSupport::ShaderSampleComparison);
|
||||||
|
// TODO: fallback to 32-bit shadow map format if 16-bit is not supported
|
||||||
if (!_supportsShadows)
|
if (!_supportsShadows)
|
||||||
{
|
{
|
||||||
LOG(Warning, "GPU doesn't support shadows rendering");
|
LOG(Warning, "GPU doesn't support shadows rendering");
|
||||||
LOG(Warning, "Format: {0}, features support: {1}", (int32)SHADOW_MAPS_FORMAT, (uint32)formatFeaturesDepth.Support);
|
LOG(Warning, "Format: {0}, features support: {1}", ScriptingEnum::ToString(SHADOW_MAPS_FORMAT), (uint32)formatFeaturesDepth.Support);
|
||||||
LOG(Warning, "Format: {0}, features support: {1}", (int32)formatTexture, (uint32)formatFeaturesTexture.Support);
|
LOG(Warning, "Format: {0}, features support: {1}", ScriptingEnum::ToString(formatTexture), (uint32)formatFeaturesTexture.Support);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -190,7 +190,6 @@ DEFINE_INTERNAL_CALL(bool) ScriptingInternal_IsTypeFromGameScripts(MTypeObject*
|
|||||||
|
|
||||||
DEFINE_INTERNAL_CALL(void) ScriptingInternal_FlushRemovedObjects()
|
DEFINE_INTERNAL_CALL(void) ScriptingInternal_FlushRemovedObjects()
|
||||||
{
|
{
|
||||||
ASSERT(IsInMainThread());
|
|
||||||
ObjectsRemovalService::Flush();
|
ObjectsRemovalService::Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#include "ManagedDictionary.h"
|
#include "ManagedDictionary.h"
|
||||||
|
|
||||||
|
#if USE_CSHARP
|
||||||
Dictionary<ManagedDictionary::KeyValueType, MTypeObject*> ManagedDictionary::CachedDictionaryTypes;
|
Dictionary<ManagedDictionary::KeyValueType, MTypeObject*> ManagedDictionary::CachedDictionaryTypes;
|
||||||
#if !USE_MONO_AOT
|
#if !USE_MONO_AOT
|
||||||
ManagedDictionary::MakeGenericTypeThunk ManagedDictionary::MakeGenericType;
|
ManagedDictionary::MakeGenericTypeThunk ManagedDictionary::MakeGenericType;
|
||||||
@@ -12,3 +15,4 @@ MMethod* ManagedDictionary::CreateInstance;
|
|||||||
MMethod* ManagedDictionary::AddDictionaryItem;
|
MMethod* ManagedDictionary::AddDictionaryItem;
|
||||||
MMethod* ManagedDictionary::GetDictionaryKeys;
|
MMethod* ManagedDictionary::GetDictionaryKeys;
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ private:
|
|||||||
MonoAssembly* _monoAssembly = nullptr;
|
MonoAssembly* _monoAssembly = nullptr;
|
||||||
MonoImage* _monoImage = nullptr;
|
MonoImage* _monoImage = nullptr;
|
||||||
#elif USE_NETCORE
|
#elif USE_NETCORE
|
||||||
StringAnsi _fullname;
|
|
||||||
void* _handle = nullptr;
|
void* _handle = nullptr;
|
||||||
|
StringAnsi _fullname;
|
||||||
#endif
|
#endif
|
||||||
MDomain* _domain;
|
MDomain* _domain;
|
||||||
|
|
||||||
@@ -50,6 +50,7 @@ public:
|
|||||||
/// <param name="name">The assembly name.</param>
|
/// <param name="name">The assembly name.</param>
|
||||||
MAssembly(MDomain* domain, const StringAnsiView& name);
|
MAssembly(MDomain* domain, const StringAnsiView& name);
|
||||||
|
|
||||||
|
#if USE_NETCORE
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="MAssembly"/> class.
|
/// Initializes a new instance of the <see cref="MAssembly"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -58,6 +59,7 @@ public:
|
|||||||
/// <param name="fullname">The assembly full name.</param>
|
/// <param name="fullname">The assembly full name.</param>
|
||||||
/// <param name="handle">The managed handle of the assembly.</param>
|
/// <param name="handle">The managed handle of the assembly.</param>
|
||||||
MAssembly(MDomain* domain, const StringAnsiView& name, const StringAnsiView& fullname, void* handle);
|
MAssembly(MDomain* domain, const StringAnsiView& name, const StringAnsiView& fullname, void* handle);
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finalizes an instance of the <see cref="MAssembly"/> class.
|
/// Finalizes an instance of the <see cref="MAssembly"/> class.
|
||||||
|
|||||||
@@ -48,18 +48,22 @@ MAssembly::MAssembly(MDomain* domain, const StringAnsiView& name)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if USE_NETCORE
|
||||||
|
|
||||||
MAssembly::MAssembly(MDomain* domain, const StringAnsiView& name, const StringAnsiView& fullname, void* handle)
|
MAssembly::MAssembly(MDomain* domain, const StringAnsiView& name, const StringAnsiView& fullname, void* handle)
|
||||||
: _domain(domain)
|
: _handle(handle)
|
||||||
|
, _fullname(fullname)
|
||||||
|
, _domain(domain)
|
||||||
, _isLoaded(false)
|
, _isLoaded(false)
|
||||||
, _isLoading(false)
|
, _isLoading(false)
|
||||||
, _hasCachedClasses(false)
|
, _hasCachedClasses(false)
|
||||||
, _reloadCount(0)
|
, _reloadCount(0)
|
||||||
, _name(name)
|
, _name(name)
|
||||||
, _fullname(fullname)
|
|
||||||
, _handle(handle)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
MAssembly::~MAssembly()
|
MAssembly::~MAssembly()
|
||||||
{
|
{
|
||||||
Unload();
|
Unload();
|
||||||
|
|||||||
@@ -41,12 +41,18 @@
|
|||||||
#include <mono/jit/mono-private-unstable.h>
|
#include <mono/jit/mono-private-unstable.h>
|
||||||
#include <mono/utils/mono-logger.h>
|
#include <mono/utils/mono-logger.h>
|
||||||
#include <mono/metadata/assembly.h>
|
#include <mono/metadata/assembly.h>
|
||||||
|
#include <mono/metadata/appdomain.h>
|
||||||
#include <mono/metadata/class.h>
|
#include <mono/metadata/class.h>
|
||||||
#include <mono/metadata/metadata.h>
|
#include <mono/metadata/metadata.h>
|
||||||
|
#include <mono/metadata/threads.h>
|
||||||
#include <mono/metadata/reflection.h>
|
#include <mono/metadata/reflection.h>
|
||||||
#include <mono/metadata/mono-private-unstable.h>
|
#include <mono/metadata/mono-private-unstable.h>
|
||||||
typedef char char_t;
|
typedef char char_t;
|
||||||
#define DOTNET_HOST_MONO_DEBUG 0
|
#define DOTNET_HOST_MONO_DEBUG 0
|
||||||
|
#ifdef USE_MONO_AOT_MODULE
|
||||||
|
void* MonoAotModuleHandle = nullptr;
|
||||||
|
#endif
|
||||||
|
MonoDomain* MonoDomainHandle = nullptr;
|
||||||
#else
|
#else
|
||||||
#error "Unknown .NET runtime host."
|
#error "Unknown .NET runtime host."
|
||||||
#endif
|
#endif
|
||||||
@@ -180,7 +186,7 @@ void* GetStaticMethodPointer(const String& methodName);
|
|||||||
/// Calls the managed static method in NativeInterop class with given parameters.
|
/// Calls the managed static method in NativeInterop class with given parameters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
template<typename RetType, typename... Args>
|
template<typename RetType, typename... Args>
|
||||||
inline RetType CallStaticMethodByName(const String& methodName, Args... args)
|
FORCE_INLINE RetType CallStaticMethodByName(const String& methodName, Args... args)
|
||||||
{
|
{
|
||||||
typedef RetType (CORECLR_DELEGATE_CALLTYPE* fun)(Args...);
|
typedef RetType (CORECLR_DELEGATE_CALLTYPE* fun)(Args...);
|
||||||
return ((fun)GetStaticMethodPointer(methodName))(args...);
|
return ((fun)GetStaticMethodPointer(methodName))(args...);
|
||||||
@@ -190,7 +196,7 @@ inline RetType CallStaticMethodByName(const String& methodName, Args... args)
|
|||||||
/// Calls the managed static method with given parameters.
|
/// Calls the managed static method with given parameters.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
template<typename RetType, typename... Args>
|
template<typename RetType, typename... Args>
|
||||||
inline RetType CallStaticMethod(void* methodPtr, Args... args)
|
FORCE_INLINE RetType CallStaticMethod(void* methodPtr, Args... args)
|
||||||
{
|
{
|
||||||
typedef RetType (CORECLR_DELEGATE_CALLTYPE* fun)(Args...);
|
typedef RetType (CORECLR_DELEGATE_CALLTYPE* fun)(Args...);
|
||||||
return ((fun)methodPtr)(args...);
|
return ((fun)methodPtr)(args...);
|
||||||
@@ -516,6 +522,12 @@ void MCore::GC::FreeMemory(void* ptr, bool coTaskMem)
|
|||||||
|
|
||||||
void MCore::Thread::Attach()
|
void MCore::Thread::Attach()
|
||||||
{
|
{
|
||||||
|
#if DOTNET_HOST_MONO
|
||||||
|
if (!IsInMainThread() && !mono_domain_get())
|
||||||
|
{
|
||||||
|
mono_thread_attach(MonoDomainHandle);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCore::Thread::Exit()
|
void MCore::Thread::Exit()
|
||||||
@@ -617,14 +629,33 @@ bool MCore::Type::IsReference(MType* type)
|
|||||||
|
|
||||||
void MCore::ScriptingObject::SetInternalValues(MClass* klass, MObject* object, void* unmanagedPtr, const Guid* id)
|
void MCore::ScriptingObject::SetInternalValues(MClass* klass, MObject* object, void* unmanagedPtr, const Guid* id)
|
||||||
{
|
{
|
||||||
|
#if PLATFORM_DESKTOP && !USE_MONO_AOT
|
||||||
static void* ScriptingObjectSetInternalValuesPtr = GetStaticMethodPointer(TEXT("ScriptingObjectSetInternalValues"));
|
static void* ScriptingObjectSetInternalValuesPtr = GetStaticMethodPointer(TEXT("ScriptingObjectSetInternalValues"));
|
||||||
CallStaticMethod<void, MObject*, void*, const Guid*>(ScriptingObjectSetInternalValuesPtr, object, unmanagedPtr, id);
|
CallStaticMethod<void, MObject*, void*, const Guid*>(ScriptingObjectSetInternalValuesPtr, object, unmanagedPtr, id);
|
||||||
|
#else
|
||||||
|
const MField* monoUnmanagedPtrField = klass->GetField("__unmanagedPtr");
|
||||||
|
if (monoUnmanagedPtrField)
|
||||||
|
monoUnmanagedPtrField->SetValue(object, &unmanagedPtr);
|
||||||
|
const MField* monoIdField = klass->GetField("__internalId");
|
||||||
|
if (id != nullptr && monoIdField)
|
||||||
|
monoIdField->SetValue(object, (void*)id);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
MObject* MCore::ScriptingObject::CreateScriptingObject(MClass* klass, void* unmanagedPtr, const Guid* id)
|
MObject* MCore::ScriptingObject::CreateScriptingObject(MClass* klass, void* unmanagedPtr, const Guid* id)
|
||||||
{
|
{
|
||||||
|
#if PLATFORM_DESKTOP && !USE_MONO_AOT
|
||||||
static void* ScriptingObjectSetInternalValuesPtr = GetStaticMethodPointer(TEXT("ScriptingObjectCreate"));
|
static void* ScriptingObjectSetInternalValuesPtr = GetStaticMethodPointer(TEXT("ScriptingObjectCreate"));
|
||||||
return CallStaticMethod<MObject*, void*, void*, const Guid*>(ScriptingObjectSetInternalValuesPtr, klass->_handle, unmanagedPtr, id);
|
return CallStaticMethod<MObject*, void*, void*, const Guid*>(ScriptingObjectSetInternalValuesPtr, klass->_handle, unmanagedPtr, id);
|
||||||
|
#else
|
||||||
|
MObject* object = MCore::Object::New(klass);
|
||||||
|
if (object)
|
||||||
|
{
|
||||||
|
MCore::ScriptingObject::SetInternalValues(klass, object, unmanagedPtr, id);
|
||||||
|
MCore::Object::Init(object);
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAssembly::ClassesDictionary& MAssembly::GetClasses() const
|
const MAssembly::ClassesDictionary& MAssembly::GetClasses() const
|
||||||
@@ -1241,8 +1272,8 @@ void MField::GetValue(MObject* instance, void* result) const
|
|||||||
|
|
||||||
void MField::GetValueReference(MObject* instance, void* result) const
|
void MField::GetValueReference(MObject* instance, void* result) const
|
||||||
{
|
{
|
||||||
static void* FieldGetValueReferencePtr = GetStaticMethodPointer(TEXT("FieldGetValueReferenceWithOffset"));
|
static void* FieldGetValueReferencePtr = GetStaticMethodPointer(TEXT("FieldGetValueReference"));
|
||||||
CallStaticMethod<void, void*, int, void*>(FieldGetValueReferencePtr, instance, _fieldOffset, result);
|
CallStaticMethod<void, void*, void*, int, void*>(FieldGetValueReferencePtr, instance, _handle, _fieldOffset, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
MObject* MField::GetValueBoxed(MObject* instance) const
|
MObject* MField::GetValueBoxed(MObject* instance) const
|
||||||
@@ -1767,11 +1798,6 @@ void* GetStaticMethodPointer(const String& methodName)
|
|||||||
|
|
||||||
#elif DOTNET_HOST_MONO
|
#elif DOTNET_HOST_MONO
|
||||||
|
|
||||||
#ifdef USE_MONO_AOT_MODULE
|
|
||||||
void* MonoAotModuleHandle = nullptr;
|
|
||||||
#endif
|
|
||||||
MonoDomain* MonoDomainHandle = nullptr;
|
|
||||||
|
|
||||||
void OnLogCallback(const char* logDomain, const char* logLevel, const char* message, mono_bool fatal, void* userData)
|
void OnLogCallback(const char* logDomain, const char* logLevel, const char* message, mono_bool fatal, void* userData)
|
||||||
{
|
{
|
||||||
String currentDomain(logDomain);
|
String currentDomain(logDomain);
|
||||||
|
|||||||
@@ -2157,7 +2157,7 @@ MObject* MCore::ScriptingObject::CreateScriptingObject(MClass* klass, void* unma
|
|||||||
if (managedInstance)
|
if (managedInstance)
|
||||||
{
|
{
|
||||||
// Set unmanaged object handle and id
|
// Set unmanaged object handle and id
|
||||||
MCore::ScriptingObject::SetInternalValues(klass, managedInstance, unmanagedPtr, _id);
|
MCore::ScriptingObject::SetInternalValues(klass, managedInstance, unmanagedPtr, id);
|
||||||
|
|
||||||
// Initialize managed instance (calls constructor)
|
// Initialize managed instance (calls constructor)
|
||||||
MCore::Object::Init(managedInstance);
|
MCore::Object::Init(managedInstance);
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#include "Engine/Scripting/Types.h"
|
#include "Engine/Scripting/Types.h"
|
||||||
|
|
||||||
#if !USE_CSHARP
|
#if !USE_CSHARP
|
||||||
|
#include "Engine/Core/Types/Span.h"
|
||||||
#include "Engine/Scripting/ManagedCLR/MCore.h"
|
#include "Engine/Scripting/ManagedCLR/MCore.h"
|
||||||
#include "Engine/Scripting/ManagedCLR/MDomain.h"
|
#include "Engine/Scripting/ManagedCLR/MDomain.h"
|
||||||
#include "Engine/Scripting/ManagedCLR/MAssembly.h"
|
#include "Engine/Scripting/ManagedCLR/MAssembly.h"
|
||||||
|
|||||||
@@ -493,9 +493,11 @@ bool Scripting::Load()
|
|||||||
flaxEngineModule->TypeNameToTypeIndex["FlaxEngine.Vector3"] = flaxEngineModule->TypeNameToTypeIndex["FlaxEngine.Float3"];
|
flaxEngineModule->TypeNameToTypeIndex["FlaxEngine.Vector3"] = flaxEngineModule->TypeNameToTypeIndex["FlaxEngine.Float3"];
|
||||||
flaxEngineModule->TypeNameToTypeIndex["FlaxEngine.Vector4"] = flaxEngineModule->TypeNameToTypeIndex["FlaxEngine.Float4"];
|
flaxEngineModule->TypeNameToTypeIndex["FlaxEngine.Vector4"] = flaxEngineModule->TypeNameToTypeIndex["FlaxEngine.Float4"];
|
||||||
#endif
|
#endif
|
||||||
|
#if USE_CSHARP
|
||||||
flaxEngineModule->ClassToTypeIndex[flaxEngineModule->Assembly->GetClass("FlaxEngine.Vector2")] = flaxEngineModule->TypeNameToTypeIndex["FlaxEngine.Vector2"];
|
flaxEngineModule->ClassToTypeIndex[flaxEngineModule->Assembly->GetClass("FlaxEngine.Vector2")] = flaxEngineModule->TypeNameToTypeIndex["FlaxEngine.Vector2"];
|
||||||
flaxEngineModule->ClassToTypeIndex[flaxEngineModule->Assembly->GetClass("FlaxEngine.Vector3")] = flaxEngineModule->TypeNameToTypeIndex["FlaxEngine.Vector3"];
|
flaxEngineModule->ClassToTypeIndex[flaxEngineModule->Assembly->GetClass("FlaxEngine.Vector3")] = flaxEngineModule->TypeNameToTypeIndex["FlaxEngine.Vector3"];
|
||||||
flaxEngineModule->ClassToTypeIndex[flaxEngineModule->Assembly->GetClass("FlaxEngine.Vector4")] = flaxEngineModule->TypeNameToTypeIndex["FlaxEngine.Vector4"];
|
flaxEngineModule->ClassToTypeIndex[flaxEngineModule->Assembly->GetClass("FlaxEngine.Vector4")] = flaxEngineModule->TypeNameToTypeIndex["FlaxEngine.Vector4"];
|
||||||
|
#endif
|
||||||
|
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
// Skip loading game modules in Editor on startup - Editor loads them later during splash screen (eg. after first compilation)
|
// Skip loading game modules in Editor on startup - Editor loads them later during splash screen (eg. after first compilation)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "BinaryModule.h"
|
#include "BinaryModule.h"
|
||||||
#include "Engine/Level/Actor.h"
|
#include "Engine/Level/Actor.h"
|
||||||
#include "Engine/Core/Log.h"
|
#include "Engine/Core/Log.h"
|
||||||
|
#include "Engine/Core/Types/Pair.h"
|
||||||
#include "Engine/Utilities/StringConverter.h"
|
#include "Engine/Utilities/StringConverter.h"
|
||||||
#include "Engine/Content/Asset.h"
|
#include "Engine/Content/Asset.h"
|
||||||
#include "Engine/Content/Content.h"
|
#include "Engine/Content/Content.h"
|
||||||
@@ -25,7 +26,8 @@
|
|||||||
#define ScriptingObject_id "__internalId"
|
#define ScriptingObject_id "__internalId"
|
||||||
|
|
||||||
// TODO: don't leak memory (use some kind of late manual GC for those wrapper objects)
|
// TODO: don't leak memory (use some kind of late manual GC for those wrapper objects)
|
||||||
Dictionary<ScriptingObject*, void*> ScriptingObjectsInterfaceWrappers;
|
typedef Pair<ScriptingObject*, ScriptingTypeHandle> ScriptingObjectsInterfaceKey;
|
||||||
|
Dictionary<ScriptingObjectsInterfaceKey, void*> ScriptingObjectsInterfaceWrappers;
|
||||||
|
|
||||||
SerializableScriptingObject::SerializableScriptingObject(const SpawnParams& params)
|
SerializableScriptingObject::SerializableScriptingObject(const SpawnParams& params)
|
||||||
: ScriptingObject(params)
|
: ScriptingObject(params)
|
||||||
@@ -202,10 +204,10 @@ ScriptingObject* ScriptingObject::FromInterface(void* interfaceObj, const Script
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Special case for interface wrapper object
|
// Special case for interface wrapper object
|
||||||
for (auto& e : ScriptingObjectsInterfaceWrappers)
|
for (const auto& e : ScriptingObjectsInterfaceWrappers)
|
||||||
{
|
{
|
||||||
if (e.Value == interfaceObj)
|
if (e.Value == interfaceObj)
|
||||||
return e.Key;
|
return e.Key.First;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -226,10 +228,11 @@ void* ScriptingObject::ToInterface(ScriptingObject* obj, const ScriptingTypeHand
|
|||||||
else if (interface)
|
else if (interface)
|
||||||
{
|
{
|
||||||
// Interface implemented in scripting (eg. C# class inherits C++ interface)
|
// Interface implemented in scripting (eg. C# class inherits C++ interface)
|
||||||
if (!ScriptingObjectsInterfaceWrappers.TryGet(obj, result))
|
const ScriptingObjectsInterfaceKey key(obj, interfaceType);
|
||||||
|
if (!ScriptingObjectsInterfaceWrappers.TryGet(key, result))
|
||||||
{
|
{
|
||||||
result = interfaceType.GetType().Interface.GetInterfaceWrapper(obj);
|
result = interfaceType.GetType().Interface.GetInterfaceWrapper(obj);
|
||||||
ScriptingObjectsInterfaceWrappers.Add(obj, result);
|
ScriptingObjectsInterfaceWrappers.Add(key, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -241,7 +244,7 @@ ScriptingObject* ScriptingObject::ToNative(MObject* obj)
|
|||||||
#if USE_CSHARP
|
#if USE_CSHARP
|
||||||
if (obj)
|
if (obj)
|
||||||
{
|
{
|
||||||
#if USE_MONO
|
#if USE_MONO || USE_MONO_AOT
|
||||||
const auto ptrField = MCore::Object::GetClass(obj)->GetField(ScriptingObject_unmanagedPtr);
|
const auto ptrField = MCore::Object::GetClass(obj)->GetField(ScriptingObject_unmanagedPtr);
|
||||||
CHECK_RETURN(ptrField, nullptr);
|
CHECK_RETURN(ptrField, nullptr);
|
||||||
ptrField->GetValue(obj, &ptr);
|
ptrField->GetValue(obj, &ptr);
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ void SpriteRender::Draw(RenderContext& renderContext)
|
|||||||
auto model = _quadModel.As<Model>();
|
auto model = _quadModel.As<Model>();
|
||||||
if (model->GetLoadedLODs() == 0)
|
if (model->GetLoadedLODs() == 0)
|
||||||
return;
|
return;
|
||||||
const auto& view = renderContext.View;
|
const auto& view = (renderContext.LodProxyView ? *renderContext.LodProxyView : renderContext.View);
|
||||||
Matrix m1, m2, m3, world;
|
Matrix m1, m2, m3, world;
|
||||||
Matrix::Scaling(_size.X, _size.Y, 1.0f, m2);
|
Matrix::Scaling(_size.X, _size.Y, 1.0f, m2);
|
||||||
Matrix::RotationY(PI, m3);
|
Matrix::RotationY(PI, m3);
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ UICanvas::UICanvas(const SpawnParams& params)
|
|||||||
UICanvas_EndPlay = mclass->GetMethod("EndPlay");
|
UICanvas_EndPlay = mclass->GetMethod("EndPlay");
|
||||||
UICanvas_ParentChanged = mclass->GetMethod("ParentChanged");
|
UICanvas_ParentChanged = mclass->GetMethod("ParentChanged");
|
||||||
UICanvas_Serialize = mclass->GetMethod("Serialize");
|
UICanvas_Serialize = mclass->GetMethod("Serialize");
|
||||||
|
Platform::MemoryBarrier();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user