Merge branch 'FlaxEngine:master' into model-prefab-fix

This commit is contained in:
Menotdan
2024-02-19 12:28:38 -05:00
committed by GitHub
70 changed files with 1103 additions and 333 deletions

1
.gitignore vendored
View File

@@ -11,7 +11,6 @@ Source/*.Gen.*
Source/*.csproj
/Package_*/
!Source/Engine/Debug
/Source/Platforms/Editor/Linux/Mono/etc/mono/registry
PackageEditor_Cert.command
PackageEditor_Cert.bat
PackagePlatforms_Cert.bat

BIN
Content/Editor/Fonts/NotoSansSC-Regular.flax (Stored with Git LFS) Normal file

Binary file not shown.

View File

@@ -73,8 +73,12 @@
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=TYPEDEF/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=UNION/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=UNION_005FMEMBER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AI/@EntryIndexedValue">AI</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LO/@EntryIndexedValue">LO</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RPC/@EntryIndexedValue">RPC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SDK/@EntryIndexedValue">SDK</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=VS/@EntryIndexedValue">VS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FCONSTANT/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FFUNCTION/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FVARIABLE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>

View File

@@ -69,8 +69,7 @@ namespace FlaxEditor.Content
/// <inheritdoc />
public override bool IsFileNameValid(string filename)
{
// Scripts cannot start with digit.
if (Char.IsDigit(filename[0]))
if (char.IsDigit(filename[0]))
return false;
if (filename.Equals("Script"))
return false;

View File

@@ -3,6 +3,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using FlaxEditor.Actions;
using FlaxEditor.Content;
using FlaxEditor.GUI;
@@ -16,6 +18,27 @@ using Object = FlaxEngine.Object;
namespace FlaxEditor.CustomEditors.Dedicated
{
internal class NewScriptItem : ItemsListContextMenu.Item
{
private string _scriptName;
public string ScriptName
{
get => _scriptName;
set
{
_scriptName = value;
Name = $"Create script '{value}'";
}
}
public NewScriptItem(string scriptName)
{
ScriptName = scriptName;
TooltipText = "Create a new script";
}
}
/// <summary>
/// Drag and drop scripts area control.
/// </summary>
@@ -74,7 +97,43 @@ namespace FlaxEditor.CustomEditors.Dedicated
{
cm.AddItem(new TypeSearchPopup.TypeItemView(scripts[i]));
}
cm.ItemClicked += item => AddScript((ScriptType)item.Tag);
cm.TextChanged += text =>
{
if (!IsValidScriptName(text))
return;
if (!cm.ItemsPanel.Children.Any(x => x.Visible && x is not NewScriptItem))
{
// If there are no visible items, that means the search failed so we can find the create script button or create one if it's the first time
var newScriptItem = (NewScriptItem)cm.ItemsPanel.Children.FirstOrDefault(x => x is NewScriptItem);
if (newScriptItem != null)
{
newScriptItem.Visible = true;
newScriptItem.ScriptName = text;
}
else
{
cm.AddItem(new NewScriptItem(text));
}
}
else
{
// Make sure to hide the create script button if there
var newScriptItem = cm.ItemsPanel.Children.FirstOrDefault(x => x is NewScriptItem);
if (newScriptItem != null)
newScriptItem.Visible = false;
}
};
cm.ItemClicked += item =>
{
if (item.Tag is ScriptType script)
{
AddScript(script);
}
else if (item is NewScriptItem newScriptItem)
{
CreateScript(newScriptItem);
}
};
cm.SortItems();
cm.Show(this, button.BottomLeft - new Float2((cm.Width - button.Width) / 2, 0));
}
@@ -113,6 +172,19 @@ namespace FlaxEditor.CustomEditors.Dedicated
return false;
}
private static bool IsValidScriptName(string text)
{
if (string.IsNullOrEmpty(text))
return false;
if (text.Contains(' '))
return false;
if (char.IsDigit(text[0]))
return false;
if (text.Any(c => !char.IsLetterOrDigit(c) && c != '_'))
return false;
return Editor.Instance.ContentDatabase.GetProxy("cs").IsFileNameValid(text);
}
/// <inheritdoc />
public override DragDropEffect OnDragEnter(ref Float2 location, DragData data)
{
@@ -163,6 +235,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
if (_dragScripts.HasValidDrag)
{
result = _dragScripts.Effect;
AddScripts(_dragScripts.Objects);
}
else if (_dragAssets.HasValidDrag)
@@ -177,7 +250,43 @@ namespace FlaxEditor.CustomEditors.Dedicated
return result;
}
private void AddScript(ScriptType item)
private void CreateScript(NewScriptItem item)
{
ScriptsEditor.NewScriptName = item.ScriptName;
var paths = Directory.GetFiles(Globals.ProjectSourceFolder, "*.Build.cs");
string moduleName = null;
foreach (var p in paths)
{
var file = File.ReadAllText(p);
if (!file.Contains("GameProjectTarget"))
continue; // Skip
if (file.Contains("Modules.Add(\"Game\")"))
{
// Assume Game represents the main game module
moduleName = "Game";
break;
}
}
// Ensure the path slashes are correct for the OS
var correctedPath = Path.GetFullPath(Globals.ProjectSourceFolder);
if (string.IsNullOrEmpty(moduleName))
{
var error = FileSystem.ShowBrowseFolderDialog(Editor.Instance.Windows.MainWindow, correctedPath, "Select a module folder to put the new script in", out moduleName);
if (error)
return;
}
var path = Path.Combine(Globals.ProjectSourceFolder, moduleName, item.ScriptName + ".cs");
Editor.Instance.ContentDatabase.GetProxy("cs").Create(path, null);
}
/// <summary>
/// Attach a script to the actor.
/// </summary>
/// <param name="item">The script.</param>
public void AddScript(ScriptType item)
{
var list = new List<ScriptType>(1) { item };
AddScripts(list);
@@ -224,16 +333,67 @@ namespace FlaxEditor.CustomEditors.Dedicated
private void AddScripts(List<ScriptType> items)
{
var actions = new List<IUndoAction>(4);
var actions = new List<IUndoAction>();
for (int i = 0; i < items.Count; i++)
{
var scriptType = items[i];
RequireScriptAttribute scriptAttribute = null;
if (scriptType.HasAttribute(typeof(RequireScriptAttribute), false))
{
foreach (var e in scriptType.GetAttributes(false))
{
if (e is not RequireScriptAttribute requireScriptAttribute)
continue;
scriptAttribute = requireScriptAttribute;
break;
}
}
// See if script requires a specific actor type
RequireActorAttribute actorAttribute = null;
if (scriptType.HasAttribute(typeof(RequireActorAttribute), false))
{
foreach (var e in scriptType.GetAttributes(false))
{
if (e is not RequireActorAttribute requireActorAttribute)
continue;
actorAttribute = requireActorAttribute;
break;
}
}
var actors = ScriptsEditor.ParentEditor.Values;
for (int j = 0; j < actors.Count; j++)
{
var actor = (Actor)actors[j];
// If required actor exists but is not this actor type then skip adding to actor
if (actorAttribute != null)
{
if (actor.GetType() != actorAttribute.RequiredType && !actor.GetType().IsSubclassOf(actorAttribute.RequiredType))
{
Editor.LogWarning($"`{Utilities.Utils.GetPropertyNameUI(scriptType.Name)}` not added to `{actor}` due to script requiring an Actor type of `{actorAttribute.RequiredType}`.");
continue;
}
}
actions.Add(AddRemoveScript.Add(actor, scriptType));
// Check if actor has required scripts and add them if the actor does not.
if (scriptAttribute != null)
{
foreach (var type in scriptAttribute.RequiredTypes)
{
if (!type.IsSubclassOf(typeof(Script)))
{
Editor.LogWarning($"`{Utilities.Utils.GetPropertyNameUI(type.Name)}` not added to `{actor}` due to the class not being a subclass of Script.");
continue;
}
if (actor.GetScript(type) != null)
continue;
actions.Add(AddRemoveScript.Add(actor, new ScriptType(type)));
}
}
}
}
@@ -440,6 +600,11 @@ namespace FlaxEditor.CustomEditors.Dedicated
/// <inheritdoc />
public override IEnumerable<object> UndoObjects => _scripts;
/// <summary>
/// Cached the newly created script name - used to add script after compilation.
/// </summary>
internal static string NewScriptName;
private void AddMissingScript(int index, LayoutElementsContainer layout)
{
var group = layout.Group("Missing script");
@@ -548,6 +713,21 @@ namespace FlaxEditor.CustomEditors.Dedicated
var dragArea = layout.CustomContainer<DragAreaControl>();
dragArea.CustomControl.ScriptsEditor = this;
// If the initialization is triggered by an editor recompilation, check if it was due to script generation from DragAreaControl
if (NewScriptName != null)
{
var script = Editor.Instance.CodeEditing.Scripts.Get().FirstOrDefault(x => x.Name == NewScriptName);
NewScriptName = null;
if (script != null)
{
dragArea.CustomControl.AddScript(script);
}
else
{
Editor.LogWarning("Failed to find newly created script.");
}
}
// No support for showing scripts from multiple actors that have different set of scripts
var scripts = (Script[])Values[0];
_scripts.Clear();
@@ -586,9 +766,61 @@ namespace FlaxEditor.CustomEditors.Dedicated
var scriptType = TypeUtils.GetObjectType(script);
var editor = CustomEditorsUtil.CreateEditor(scriptType, false);
// Check if actor has all the required scripts
bool hasAllRequirements = true;
if (scriptType.HasAttribute(typeof(RequireScriptAttribute), false))
{
RequireScriptAttribute scriptAttribute = null;
foreach (var e in scriptType.GetAttributes(false))
{
if (e is not RequireScriptAttribute requireScriptAttribute)
continue;
scriptAttribute = requireScriptAttribute;
}
if (scriptAttribute != null)
{
foreach (var type in scriptAttribute.RequiredTypes)
{
if (!type.IsSubclassOf(typeof(Script)))
continue;
var requiredScript = script.Actor.GetScript(type);
if (requiredScript == null)
{
Editor.LogWarning($"`{Utilities.Utils.GetPropertyNameUI(scriptType.Name)}` on `{script.Actor}` is missing a required Script of type `{type}`.");
hasAllRequirements = false;
}
}
}
}
if (scriptType.HasAttribute(typeof(RequireActorAttribute), false))
{
RequireActorAttribute attribute = null;
foreach (var e in scriptType.GetAttributes(false))
{
if (e is not RequireActorAttribute requireActorAttribute)
continue;
attribute = requireActorAttribute;
break;
}
if (attribute != null)
{
var actor = script.Actor;
if (actor.GetType() != attribute.RequiredType && !actor.GetType().IsSubclassOf(attribute.RequiredType))
{
Editor.LogWarning($"`{Utilities.Utils.GetPropertyNameUI(scriptType.Name)}` on `{script.Actor}` is missing a required Actor of type `{attribute.RequiredType}`.");
hasAllRequirements = false;
// Maybe call to remove script here?
}
}
}
// Create group
var title = Utilities.Utils.GetPropertyNameUI(scriptType.Name);
var group = layout.Group(title, editor);
if (!hasAllRequirements)
group.Panel.HeaderTextColor = FlaxEngine.GUI.Style.Current.Statusbar.Failed;
if ((Presenter.Features & FeatureFlags.CacheExpandedGroups) != 0)
{
if (Editor.Instance.ProjectCache.IsGroupToggled(title))

View File

@@ -54,6 +54,11 @@ namespace FlaxEditor
/// </summary>
public static string PrimaryFont = "Editor/Fonts/Roboto-Regular";
/// <summary>
/// The secondary (fallback) font to use for missing characters rendering (CJK - Chinese/Japanese/Korean characters).
/// </summary>
public static string FallbackFont = "Editor/Fonts/NotoSansSC-Regular";
/// <summary>
/// The Inconsolata Regular font.
/// </summary>

View File

@@ -189,6 +189,11 @@ namespace FlaxEditor.GUI
/// </summary>
public event Action<Item> ItemClicked;
/// <summary>
/// Event fired when search text in this popup menu gets changed.
/// </summary>
public event Action<string> TextChanged;
/// <summary>
/// The panel control where you should add your items.
/// </summary>
@@ -263,6 +268,7 @@ namespace FlaxEditor.GUI
UnlockChildrenRecursive();
PerformLayout(true);
_searchBox.Focus();
TextChanged?.Invoke(_searchBox.Text);
}
/// <summary>
@@ -439,6 +445,7 @@ namespace FlaxEditor.GUI
Hide();
return true;
case KeyboardKeys.ArrowDown:
{
if (RootWindow.FocusedControl == null)
{
// Focus search box if nothing is focused
@@ -447,20 +454,19 @@ namespace FlaxEditor.GUI
}
// Focus the first visible item or then next one
var items = GetVisibleItems();
var focusedIndex = items.IndexOf(focusedItem);
if (focusedIndex == -1)
focusedIndex = -1;
if (focusedIndex + 1 < items.Count)
{
var items = GetVisibleItems();
var focusedIndex = items.IndexOf(focusedItem);
if (focusedIndex == -1)
focusedIndex = -1;
if (focusedIndex + 1 < items.Count)
{
var item = items[focusedIndex + 1];
item.Focus();
_scrollPanel.ScrollViewTo(item);
return true;
}
var item = items[focusedIndex + 1];
item.Focus();
_scrollPanel.ScrollViewTo(item);
return true;
}
break;
}
case KeyboardKeys.ArrowUp:
if (focusedItem != null)
{

View File

@@ -43,8 +43,9 @@ namespace FlaxEditor.GUI
{
Depth = -1;
if (Height < Style.Current.FontMedium.Height)
Height = Style.Current.FontMedium.Height + 4;
var fontHeight = Style.Current.FontMedium.Height;
if (Height < fontHeight)
Height = fontHeight + 4;
}
/// <inheritdoc />

View File

@@ -536,6 +536,7 @@ namespace FlaxEditor.Modules
_menuFileRecompileScripts = cm.AddButton("Recompile scripts", inputOptions.RecompileScripts, ScriptsBuilder.Compile);
cm.AddSeparator();
cm.AddButton("Open project...", OpenProject);
cm.AddButton("Reload project", ReloadProject);
cm.AddSeparator();
cm.AddButton("Exit", "Alt+F4", () => Editor.Windows.MainWindow.Close(ClosingReason.User));
@@ -823,6 +824,13 @@ namespace FlaxEditor.Modules
}
}
private void ReloadProject()
{
// Open project, then close it
Editor.OpenProject(Editor.GameProject.ProjectPath);
Editor.Windows.MainWindow.Close(ClosingReason.User);
}
private void OnMenuFileShowHide(Control control)
{
if (control.Visible == false)

View File

@@ -172,9 +172,9 @@ namespace FlaxEditor.Options
set
{
if (value == null)
_outputLogFont = new FontReference(FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.InconsolataRegularFont), 10);
_outputLogFont = new FontReference(ConsoleFont, 10);
else if (!value.Font)
_outputLogFont.Font = FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.InconsolataRegularFont);
_outputLogFont.Font = ConsoleFont;
else
_outputLogFont = value;
}
@@ -237,11 +237,19 @@ namespace FlaxEditor.Options
public int NumberOfGameClientsToLaunch = 1;
private static FontAsset DefaultFont => FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.PrimaryFont);
private static FontAsset ConsoleFont => FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.InconsolataRegularFont);
private FontReference _titleFont = new FontReference(DefaultFont, 18);
private FontReference _largeFont = new FontReference(DefaultFont, 14);
private FontReference _mediumFont = new FontReference(DefaultFont, 9);
private FontReference _smallFont = new FontReference(DefaultFont, 9);
private FontReference _outputLogFont = new FontReference(FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.InconsolataRegularFont), 10);
private FontReference _outputLogFont = new FontReference(ConsoleFont, 10);
/// <summary>
/// The list of fallback fonts to use when main text font is missing certain characters. Empty to use fonts from GraphicsSettings.
/// </summary>
[EditorDisplay("Fonts"), EditorOrder(650)]
public FontAsset[] FallbackFonts = new FontAsset[1] { FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.FallbackFont) };
/// <summary>
/// Gets or sets the title font for editor UI.

View File

@@ -3,6 +3,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using FlaxEditor.Content.Settings;
using FlaxEditor.Modules;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -223,6 +225,12 @@ namespace FlaxEditor.Options
Style.Current = CreateDefaultStyle();
}
}
// Set fallback fonts
var fallbackFonts = Options.Interface.FallbackFonts;
if (fallbackFonts == null || fallbackFonts.Length == 0 || fallbackFonts.All(x => x == null))
fallbackFonts = GameSettings.Load<GraphicsSettings>().FallbackFonts;
Font.FallbackFonts = fallbackFonts;
}
/// <summary>

View File

@@ -7,11 +7,14 @@ using Real = System.Single;
#endif
using System;
using FlaxEditor.GUI.ContextMenu;
using System.Collections.Generic;
using FlaxEditor.Actions;
using FlaxEditor.Modules;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.Windows;
using FlaxEngine;
using FlaxEngine.Json;
using FlaxEngine.Utilities;
using Object = FlaxEngine.Object;
namespace FlaxEditor.SceneGraph.Actors
@@ -288,6 +291,8 @@ namespace FlaxEditor.SceneGraph.Actors
private const Real PointNodeSize = 1.5f;
private const Real TangentNodeSize = 1.0f;
private const Real SnapIndicatorSize = 1.7f;
private const Real SnapPointIndicatorSize = 2f;
/// <inheritdoc />
public SplineNode(Actor actor)
@@ -297,9 +302,26 @@ namespace FlaxEditor.SceneGraph.Actors
FlaxEngine.Scripting.Update += OnUpdate;
}
private unsafe void OnUpdate()
private void OnUpdate()
{
// If this node's point is selected
var selection = Editor.Instance.SceneEditing.Selection;
if (selection.Count == 1 && selection[0] is SplinePointNode selectedPoint && selectedPoint.ParentNode == this)
{
if (Input.Keyboard.GetKey(KeyboardKeys.Shift))
EditSplineWithSnap(selectedPoint);
var canAddSplinePoint = Input.Mouse.PositionDelta == Float2.Zero && Input.Mouse.Position != Float2.Zero;
var requestAddSplinePoint = Input.Keyboard.GetKey(KeyboardKeys.Control) && Input.Mouse.GetButtonDown(MouseButton.Right);
if (requestAddSplinePoint && canAddSplinePoint)
AddSplinePoint(selectedPoint);
}
SyncSplineKeyframeWithNodes();
}
private unsafe void SyncSplineKeyframeWithNodes()
{
// Sync spline points with gizmo handles
var actor = (Spline)Actor;
var dstCount = actor.SplinePointsCount;
if (dstCount > 1 && actor.IsLoop)
@@ -329,6 +351,119 @@ namespace FlaxEditor.SceneGraph.Actors
}
}
private unsafe void AddSplinePoint(SplinePointNode selectedPoint)
{
// Check mouse hit on scene
var spline = (Spline)Actor;
var viewport = Editor.Instance.Windows.EditWin.Viewport;
var mouseRay = viewport.MouseRay;
var viewRay = viewport.ViewRay;
var flags = RayCastData.FlagTypes.SkipColliders | RayCastData.FlagTypes.SkipEditorPrimitives;
var hit = Editor.Instance.Scene.Root.RayCast(ref mouseRay, ref viewRay, out var closest, out var normal, flags);
if (hit == null)
return;
// Undo data
var oldSpline = spline.SplineKeyframes;
var editAction = new EditSplineAction(spline, oldSpline);
Root.Undo.AddAction(editAction);
// Get spline point to duplicate
var hitPoint = mouseRay.Position + mouseRay.Direction * closest;
var lastPointIndex = selectedPoint.Index;
var newPointIndex = lastPointIndex > 0 ? lastPointIndex + 1 : 0;
var lastKeyframe = spline.GetSplineKeyframe(lastPointIndex);
var isLastPoint = lastPointIndex == spline.SplinePointsCount - 1;
var isFirstPoint = lastPointIndex == 0;
// Get data to create new point
var lastPointTime = spline.GetSplineTime(lastPointIndex);
var nextPointTime = isLastPoint ? lastPointTime : spline.GetSplineTime(newPointIndex);
var newTime = isLastPoint ? lastPointTime + 1.0f : (lastPointTime + nextPointTime) * 0.5f;
var distanceFromLastPoint = Vector3.Distance(hitPoint, spline.GetSplinePoint(lastPointIndex));
var newPointDirection = spline.GetSplineTangent(lastPointIndex, false).Translation - hitPoint;
// Set correctly keyframe direction on spawn point
if (isFirstPoint)
newPointDirection = hitPoint - spline.GetSplineTangent(lastPointIndex, true).Translation;
else if (isLastPoint)
newPointDirection = spline.GetSplineTangent(lastPointIndex, false).Translation - hitPoint;
var newPointLocalPosition = spline.Transform.WorldToLocal(hitPoint);
var newPointLocalOrientation = Quaternion.LookRotation(newPointDirection);
// Add new point
spline.InsertSplinePoint(newPointIndex, newTime, Transform.Identity, false);
var newKeyframe = lastKeyframe.DeepClone();
var newKeyframeTransform = newKeyframe.Value;
newKeyframeTransform.Translation = newPointLocalPosition;
newKeyframeTransform.Orientation = newPointLocalOrientation;
newKeyframe.Value = newKeyframeTransform;
// Set new point keyframe
var newKeyframeTangentIn = Transform.Identity;
var newKeyframeTangentOut = Transform.Identity;
newKeyframeTangentIn.Translation = (Vector3.Forward * newPointLocalOrientation) * distanceFromLastPoint;
newKeyframeTangentOut.Translation = (Vector3.Backward * newPointLocalOrientation) * distanceFromLastPoint;
newKeyframe.TangentIn = newKeyframeTangentIn;
newKeyframe.TangentOut = newKeyframeTangentOut;
spline.SetSplineKeyframe(newPointIndex, newKeyframe);
for (int i = 1; i < spline.SplinePointsCount; i++)
{
// check all elements to don't left keyframe has invalid time
// because points can be added on start or on middle of spline
// conflicting with time of another keyframes
spline.SetSplinePointTime(i, i, false);
}
// Select new point node
SyncSplineKeyframeWithNodes();
Editor.Instance.SceneEditing.Select(ChildNodes[newPointIndex]);
spline.UpdateSpline();
}
private void EditSplineWithSnap(SplinePointNode selectedPoint)
{
var spline = (Spline)Actor;
var selectedPointBounds = new BoundingSphere(selectedPoint.Transform.Translation, 1f);
var allSplinesInView = GetSplinesInView();
allSplinesInView.Remove(spline);
if (allSplinesInView.Count == 0)
return;
var snappedOnSplinePoint = false;
for (int i = 0; i < allSplinesInView.Count; i++)
{
for (int x = 0; x < allSplinesInView[i].SplineKeyframes.Length; x++)
{
var keyframePosition = allSplinesInView[i].GetSplinePoint(x);
var pointIndicatorSize = NodeSizeByDistance(keyframePosition, SnapPointIndicatorSize);
var keyframeBounds = new BoundingSphere(keyframePosition, pointIndicatorSize);
DebugDraw.DrawSphere(keyframeBounds, Color.Red, 0, false);
if (keyframeBounds.Intersects(selectedPointBounds))
{
spline.SetSplinePoint(selectedPoint.Index, keyframeBounds.Center);
snappedOnSplinePoint = true;
break;
}
}
}
if (!snappedOnSplinePoint)
{
var nearSplineSnapPoint = GetNearSplineSnapPosition(selectedPoint.Transform.Translation, allSplinesInView);
var snapIndicatorSize = NodeSizeByDistance(nearSplineSnapPoint, SnapIndicatorSize);
var snapBounds = new BoundingSphere(nearSplineSnapPoint, snapIndicatorSize);
if (snapBounds.Intersects(selectedPointBounds))
{
spline.SetSplinePoint(selectedPoint.Index, snapBounds.Center);
}
DebugDraw.DrawSphere(snapBounds, Color.Yellow, 0, true);
}
}
/// <inheritdoc />
public override void PostSpawn()
{
@@ -343,14 +478,12 @@ namespace FlaxEditor.SceneGraph.Actors
var spline = (Spline)Actor;
spline.AddSplineLocalPoint(Vector3.Zero, false);
spline.AddSplineLocalPoint(new Vector3(0, 0, 100.0f));
spline.SetSplineKeyframe(0, new BezierCurve<Transform>.Keyframe()
{
Value = new Transform(Vector3.Zero, Quaternion.Identity, Vector3.One),
TangentIn = new Transform(Vector3.Backward * 100, Quaternion.Identity, Vector3.One),
TangentOut = new Transform(Vector3.Forward * 100, Quaternion.Identity, Vector3.One),
});
spline.SetSplineKeyframe(1, new BezierCurve<Transform>.Keyframe()
{
Value = new Transform(Vector3.Forward * 100, Quaternion.Identity, Vector3.One),
@@ -413,6 +546,39 @@ namespace FlaxEditor.SceneGraph.Actors
}
}
private static List<Spline> GetSplinesInView()
{
var splines = Level.GetActors<Spline>(true);
var result = new List<Spline>();
var viewBounds = Editor.Instance.Windows.EditWin.Viewport.ViewFrustum;
foreach (var s in splines)
{
var contains = viewBounds.Contains(s.EditorBox);
if (contains == ContainmentType.Contains || contains == ContainmentType.Intersects)
result.Add(s);
}
return result;
}
private static Vector3 GetNearSplineSnapPosition(Vector3 position, List<Spline> splines)
{
var nearPoint = splines[0].GetSplinePointClosestToPoint(position);
var nearDistance = Vector3.Distance(nearPoint, position);
for (int i = 1; i < splines.Count; i++)
{
var point = splines[i].GetSplinePointClosestToPoint(position);
var distance = Vector3.Distance(point, position);
if (distance < nearDistance)
{
nearPoint = point;
nearDistance = distance;
}
}
return nearPoint;
}
internal static Real NodeSizeByDistance(Vector3 nodePosition, Real nodeSize)
{
var cameraTransform = Editor.Instance.Windows.EditWin.Viewport.ViewportCamera.Viewport.ViewTransform;

View File

@@ -492,8 +492,7 @@ namespace FlaxEditor.Surface.ContextMenu
// If no item is selected (or it's not visible anymore), select the top one
Profiler.BeginEvent("VisjectCM.Layout");
if (SelectedItem == null || !SelectedItem.VisibleInHierarchy)
SelectedItem = _groups.Find(g => g.Visible)?.Children.Find(c => c.Visible && c is VisjectCMItem) as VisjectCMItem;
SelectedItem = _groups.Find(g => g.Visible)?.Children.Find(c => c.Visible && c is VisjectCMItem) as VisjectCMItem;
PerformLayout();
if (SelectedItem != null)
_panel1.ScrollViewTo(SelectedItem);
@@ -704,7 +703,7 @@ namespace FlaxEditor.Surface.ContextMenu
Hide();
return true;
}
else if (key == KeyboardKeys.Return)
else if (key == KeyboardKeys.Return || key == KeyboardKeys.Tab)
{
if (SelectedItem != null)
OnClickItem(SelectedItem);

View File

@@ -73,8 +73,6 @@ namespace FlaxEditor.Surface.ContextMenu
{
SortScore = 0;
if (!(_highlights?.Count > 0))
return;
if (!Visible)
return;
@@ -83,6 +81,8 @@ namespace FlaxEditor.Surface.ContextMenu
SortScore += 1;
if (Data != null)
SortScore += 1;
if (_highlights is { Count: > 0 })
SortScore += 1;
if (_isStartsWithMatch)
SortScore += 2;
if (_isFullMatch)
@@ -169,6 +169,7 @@ namespace FlaxEditor.Surface.ContextMenu
/// <param name="groupHeaderMatches">True if item's group header got a filter match and item should stay visible.</param>
public void UpdateFilter(string filterText, Box selectedBox, bool groupHeaderMatches = false)
{
// When dragging connection out of a box, validate if the box is compatible with this item's type
if (selectedBox != null)
{
Visible = CanConnectTo(selectedBox);
@@ -185,72 +186,87 @@ namespace FlaxEditor.Surface.ContextMenu
// Clear filter
_highlights?.Clear();
Visible = true;
return;
}
else
GetTextRectangle(out var textRect);
// Check archetype title
if (QueryFilterHelper.Match(filterText, _archetype.Title, out var ranges))
{
GetTextRectangle(out var textRect);
if (QueryFilterHelper.Match(filterText, _archetype.Title, out var ranges))
// Update highlights
if (_highlights == null)
_highlights = new List<Rectangle>(ranges.Length);
else
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
for (int i = 0; i < ranges.Length; i++)
{
// Update highlights
if (_highlights == null)
_highlights = new List<Rectangle>(ranges.Length);
else
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
for (int i = 0; i < ranges.Length; i++)
var start = font.GetCharPosition(_archetype.Title, ranges[i].StartIndex);
var end = font.GetCharPosition(_archetype.Title, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
if (ranges[i].StartIndex <= 0)
{
var start = font.GetCharPosition(_archetype.Title, ranges[i].StartIndex);
var end = font.GetCharPosition(_archetype.Title, ranges[i].EndIndex);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
if (ranges[i].StartIndex <= 0)
{
_isStartsWithMatch = true;
if (ranges[i].Length == _archetype.Title.Length)
_isFullMatch = true;
}
_isStartsWithMatch = true;
if (ranges[i].Length == _archetype.Title.Length)
_isFullMatch = true;
}
Visible = true;
}
else if (_archetype.AlternativeTitles?.Any(altTitle => string.Equals(filterText, altTitle, StringComparison.CurrentCultureIgnoreCase)) == true)
{
// Update highlights
if (_highlights == null)
_highlights = new List<Rectangle>(1);
else
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
var start = font.GetCharPosition(_archetype.Title, 0);
var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
_isFullMatch = true;
Visible = true;
}
else if (NodeArchetype.TryParseText != null && NodeArchetype.TryParseText(filterText, out var data))
{
// Update highlights
if (_highlights == null)
_highlights = new List<Rectangle>(1);
else
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
var start = font.GetCharPosition(_archetype.Title, 0);
var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
Visible = true;
Data = data;
}
else if (!groupHeaderMatches)
{
// Hide
_highlights?.Clear();
Visible = false;
}
Visible = true;
return;
}
// Check archetype synonyms
if (_archetype.AlternativeTitles!= null && _archetype.AlternativeTitles.Any(altTitle => QueryFilterHelper.Match(filterText, altTitle, out ranges)))
{
// Update highlights
if (_highlights == null)
_highlights = new List<Rectangle>(1);
else
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
var start = font.GetCharPosition(_archetype.Title, 0);
var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
for (int i = 0; i < ranges.Length; i++)
{
if (ranges[i].StartIndex <= 0)
{
_isStartsWithMatch = true;
}
}
Visible = true;
return;
}
// Check archetype data (if it exists)
if (NodeArchetype.TryParseText != null && NodeArchetype.TryParseText(filterText, out var data))
{
// Update highlights
if (_highlights == null)
_highlights = new List<Rectangle>(1);
else
_highlights.Clear();
var style = Style.Current;
var font = style.FontSmall;
var start = font.GetCharPosition(_archetype.Title, 0);
var end = font.GetCharPosition(_archetype.Title, _archetype.Title.Length - 1);
_highlights.Add(new Rectangle(start.X + textRect.X, 0, end.X - start.X, Height));
Visible = true;
Data = data;
return;
}
_highlights?.Clear();
// Hide
if (!groupHeaderMatches)
Visible = false;
}
/// <inheritdoc />

View File

@@ -48,6 +48,7 @@ namespace FlaxEditor.Tools.Terrain
if (DataPtr != IntPtr.Zero)
Marshal.FreeHGlobal(DataPtr);
DataPtr = Marshal.AllocHGlobal(size);
Utils.MemoryClear(DataPtr, (ulong)size);
Size = size;
}
}
@@ -294,7 +295,7 @@ namespace FlaxEditor.Tools.Terrain
base.OnDeactivated();
// Free temporary memory buffer
foreach (var splatmapData in _cachedSplatmapData)
foreach (ref var splatmapData in _cachedSplatmapData.AsSpan())
splatmapData.Free();
}

View File

@@ -140,8 +140,7 @@ namespace FlaxEditor.Utilities
// Check if start the matching sequence
if (matchStartPos == -1)
{
if (ranges == null)
ranges = new List<Range>();
ranges ??= new List<Range>();
matchStartPos = textPos;
}
}
@@ -152,7 +151,7 @@ namespace FlaxEditor.Utilities
{
var length = textPos - matchStartPos;
if (length >= MinLength)
ranges.Add(new Range(matchStartPos, length));
ranges!.Add(new Range(matchStartPos, length));
textPos = matchStartPos + length;
matchStartPos = -1;
}
@@ -165,13 +164,13 @@ namespace FlaxEditor.Utilities
{
var length = endPos - matchStartPos;
if (length >= MinLength)
ranges.Add(new Range(matchStartPos, length));
ranges!.Add(new Range(matchStartPos, length));
textPos = matchStartPos + length;
}
}
// Check if has any range
if (ranges != null && ranges.Count > 0)
if (ranges is { Count: > 0 })
{
matches = ranges.ToArray();
return true;

View File

@@ -174,7 +174,10 @@ namespace FlaxEditor.Viewport.Cameras
}
else
{
position = sphere.Center - Vector3.Forward * orientation * (sphere.Radius * 2.5f);
// calculate the min. distance so that the sphere fits roughly 70% in FOV
// clip to far plane as a disappearing big object might be confusing
var distance = Mathf.Min(1.4f * sphere.Radius / Mathf.Tan(Mathf.DegreesToRadians * Viewport.FieldOfView / 2), Viewport.FarPlane);
position = sphere.Center - Vector3.Forward * orientation * distance;
}
TargetPoint = sphere.Center;
MoveViewport(position, orientation);

View File

@@ -334,6 +334,22 @@ namespace FlaxEditor.Viewport
}
}
/// <summary>
/// Gets the bounding frustum of the current viewport camera.
/// </summary>
public BoundingFrustum ViewFrustum
{
get
{
Vector3 viewOrigin = Task.View.Origin;
Float3 position = ViewPosition - viewOrigin;
CreateViewMatrix(position, out var view);
CreateProjectionMatrix(out var projection);
Matrix.Multiply(ref view, ref projection, out var viewProjection);
return new BoundingFrustum(ref viewProjection);
}
}
/// <summary>
/// Gets or sets the yaw angle (in degrees).
/// </summary>

View File

@@ -144,7 +144,7 @@ namespace FlaxEditor.Windows.Assets
protected override void OnAssetLinked()
{
Asset.WaitForLoaded();
_textPreview.Font = new FontReference(Asset.CreateFont(30));
_textPreview.Font = new FontReference(Asset, 30);
_inputText.Text = string.Format("This is a sample text using font {0}.", Asset.FamilyName);
var options = Asset.Options;
_proxy.Set(ref options);

View File

@@ -485,6 +485,16 @@ namespace FlaxEditor.Windows
{
base.OnShowContextMenu(menu);
// Focus on play
{
var focus = menu.AddButton("Start Focused");
focus.CloseMenuOnClick = false;
var checkbox = new CheckBox(140, 2, FocusOnPlay) { Parent = focus };
checkbox.StateChanged += state => FocusOnPlay = state.Checked;
}
menu.AddSeparator();
// Viewport Brightness
{
var brightness = menu.AddButton("Viewport Brightness");

View File

@@ -250,6 +250,16 @@ public:
return _count == 0;
}
/// <summary>
/// Determines if given index is valid.
/// </summary>
/// <param name="index">The index.</param>
/// <returns><c>true</c> if is valid a index; otherwise, <c>false</c>.</returns>
bool IsValidIndex(int32 index) const
{
return index < _count && index >= 0;
}
/// <summary>
/// Gets the pointer to the first item in the collection (linear allocation).
/// </summary>

View File

@@ -119,7 +119,7 @@ namespace FlaxEditor.Content.Settings
/// <summary>
/// The custom settings to use with a game. Can be specified by the user to define game-specific options and be used by the external plugins (used as key-value pair).
/// </summary>
[EditorOrder(1100), EditorDisplay("Other Settings"), Tooltip("The custom settings to use with a game. Can be specified by the user to define game-specific options and be used by the external plugins (used as key-value pair).")]
[EditorOrder(1500), EditorDisplay("Other Settings"), Tooltip("The custom settings to use with a game. Can be specified by the user to define game-specific options and be used by the external plugins (used as key-value pair).")]
public Dictionary<string, JsonAsset> CustomSettings;
#if FLAX_EDITOR || PLATFORM_WINDOWS

View File

@@ -6,6 +6,8 @@
#include "Engine/Graphics/Enums.h"
#include "Engine/Graphics/PostProcessSettings.h"
class FontAsset;
/// <summary>
/// Graphics rendering settings.
/// </summary>
@@ -13,6 +15,7 @@ API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings", NoConstructor) class
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE_MINIMAL(GraphicsSettings);
public:
/// <summary>
/// Enables rendering synchronization with the refresh rate of the display device to avoid "tearing" artifacts.
@@ -118,6 +121,12 @@ public:
API_FIELD(Attributes="EditorOrder(10000), EditorDisplay(\"Post Process Settings\", EditorDisplayAttribute.InlineStyle)")
PostProcessSettings PostProcessSettings;
/// <summary>
/// The list of fallback fonts used for text rendering. Ignored if empty.
/// </summary>
API_FIELD(Attributes="EditorOrder(5000), EditorDisplay(\"Text\")")
Array<AssetReference<FontAsset>> FallbackFonts;
private:
/// <summary>
/// Renamed UeeHDRProbes into UseHDRProbes

View File

@@ -104,6 +104,16 @@ namespace FlaxEngine
GetPlanesFromMatrix(ref pMatrix, out pNear, out pFar, out pLeft, out pRight, out pTop, out pBottom);
}
/// <summary>
/// Creates a new instance of BoundingFrustum.
/// </summary>
/// <param name="matrix">Combined matrix that usually takes view × projection matrix.</param>
public BoundingFrustum(ref Matrix matrix)
{
pMatrix = matrix;
GetPlanesFromMatrix(ref pMatrix, out pNear, out pFar, out pLeft, out pRight, out pTop, out pBottom);
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>

View File

@@ -923,11 +923,40 @@ void DebugDraw::DrawActors(Actor** selectedActors, int32 selectedActorsCount, bo
}
}
void DebugDraw::DrawRay(const Vector3& origin, const Vector3& direction, const Color& color, float duration, bool depthTest)
void DebugDraw::DrawAxisFromDirection(const Vector3& origin, const Vector3& direction, float size, float duration, bool depthTest)
{
const auto rot = Quaternion::FromDirection(direction.GetNormalized());
const Vector3 up = (rot * Vector3::Up);
const Vector3 forward = (rot * Vector3::Forward);
const Vector3 right = (rot * Vector3::Right);
const float sizeHalf = size * 0.5f;
DrawLine(origin, origin + up * sizeHalf + up, Color::Green, duration, depthTest);
DrawLine(origin, origin + forward * sizeHalf + forward, Color::Blue, duration, depthTest);
DrawLine(origin, origin + right * sizeHalf + right, Color::Red, duration, depthTest);
}
void DebugDraw::DrawDirection(const Vector3& origin, const Vector3& direction, const Color& color, float duration, bool depthTest)
{
auto dir = origin + direction;
if (dir.IsNanOrInfinity())
return;
DrawLine(origin, origin + direction, color, duration, depthTest);
}
void DebugDraw::DrawRay(const Vector3& origin, const Vector3& direction, const Color& color, float length, float duration, bool depthTest)
{
if (isnan(length) || isinf(length))
return;
DrawLine(origin, origin + (direction.GetNormalized() * length), color, duration, depthTest);
}
void DebugDraw::DrawRay(const Ray& ray, const Color& color, float length, float duration, bool depthTest)
{
if (isnan(length) || isinf(length))
return;
DrawLine(ray.Position, ray.Position + (ray.Direction.GetNormalized() * length), color, duration, depthTest);
}
void DebugDraw::DrawLine(const Vector3& start, const Vector3& end, const Color& color, float duration, bool depthTest)
{
const Float3 startF = start - Context->Origin, endF = end - Context->Origin;

View File

@@ -31,6 +31,17 @@ namespace FlaxEngine
{
}
/// <summary>
/// Draws the lines axis from direction.
/// </summary>
/// <param name="origin">The origin of the line.</param>
/// <param name="direction">The direction of the line.</param>
/// <param name="color">The color.</param>
/// <param name="Size">The size of the axis.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
public static void DrawAxisFromDirection(Vector3 origin, Vector3 direction, Color color ,float Size = 100.0f, float duration = 0.0f, bool depthTest = true){}
/// <summary>
/// Draws the line in a direction.
/// </summary>
@@ -39,7 +50,28 @@ namespace FlaxEngine
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
public static void DrawRay(Vector3 origin, Vector3 direction, Color color, float duration = 0.0f, bool depthTest = true)
public static void DrawDirection(Vector3 origin, Vector3 direction, Color color, float duration = 0.0f, bool depthTest = true){}
/// <summary>
/// Draws the line in a direction.
/// </summary>
/// <param name="origin">The origin of the line.</param>
/// <param name="direction">The direction of the line.</param>
/// <param name="color">The color.</param>
/// <param name="length">The length of the ray.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
public static void DrawRay(Vector3 origin, Vector3 direction, Color color, float length = 3.402823466e+38f, float duration = 0.0f, bool depthTest = true){}
/// <summary>
/// Draws the line in a direction.
/// </summary>
/// <param name="ray">The ray.</param>
/// <param name="color">The color.</param>
/// <param name="length">The length of the ray.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
public static void DrawRay(Ray ray,Color color, float length = 3.402823466e+38f, float duration = 0.0f, bool depthTest = true)
{
}

View File

@@ -24,7 +24,6 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
DECLARE_SCRIPTING_TYPE_NO_SPAWN(DebugDraw);
#if USE_EDITOR
/// <summary>
/// Allocates the context for Debug Drawing. Can be use to redirect debug shapes collecting to a separate container (instead of global state).
/// </summary>
@@ -49,7 +48,6 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// </summary>
/// <param name="context">The context or null.</param>
API_FUNCTION() static void SetContext(void* context);
#endif
/// <summary>
@@ -69,6 +67,16 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="drawScenes">True if draw all debug shapes from scenes too or false if draw just from specified actor list.</param>
API_FUNCTION() static void DrawActors(Actor** selectedActors, int32 selectedActorsCount, bool drawScenes);
/// <summary>
/// Draws the lines axis from direction.
/// </summary>
/// <param name="origin">The origin of the line.</param>
/// <param name="direction">The direction of the line.</param>
/// <param name="size">The size of the axis.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawAxisFromDirection(const Vector3& origin, const Vector3& direction, float size = 100.0f, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the line in a direction.
/// </summary>
@@ -77,7 +85,28 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawRay(const Vector3& origin, const Vector3& direction, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawDirection(const Vector3& origin, const Vector3& direction, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the line in a direction.
/// </summary>
/// <param name="origin">The origin of the line.</param>
/// <param name="direction">The direction of the line.</param>
/// <param name="color">The color.</param>
/// <param name="length">The length of the ray.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawRay(const Vector3& origin, const Vector3& direction, const Color& color = Color::White, float length = MAX_float, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the line in a direction.
/// </summary>
/// <param name="ray">The ray.</param>
/// <param name="color">The color.</param>
/// <param name="length">The length of the ray.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawRay(const Ray& ray, const Color& color = Color::White, float length = MAX_float, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the line.
@@ -87,7 +116,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawLine(const Vector3& start, const Vector3& end, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawLine(const Vector3& start, const Vector3& end, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the line.
@@ -108,7 +137,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawLines(const Span<Float3>& lines, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawLines(const Span<Float3>& lines, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the lines. Line positions are located one after another (e.g. l0.start, l0.end, l1.start, l1.end,...).
@@ -118,7 +147,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
static void DrawLines(const Array<Float3, HeapAllocation>& lines, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true);
static void DrawLines(const Array<Float3, HeapAllocation>& lines, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the lines. Line positions are located one after another (e.g. l0.start, l0.end, l1.start, l1.end,...).
@@ -128,7 +157,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawLines(const Span<Double3>& lines, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawLines(const Span<Double3>& lines, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the lines. Line positions are located one after another (e.g. l0.start, l0.end, l1.start, l1.end,...).
@@ -138,7 +167,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
static void DrawLines(const Array<Double3, HeapAllocation>& lines, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true);
static void DrawLines(const Array<Double3, HeapAllocation>& lines, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws a Bezier curve.
@@ -150,7 +179,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The line color</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawBezier(const Vector3& p1, const Vector3& p2, const Vector3& p3, const Vector3& p4, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawBezier(const Vector3& p1, const Vector3& p2, const Vector3& p3, const Vector3& p4, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the circle.
@@ -161,7 +190,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawCircle(const Vector3& position, const Float3& normal, float radius, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawCircle(const Vector3& position, const Float3& normal, float radius, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe triangle.
@@ -172,7 +201,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawWireTriangle(const Vector3& v0, const Vector3& v1, const Vector3& v2, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawWireTriangle(const Vector3& v0, const Vector3& v1, const Vector3& v2, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangle.
@@ -183,7 +212,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawTriangle(const Vector3& v0, const Vector3& v1, const Vector3& v2, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawTriangle(const Vector3& v0, const Vector3& v1, const Vector3& v2, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles.
@@ -192,7 +221,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawTriangles(const Span<Float3>& vertices, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawTriangles(const Span<Float3>& vertices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles.
@@ -202,7 +231,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawTriangles(const Span<Float3>& vertices, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawTriangles(const Span<Float3>& vertices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles.
@@ -211,7 +240,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
static void DrawTriangles(const Array<Float3, HeapAllocation>& vertices, const Color& color, float duration = 0.0f, bool depthTest = true);
static void DrawTriangles(const Array<Float3, HeapAllocation>& vertices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles.
@@ -221,7 +250,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
static void DrawTriangles(const Array<Float3, HeapAllocation>& vertices, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true);
static void DrawTriangles(const Array<Float3, HeapAllocation>& vertices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles using the given index buffer.
@@ -231,7 +260,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawTriangles(const Span<Float3>& vertices, const Span<int32>& indices, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawTriangles(const Span<Float3>& vertices, const Span<int32>& indices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles using the given index buffer.
@@ -242,7 +271,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawTriangles(const Span<Float3>& vertices, const Span<int32>& indices, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawTriangles(const Span<Float3>& vertices, const Span<int32>& indices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles using the given index buffer.
@@ -252,7 +281,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
static void DrawTriangles(const Array<Float3, HeapAllocation>& vertices, const Array<int32, HeapAllocation>& indices, const Color& color, float duration = 0.0f, bool depthTest = true);
static void DrawTriangles(const Array<Float3, HeapAllocation>& vertices, const Array<int32, HeapAllocation>& indices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles using the given index buffer.
@@ -263,7 +292,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
static void DrawTriangles(const Array<Float3, HeapAllocation>& vertices, const Array<int32, HeapAllocation>& indices, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true);
static void DrawTriangles(const Array<Float3, HeapAllocation>& vertices, const Array<int32, HeapAllocation>& indices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles.
@@ -272,7 +301,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawTriangles(const Span<Double3>& vertices, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawTriangles(const Span<Double3>& vertices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles.
@@ -282,7 +311,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawTriangles(const Span<Double3>& vertices, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawTriangles(const Span<Double3>& vertices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles.
@@ -291,7 +320,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
static void DrawTriangles(const Array<Double3, HeapAllocation>& vertices, const Color& color, float duration = 0.0f, bool depthTest = true);
static void DrawTriangles(const Array<Double3, HeapAllocation>& vertices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles.
@@ -301,7 +330,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
static void DrawTriangles(const Array<Double3, HeapAllocation>& vertices, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true);
static void DrawTriangles(const Array<Double3, HeapAllocation>& vertices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles using the given index buffer.
@@ -311,7 +340,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawTriangles(const Span<Double3>& vertices, const Span<int32>& indices, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawTriangles(const Span<Double3>& vertices, const Span<int32>& indices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles using the given index buffer.
@@ -322,7 +351,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawTriangles(const Span<Double3>& vertices, const Span<int32>& indices, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawTriangles(const Span<Double3>& vertices, const Span<int32>& indices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles using the given index buffer.
@@ -332,7 +361,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
static void DrawTriangles(const Array<Double3, HeapAllocation>& vertices, const Array<int32, HeapAllocation>& indices, const Color& color, float duration = 0.0f, bool depthTest = true);
static void DrawTriangles(const Array<Double3, HeapAllocation>& vertices, const Array<int32, HeapAllocation>& indices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the triangles using the given index buffer.
@@ -343,7 +372,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
static void DrawTriangles(const Array<Double3, HeapAllocation>& vertices, const Array<int32, HeapAllocation>& indices, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true);
static void DrawTriangles(const Array<Double3, HeapAllocation>& vertices, const Array<int32, HeapAllocation>& indices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe triangles.
@@ -352,7 +381,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawWireTriangles(const Span<Float3>& vertices, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawWireTriangles(const Span<Float3>& vertices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe triangles.
@@ -361,7 +390,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
static void DrawWireTriangles(const Array<Float3, HeapAllocation>& vertices, const Color& color, float duration = 0.0f, bool depthTest = true);
static void DrawWireTriangles(const Array<Float3, HeapAllocation>& vertices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe triangles using the given index buffer.
@@ -371,7 +400,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawWireTriangles(const Span<Float3>& vertices, const Span<int32>& indices, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawWireTriangles(const Span<Float3>& vertices, const Span<int32>& indices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe triangles using the given index buffer.
@@ -381,7 +410,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
static void DrawWireTriangles(const Array<Float3, HeapAllocation>& vertices, const Array<int32, HeapAllocation>& indices, const Color& color, float duration = 0.0f, bool depthTest = true);
static void DrawWireTriangles(const Array<Float3, HeapAllocation>& vertices, const Array<int32, HeapAllocation>& indices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe triangles.
@@ -390,7 +419,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawWireTriangles(const Span<Double3>& vertices, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawWireTriangles(const Span<Double3>& vertices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe triangles.
@@ -399,7 +428,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
static void DrawWireTriangles(const Array<Double3, HeapAllocation>& vertices, const Color& color, float duration = 0.0f, bool depthTest = true);
static void DrawWireTriangles(const Array<Double3, HeapAllocation>& vertices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe triangles using the given index buffer.
@@ -409,7 +438,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawWireTriangles(const Span<Double3>& vertices, const Span<int32>& indices, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawWireTriangles(const Span<Double3>& vertices, const Span<int32>& indices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe triangles using the given index buffer.
@@ -419,7 +448,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
static void DrawWireTriangles(const Array<Double3, HeapAllocation>& vertices, const Array<int32, HeapAllocation>& indices, const Color& color, float duration = 0.0f, bool depthTest = true);
static void DrawWireTriangles(const Array<Double3, HeapAllocation>& vertices, const Array<int32, HeapAllocation>& indices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe box.
@@ -428,7 +457,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawWireBox(const BoundingBox& box, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawWireBox(const BoundingBox& box, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe frustum.
@@ -437,7 +466,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawWireFrustum(const BoundingFrustum& frustum, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawWireFrustum(const BoundingFrustum& frustum, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe box.
@@ -446,7 +475,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawWireBox(const OrientedBoundingBox& box, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawWireBox(const OrientedBoundingBox& box, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe sphere.
@@ -455,7 +484,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawWireSphere(const BoundingSphere& sphere, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawWireSphere(const BoundingSphere& sphere, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the sphere.
@@ -464,7 +493,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawSphere(const BoundingSphere& sphere, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawSphere(const BoundingSphere& sphere, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the tube.
@@ -476,7 +505,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawTube(const Vector3& position, const Quaternion& orientation, float radius, float length, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawTube(const Vector3& position, const Quaternion& orientation, float radius, float length, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe tube.
@@ -488,7 +517,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawWireTube(const Vector3& position, const Quaternion& orientation, float radius, float length, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawWireTube(const Vector3& position, const Quaternion& orientation, float radius, float length, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the cylinder.
@@ -500,7 +529,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawCylinder(const Vector3& position, const Quaternion& orientation, float radius, float height, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawCylinder(const Vector3& position, const Quaternion& orientation, float radius, float height, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe cylinder.
@@ -512,7 +541,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawWireCylinder(const Vector3& position, const Quaternion& orientation, float radius, float height, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawWireCylinder(const Vector3& position, const Quaternion& orientation, float radius, float height, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the cone.
@@ -525,7 +554,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawCone(const Vector3& position, const Quaternion& orientation, float radius, float angleXY, float angleXZ, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawCone(const Vector3& position, const Quaternion& orientation, float radius, float angleXY, float angleXZ, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe cone.
@@ -538,7 +567,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawWireCone(const Vector3& position, const Quaternion& orientation, float radius, float angleXY, float angleXZ, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawWireCone(const Vector3& position, const Quaternion& orientation, float radius, float angleXY, float angleXZ, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the arc.
@@ -550,7 +579,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawArc(const Vector3& position, const Quaternion& orientation, float radius, float angle, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawArc(const Vector3& position, const Quaternion& orientation, float radius, float angle, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe arc.
@@ -562,7 +591,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawWireArc(const Vector3& position, const Quaternion& orientation, float radius, float angle, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawWireArc(const Vector3& position, const Quaternion& orientation, float radius, float angle, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the wireframe arrow.
@@ -574,7 +603,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawWireArrow(const Vector3& position, const Quaternion& orientation, float scale, float capScale, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawWireArrow(const Vector3& position, const Quaternion& orientation, float scale, float capScale, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the box.
@@ -583,7 +612,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawBox(const BoundingBox& box, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawBox(const BoundingBox& box, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the box.
@@ -592,7 +621,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawBox(const OrientedBoundingBox& box, const Color& color, float duration = 0.0f, bool depthTest = true);
API_FUNCTION() static void DrawBox(const OrientedBoundingBox& box, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the text on a screen (2D).
@@ -602,7 +631,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="size">The font size.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
API_FUNCTION() static void DrawText(const StringView& text, const Float2& position, const Color& color, int32 size = 20, float duration = 0.0f);
API_FUNCTION() static void DrawText(const StringView& text, const Float2& position, const Color& color = Color::White, int32 size = 20, float duration = 0.0f);
/// <summary>
/// Draws the text (3D) that automatically faces the camera.
@@ -613,7 +642,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="size">The font size.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="scale">The text scale.</param>
API_FUNCTION() static void DrawText(const StringView& text, const Vector3& position, const Color& color, int32 size = 32, float duration = 0.0f, float scale = 1.0f);
API_FUNCTION() static void DrawText(const StringView& text, const Vector3& position, const Color& color = Color::White, int32 size = 32, float duration = 0.0f, float scale = 1.0f);
/// <summary>
/// Draws the text (3D).
@@ -623,39 +652,45 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="color">The color.</param>
/// <param name="size">The font size.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
API_FUNCTION() static void DrawText(const StringView& text, const Transform& transform, const Color& color, int32 size = 32, float duration = 0.0f);
API_FUNCTION() static void DrawText(const StringView& text, const Transform& transform, const Color& color = Color::White, int32 size = 32, float duration = 0.0f);
};
#define DEBUG_DRAW_RAY(origin, direction, color, duration, depthTest) DebugDraw::DrawRay(origin, direction, color, duration, depthTest)
#define DEBUG_DRAW_LINE(start, end, color, duration, depthTest) DebugDraw::DrawLine(start, end, color, duration, depthTest)
#define DEBUG_DRAW_LINES(lines, transform, color, duration, depthTest) DebugDraw::DrawLines(lines, transform, color, duration, depthTest)
#define DEBUG_DRAW_BEZIER(p1, p2, p3, p4, color, duration, depthTest) DebugDraw::DrawBezier(p1, p2, p3, p4, color, duration, depthTest)
#define DEBUG_DRAW_CIRCLE(position, normal, radius, color, duration, depthTest) DebugDraw::DrawCircle(position, normal, radius, color, duration, depthTest)
#define DEBUG_DRAW_TRIANGLE(v0, v1, v2, color, duration, depthTest) DebugDraw::DrawTriangle(v0, v1, v2, color, duration, depthTest)
#define DEBUG_DRAW_TRIANGLES(vertices, color, duration, depthTest) DebugDraw::DrawTriangles(vertices, color, duration, depthTest)
#define DEBUG_DRAW_TRIANGLES_EX(vertices, indices, color, duration, depthTest) DebugDraw::DrawTriangles(vertices, indices, color, duration, depthTest)
#define DEBUG_DRAW_TRIANGLES_EX2(vertices, indices, transform, color, duration, depthTest) DebugDraw::DrawTriangles(vertices, indices, transform, color, duration, depthTest)
#define DEBUG_DRAW_SPHERE(sphere, color, duration, depthTest) DebugDraw::DrawSphere(sphere, color, duration, depthTest)
#define DEBUG_DRAW_TUBE(position, orientation, radius, length, color, duration, depthTest) DebugDraw::DrawTube(position, orientation, radius, length, color, duration, depthTest)
#define DEBUG_DRAW_BOX(box, color, duration, depthTest) DebugDraw::DrawBox(box, color, duration, depthTest)
#define DEBUG_DRAW_CYLINDER(position, orientation, radius, height, color, duration, depthTest) DebugDraw::DrawCylinder(position, orientation, radius, height, color, duration, depthTest)
#define DEBUG_DRAW_CONE(position, orientation, radius, angleXY, angleXZ, color, duration, depthTest) DebugDraw::DrawCone(position, orientation, radius, angleXY, angleXZ, color, duration, depthTest)
#define DEBUG_DRAW_ARC(position, orientation, radius, angle, color, duration, depthTest) DebugDraw::DrawArc(position, orientation, radius, angle, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_TRIANGLE(v0, v1, v2, color, duration, depthTest) DebugDraw::DrawWireTriangle(v0, v1, v2, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_TRIANGLES(vertices, color, duration, depthTest) DebugDraw::DrawWireTriangles(vertices, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_TRIANGLES_EX(vertices, indices, color, duration, depthTest) DebugDraw::DrawWireTriangles(vertices, indices, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_BOX(box, color, duration, depthTest) DebugDraw::DrawWireBox(box, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_FRUSTUM(frustum, color, duration, depthTest) DebugDraw::DrawWireFrustum(frustum, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_SPHERE(sphere, color, duration, depthTest) DebugDraw::DrawWireSphere(sphere, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_TUBE(position, orientation, radius, length, color, duration, depthTest) DebugDraw::DrawWireTube(position, orientation, radius, length, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_CYLINDER(position, orientation, radius, height, color, duration, depthTest) DebugDraw::DrawWireCylinder(position, orientation, radius, height, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_CONE(position, orientation, radius, angleXY, angleXZ, color, duration, depthTest) DebugDraw::DrawWireCone(position, orientation, radius, angleXY, angleXZ, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_ARC(position, orientation, radius, angle, color, duration, depthTest) DebugDraw::DrawWireArc(position, orientation, radius, angle, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_ARROW(position, orientation, scale, capScale, color, duration, depthTest) DebugDraw::DrawWireArrow(position, orientation, scale, capScale, color, duration, depthTest)
#define DEBUG_DRAW_TEXT(text, position, color, size, duration) DebugDraw::DrawText(text, position, color, size, duration)
#define DEBUG_DRAW_AXIS_FROM_DIRECTION(origin, direction, size, duration, depthTest) DebugDraw::DrawAxisFromDirection(origin, direction, size, duration, depthTest);
#define DEBUG_DRAW_DIRECTION(origin, direction, color, duration, depthTest) DebugDraw::DrawDirection(origin, direction, color, duration, depthTest);
#define DEBUG_DRAW_RAY(origin, direction, color, length, duration, depthTest) DebugDraw::DrawRay(origin, direction, color, length, duration, depthTest);
#define DEBUG_DRAW_RAY(ray, color, length, duration, depthTest) DebugDraw::DrawRay(ray, color, length, duration, depthTest);
#define DEBUG_DRAW_LINE(start, end, color, duration, depthTest) DebugDraw::DrawLine(start, end, color, duration, depthTest)
#define DEBUG_DRAW_LINES(lines, transform, color, duration, depthTest) DebugDraw::DrawLines(lines, transform, color, duration, depthTest)
#define DEBUG_DRAW_BEZIER(p1, p2, p3, p4, color, duration, depthTest) DebugDraw::DrawBezier(p1, p2, p3, p4, color, duration, depthTest)
#define DEBUG_DRAW_CIRCLE(position, normal, radius, color, duration, depthTest) DebugDraw::DrawCircle(position, normal, radius, color, duration, depthTest)
#define DEBUG_DRAW_TRIANGLE(v0, v1, v2, color, duration, depthTest) DebugDraw::DrawTriangle(v0, v1, v2, color, duration, depthTest)
#define DEBUG_DRAW_TRIANGLES(vertices, color, duration, depthTest) DebugDraw::DrawTriangles(vertices, color, duration, depthTest)
#define DEBUG_DRAW_TRIANGLES_EX(vertices, indices, color, duration, depthTest) DebugDraw::DrawTriangles(vertices, indices, color, duration, depthTest)
#define DEBUG_DRAW_TRIANGLES_EX2(vertices, indices, transform, color, duration, depthTest) DebugDraw::DrawTriangles(vertices, indices, transform, color, duration, depthTest)
#define DEBUG_DRAW_SPHERE(sphere, color, duration, depthTest) DebugDraw::DrawSphere(sphere, color, duration, depthTest)
#define DEBUG_DRAW_TUBE(position, orientation, radius, length, color, duration, depthTest) DebugDraw::DrawTube(position, orientation, radius, length, color, duration, depthTest)
#define DEBUG_DRAW_BOX(box, color, duration, depthTest) DebugDraw::DrawBox(box, color, duration, depthTest)
#define DEBUG_DRAW_CYLINDER(position, orientation, radius, height, color, duration, depthTest) DebugDraw::DrawCylinder(position, orientation, radius, height, color, duration, depthTest)
#define DEBUG_DRAW_CONE(position, orientation, radius, angleXY, angleXZ, color, duration, depthTest) DebugDraw::DrawCone(position, orientation, radius, angleXY, angleXZ, color, duration, depthTest)
#define DEBUG_DRAW_ARC(position, orientation, radius, angle, color, duration, depthTest) DebugDraw::DrawArc(position, orientation, radius, angle, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_TRIANGLE(v0, v1, v2, color, duration, depthTest) DebugDraw::DrawWireTriangle(v0, v1, v2, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_TRIANGLES(vertices, color, duration, depthTest) DebugDraw::DrawWireTriangles(vertices, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_TRIANGLES_EX(vertices, indices, color, duration, depthTest) DebugDraw::DrawWireTriangles(vertices, indices, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_BOX(box, color, duration, depthTest) DebugDraw::DrawWireBox(box, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_FRUSTUM(frustum, color, duration, depthTest) DebugDraw::DrawWireFrustum(frustum, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_SPHERE(sphere, color, duration, depthTest) DebugDraw::DrawWireSphere(sphere, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_TUBE(position, orientation, radius, length, color, duration, depthTest) DebugDraw::DrawWireTube(position, orientation, radius, length, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_CYLINDER(position, orientation, radius, height, color, duration, depthTest) DebugDraw::DrawWireCylinder(position, orientation, radius, height, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_CONE(position, orientation, radius, angleXY, angleXZ, color, duration, depthTest) DebugDraw::DrawWireCone(position, orientation, radius, angleXY, angleXZ, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_ARC(position, orientation, radius, angle, color, duration, depthTest) DebugDraw::DrawWireArc(position, orientation, radius, angle, color, duration, depthTest)
#define DEBUG_DRAW_WIRE_ARROW(position, orientation, scale, capScale, color, duration, depthTest) DebugDraw::DrawWireArrow(position, orientation, scale, capScale, color, duration, depthTest)
#define DEBUG_DRAW_TEXT(text, position, color, size, duration) DebugDraw::DrawText(text, position, color, size, duration)
#else
#define DEBUG_DRAW_AXIS_FROM_DIRECTION(origin, direction, size, duration, depthTest)
#define DEBUG_DRAW_DIRECTION(origin, direction,color,duration, depthTest)
#define DEBUG_DRAW_RAY(ray, color, length, duration, depthTest)
#define DEBUG_DRAW_LINE(start, end, color, duration, depthTest)
#define DEBUG_DRAW_LINES(lines, transform, color, duration, depthTest)
#define DEBUG_DRAW_BEZIER(p1, p2, p3, p4, color, duration, depthTest)

View File

@@ -8,6 +8,7 @@
#include "Engine/Core/Config/GraphicsSettings.h"
#include "Engine/Engine/CommandLine.h"
#include "Engine/Engine/EngineService.h"
#include "Engine/Render2D/Font.h"
bool Graphics::UseVSync = false;
Quality Graphics::AAQuality = Quality::Medium;
@@ -69,6 +70,9 @@ void GraphicsSettings::Apply()
Graphics::GIQuality = GIQuality;
Graphics::PostProcessSettings = ::PostProcessSettings();
Graphics::PostProcessSettings.BlendWith(PostProcessSettings, 1.0f);
#if !USE_EDITOR // OptionsModule handles fallback fonts in Editor
Font::FallbackFonts = FallbackFonts;
#endif
}
void Graphics::DisposeDevice()

View File

@@ -27,7 +27,7 @@ namespace FlaxEngine
Matrix.Invert(ref View, out IV);
Matrix.Invert(ref Projection, out IP);
Matrix.Multiply(ref View, ref Projection, out var viewProjection);
Frustum = new BoundingFrustum(viewProjection);
Frustum = new BoundingFrustum(ref viewProjection);
Matrix.Invert(ref viewProjection, out IVP);
CullingFrustum = Frustum;
}

View File

@@ -1356,6 +1356,16 @@ bool Actor::IsPrefabRoot() const
return _isPrefabRoot != 0;
}
Actor* Actor::GetPrefabRoot()
{
if (!HasPrefabLink())
return nullptr;
Actor* result = this;
while (result && !result->IsPrefabRoot())
result = result->GetParent();
return result;
}
Actor* Actor::FindActor(const StringView& name) const
{
Actor* result = nullptr;
@@ -1376,14 +1386,16 @@ Actor* Actor::FindActor(const StringView& name) const
return result;
}
Actor* Actor::FindActor(const MClass* type) const
Actor* Actor::FindActor(const MClass* type, bool activeOnly) const
{
CHECK_RETURN(type, nullptr);
if (activeOnly && !_isActive)
return nullptr;
if (GetClass()->IsSubClassOf(type))
return const_cast<Actor*>(this);
for (auto child : Children)
{
const auto actor = child->FindActor(type);
const auto actor = child->FindActor(type, activeOnly);
if (actor)
return actor;
}
@@ -1404,14 +1416,16 @@ Actor* Actor::FindActor(const MClass* type, const StringView& name) const
return nullptr;
}
Actor* Actor::FindActor(const MClass* type, const Tag& tag) const
Actor* Actor::FindActor(const MClass* type, const Tag& tag, bool activeOnly) const
{
CHECK_RETURN(type, nullptr);
if (activeOnly && !_isActive)
return nullptr;
if (GetClass()->IsSubClassOf(type) && HasTag(tag))
return const_cast<Actor*>(this);
for (auto child : Children)
{
const auto actor = child->FindActor(type, tag);
const auto actor = child->FindActor(type, tag, activeOnly);
if (actor)
return actor;
}

View File

@@ -253,10 +253,11 @@ namespace FlaxEngine
/// Tries to find the actor of the given type in this actor hierarchy (checks this actor and all children hierarchy).
/// </summary>
/// <typeparam name="T">Type of the object.</typeparam>
/// <param name="activeOnly">Finds only a active actor.</param>
/// <returns>Actor instance if found, null otherwise.</returns>
public T FindActor<T>() where T : Actor
public T FindActor<T>(bool activeOnly = false) where T : Actor
{
return FindActor(typeof(T)) as T;
return FindActor(typeof(T), activeOnly) as T;
}
/// <summary>
@@ -275,10 +276,11 @@ namespace FlaxEngine
/// </summary>
/// <param name="tag">A tag on the object.</param>
/// <typeparam name="T">Type of the object.</typeparam>
/// <param name="activeOnly">Finds only an active actor.</param>
/// <returns>Actor instance if found, null otherwise.</returns>
public T FindActor<T>(Tag tag) where T : Actor
public T FindActor<T>(Tag tag, bool activeOnly = false) where T : Actor
{
return FindActor(typeof(T), tag) as T;
return FindActor(typeof(T), tag, activeOnly) as T;
}
/// <summary>

View File

@@ -737,6 +737,12 @@ public:
/// </summary>
API_PROPERTY() bool IsPrefabRoot() const;
/// <summary>
/// Gets the root of the prefab this actor is attached to.
/// </summary>
/// <returns>The root prefab object, or null if this actor is not a prefab.</returns>
API_FUNCTION() Actor* GetPrefabRoot();
public:
/// <summary>
/// Tries to find the actor with the given name in this actor hierarchy (checks this actor and all children hierarchy).
@@ -749,8 +755,9 @@ public:
/// Tries to find the actor of the given type in this actor hierarchy (checks this actor and all children hierarchy).
/// </summary>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type.</param>
/// <param name="activeOnly">Finds only a active actor.</param>
/// <returns>Actor instance if found, null otherwise.</returns>
API_FUNCTION() Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type) const;
API_FUNCTION() Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, bool activeOnly = false) const;
/// <summary>
/// Tries to find the actor of the given type and name in this actor hierarchy (checks this actor and all children hierarchy).
@@ -765,8 +772,9 @@ public:
/// </summary>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type.</param>
/// <param name="tag">The tag of the actor to search for.</param>
/// <param name="activeOnly">Finds only an active actor.</param>
/// <returns>Actor instance if found, null otherwise.</returns>
API_FUNCTION() Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, const Tag& tag) const;
API_FUNCTION() Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, const Tag& tag, bool activeOnly = false) const;
/// <summary>
/// Tries to find the actor of the given type in this actor hierarchy (checks this actor and all children hierarchy).

View File

@@ -1396,13 +1396,13 @@ Actor* Level::FindActor(const StringView& name)
return result;
}
Actor* Level::FindActor(const MClass* type)
Actor* Level::FindActor(const MClass* type, bool activeOnly)
{
CHECK_RETURN(type, nullptr);
Actor* result = nullptr;
ScopeLock lock(ScenesLock);
for (int32 i = 0; result == nullptr && i < Scenes.Count(); i++)
result = Scenes[i]->FindActor(type);
result = Scenes[i]->FindActor(type, activeOnly);
return result;
}
@@ -1416,29 +1416,33 @@ Actor* Level::FindActor(const MClass* type, const StringView& name)
return result;
}
Actor* FindActorRecursive(Actor* node, const Tag& tag)
Actor* FindActorRecursive(Actor* node, const Tag& tag, bool activeOnly)
{
if (activeOnly && !node->GetIsActive())
return nullptr;
if (node->HasTag(tag))
return node;
Actor* result = nullptr;
for (Actor* child : node->Children)
{
result = FindActorRecursive(child, tag);
result = FindActorRecursive(child, tag, activeOnly);
if (result)
break;
}
return result;
}
Actor* FindActorRecursiveByType(Actor* node, const MClass* type, const Tag& tag)
Actor* FindActorRecursiveByType(Actor* node, const MClass* type, const Tag& tag, bool activeOnly)
{
CHECK_RETURN(type, nullptr);
if (activeOnly && !node->GetIsActive())
return nullptr;
if (node->HasTag(tag) && node->GetClass()->IsSubClassOf(type))
return node;
Actor* result = nullptr;
for (Actor* child : node->Children)
{
result = FindActorRecursiveByType(child, type, tag);
result = FindActorRecursiveByType(child, type, tag, activeOnly);
if (result)
break;
}
@@ -1471,30 +1475,30 @@ void FindActorsRecursiveByParentTags(Actor* node, const Array<Tag>& tags, const
FindActorsRecursiveByParentTags(child, tags, activeOnly, result);
}
Actor* Level::FindActor(const Tag& tag, Actor* root)
Actor* Level::FindActor(const Tag& tag, bool activeOnly, Actor* root)
{
PROFILE_CPU();
if (root)
return FindActorRecursive(root, tag);
return FindActorRecursive(root, tag, activeOnly);
Actor* result = nullptr;
for (Scene* scene : Scenes)
{
result = FindActorRecursive(scene, tag);
result = FindActorRecursive(scene, tag, activeOnly);
if (result)
break;
}
return result;
}
Actor* Level::FindActor(const MClass* type, const Tag& tag, Actor* root)
Actor* Level::FindActor(const MClass* type, const Tag& tag, bool activeOnly, Actor* root)
{
CHECK_RETURN(type, nullptr);
if (root)
return FindActorRecursiveByType(root, type, tag);
return FindActorRecursiveByType(root, type, tag, activeOnly);
Actor* result = nullptr;
ScopeLock lock(ScenesLock);
for (int32 i = 0; result == nullptr && i < Scenes.Count(); i++)
result = Scenes[i]->FindActor(type, tag);
result = Scenes[i]->FindActor(type, tag, activeOnly);
return result;
}
@@ -1565,12 +1569,14 @@ Script* Level::FindScript(const MClass* type)
namespace
{
void GetActors(const MClass* type, Actor* actor, Array<Actor*>& result)
void GetActors(const MClass* type, Actor* actor, bool activeOnly, Array<Actor*>& result)
{
if (activeOnly && !actor->GetIsActive())
return;
if (actor->GetClass()->IsSubClassOf(type))
result.Add(actor);
for (auto child : actor->Children)
GetActors(type, child, result);
GetActors(type, child, activeOnly, result);
}
void GetScripts(const MClass* type, Actor* actor, Array<Script*>& result)
@@ -1583,13 +1589,13 @@ namespace
}
}
Array<Actor*> Level::GetActors(const MClass* type)
Array<Actor*> Level::GetActors(const MClass* type, bool activeOnly)
{
Array<Actor*> result;
CHECK_RETURN(type, result);
ScopeLock lock(ScenesLock);
for (int32 i = 0; i < Scenes.Count(); i++)
::GetActors(type, Scenes[i], result);
::GetActors(type, Scenes[i], activeOnly, result);
return result;
}

View File

@@ -109,6 +109,8 @@ namespace FlaxEngine
public static T[] GetScripts<T>() where T : Script
{
var scripts = GetScripts(typeof(T));
if (scripts.Length == 0)
return Array.Empty<T>();
var result = new T[scripts.Length];
for (int i = 0; i < scripts.Length; i++)
result[i] = scripts[i] as T;
@@ -119,10 +121,13 @@ namespace FlaxEngine
/// Finds all the actors of the given type in all the loaded scenes.
/// </summary>
/// <typeparam name="T">Type of the object.</typeparam>
/// <param name="activeOnly">Finds only active actors.</param>
/// <returns>Found actors list.</returns>
public static T[] GetActors<T>() where T : Actor
public static T[] GetActors<T>(bool activeOnly = false) where T : Actor
{
var actors = GetActors(typeof(T));
var actors = GetActors(typeof(T), activeOnly);
if (actors.Length == 0)
return Array.Empty<T>();
var result = new T[actors.Length];
for (int i = 0; i < actors.Length; i++)
result[i] = actors[i] as T;

View File

@@ -360,8 +360,9 @@ public:
/// Tries to find the actor of the given type in all the loaded scenes.
/// </summary>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type.</param>
/// <param name="activeOnly">Finds only an active actor.</param>
/// <returns>Found actor or null.</returns>
API_FUNCTION() static Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type);
API_FUNCTION() static Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, bool activeOnly = false);
/// <summary>
/// Tries to find the actor of the given type and name in all the loaded scenes.
@@ -375,18 +376,20 @@ public:
/// Tries to find the actor with the given tag (returns the first one found).
/// </summary>
/// <param name="tag">The tag of the actor to search for.</param>
/// <param name="activeOnly">Finds only an active actor.</param>
/// <param name="root">The custom root actor to start searching from (hierarchical), otherwise null to search all loaded scenes.</param>
/// <returns>Found actor or null.</returns>
API_FUNCTION() static Actor* FindActor(const Tag& tag, Actor* root = nullptr);
API_FUNCTION() static Actor* FindActor(const Tag& tag, bool activeOnly = false, Actor* root = nullptr);
/// <summary>
/// Tries to find the actor of the given type and tag in all the loaded scenes.
/// </summary>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type.</param>
/// <param name="tag">The tag of the actor to search for.</param>
/// <param name="activeOnly">Finds only an active actor.</param>
/// <param name="root">The custom root actor to start searching from (hierarchical), otherwise null to search all loaded scenes.</param>
/// <returns>Actor instance if found, null otherwise.</returns>
API_FUNCTION() static Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, const Tag& tag, Actor* root = nullptr);
API_FUNCTION() static Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, const Tag& tag, bool activeOnly = false, Actor* root = nullptr);
/// <summary>
/// Tries to find the actors with the given tag (returns all found).
@@ -460,8 +463,9 @@ public:
/// Finds all the actors of the given type in all the loaded scenes.
/// </summary>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type.</param>
/// <param name="activeOnly">Finds only active actors in the scene.</param>
/// <returns>Found actors list.</returns>
API_FUNCTION() static Array<Actor*> GetActors(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type);
API_FUNCTION() static Array<Actor*> GetActors(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, bool activeOnly = false);
/// <summary>
/// Finds all the scripts of the given type in all the loaded scenes.

View File

@@ -210,7 +210,7 @@ void CharacterController::CreateController()
// Setup
PhysicsBackend::SetControllerUpDirection(_controller, _upDirection);
PhysicsBackend::SetShapeLocalPose(_shape, _center, Quaternion::Identity);
PhysicsBackend::SetShapeLocalPose(_shape, Vector3::Zero, Quaternion::Identity);
UpdateLayerBits();
UpdateBounds();
}

View File

@@ -7,6 +7,8 @@
#include "Engine/Threading/Threading.h"
#include "IncludeFreeType.h"
Array<AssetReference<FontAsset>, HeapAllocation> Font::FallbackFonts;
Font::Font(FontAsset* parentAsset, float size)
: ManagedScriptingObject(SpawnParams(Guid::New(), Font::TypeInitializer))
, _asset(parentAsset)
@@ -32,7 +34,7 @@ Font::~Font()
_asset->_fonts.Remove(this);
}
void Font::GetCharacter(Char c, FontCharacterEntry& result)
void Font::GetCharacter(Char c, FontCharacterEntry& result, bool enableFallback)
{
// Try to get the character or cache it if cannot be found
if (!_characters.TryGet(c, result))
@@ -44,6 +46,20 @@ void Font::GetCharacter(Char c, FontCharacterEntry& result)
if (_characters.TryGet(c, result))
return;
// Try to use fallback font if character is missing
if (enableFallback && !_asset->ContainsChar(c))
{
for (int32 fallbackIndex = 0; fallbackIndex < FallbackFonts.Count(); fallbackIndex++)
{
FontAsset* fallbackFont = FallbackFonts.Get()[fallbackIndex].Get();
if (fallbackFont && fallbackFont->ContainsChar(c))
{
fallbackFont->CreateFont(GetSize())->GetCharacter(c, result, enableFallback);
return;
}
}
}
// Create character cache
FontManager::AddNewEntry(this, c, result);
@@ -87,7 +103,7 @@ void Font::CacheText(const StringView& text)
FontCharacterEntry entry;
for (int32 i = 0; i < text.Length(); i++)
{
GetCharacter(text[i], entry);
GetCharacter(text[i], entry, false);
}
}
@@ -104,12 +120,14 @@ void Font::Invalidate()
void Font::ProcessText(const StringView& text, Array<FontLineCache>& outputLines, const TextLayoutOptions& layout)
{
int32 textLength = text.Length();
if (textLength == 0)
return;
float cursorX = 0;
int32 kerning;
FontLineCache tmpLine;
FontCharacterEntry entry;
FontCharacterEntry previous;
int32 textLength = text.Length();
float scale = layout.Scale / FontManager::FontScale;
float boundsWidth = layout.Bounds.GetWidth();
float baseLinesDistance = static_cast<float>(_height) * layout.BaseLinesGapScale * scale;
@@ -157,7 +175,7 @@ void Font::ProcessText(const StringView& text, Array<FontLineCache>& outputLines
// Get kerning
if (!isWhitespace && previous.IsValid)
{
kerning = GetKerning(previous.Character, entry.Character);
kerning = entry.Font->GetKerning(previous.Character, entry.Character);
}
else
{
@@ -178,8 +196,8 @@ void Font::ProcessText(const StringView& text, Array<FontLineCache>& outputLines
if (lastWrapCharIndex != INVALID_INDEX)
{
// Skip moving twice for the same character
int32 lastLineLasCharIndex = outputLines.HasItems() ? outputLines.Last().LastCharIndex : -10000;
if (lastLineLasCharIndex == lastWrapCharIndex || lastLineLasCharIndex == lastWrapCharIndex - 1 || lastLineLasCharIndex == lastWrapCharIndex - 2)
int32 lastLineLastCharIndex = outputLines.HasItems() ? outputLines.Last().LastCharIndex : -10000;
if (lastLineLastCharIndex == lastWrapCharIndex || lastLineLastCharIndex == lastWrapCharIndex - 1 || lastLineLastCharIndex == lastWrapCharIndex - 2)
{
currentIndex = nextCharIndex;
lastMoveLine = moveLine;
@@ -238,7 +256,8 @@ void Font::ProcessText(const StringView& text, Array<FontLineCache>& outputLines
lastMoveLine = moveLine;
}
if (textLength != 0 && (tmpLine.LastCharIndex >= tmpLine.FirstCharIndex || text[textLength - 1] == '\n'))
// Check if an additional line should be created
if (tmpLine.LastCharIndex >= tmpLine.FirstCharIndex || text[textLength - 1] == '\n')
{
// Add line
tmpLine.Size.X = cursorX;
@@ -341,7 +360,7 @@ int32 Font::HitTestText(const StringView& text, const Float2& location, const Te
// Apply kerning
if (!isWhitespace && previous.IsValid)
{
x += GetKerning(previous.Character, entry.Character);
x += entry.Font->GetKerning(previous.Character, entry.Character);
}
previous = entry;
@@ -415,7 +434,7 @@ Float2 Font::GetCharPosition(const StringView& text, int32 index, const TextLayo
// Apply kerning
if (!isWhitespace && previous.IsValid)
{
x += GetKerning(previous.Character, entry.Character);
x += entry.Font->GetKerning(previous.Character, entry.Character);
}
previous = entry;

View File

@@ -18,9 +18,9 @@ struct FontTextureAtlasSlot;
/// <summary>
/// The text range.
/// </summary>
API_STRUCT(NoDefault) struct TextRange
API_STRUCT(NoDefault) struct FLAXENGINE_API TextRange
{
DECLARE_SCRIPTING_TYPE_MINIMAL(TextRange);
DECLARE_SCRIPTING_TYPE_MINIMAL(TextRange);
/// <summary>
/// The start index (inclusive).
@@ -35,7 +35,7 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(TextRange);
/// <summary>
/// Gets the range length.
/// </summary>
int32 Length() const
FORCE_INLINE int32 Length() const
{
return EndIndex - StartIndex;
}
@@ -43,7 +43,7 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(TextRange);
/// <summary>
/// Gets a value indicating whether range is empty.
/// </summary>
bool IsEmpty() const
FORCE_INLINE bool IsEmpty() const
{
return (EndIndex - StartIndex) <= 0;
}
@@ -53,7 +53,7 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(TextRange);
/// </summary>
/// <param name="index">The index.</param>
/// <returns><c>true</c> if range contains the specified character index; otherwise, <c>false</c>.</returns>
bool Contains(int32 index) const
FORCE_INLINE bool Contains(int32 index) const
{
return index >= StartIndex && index < EndIndex;
}
@@ -88,9 +88,9 @@ struct TIsPODType<TextRange>
/// <summary>
/// The font line info generated during text processing.
/// </summary>
API_STRUCT(NoDefault) struct FontLineCache
API_STRUCT(NoDefault) struct FLAXENGINE_API FontLineCache
{
DECLARE_SCRIPTING_TYPE_MINIMAL(FontLineCache);
DECLARE_SCRIPTING_TYPE_MINIMAL(FontLineCache);
/// <summary>
/// The root position of the line (upper left corner).
@@ -108,7 +108,7 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(FontLineCache);
API_FIELD() int32 FirstCharIndex;
/// <summary>
/// The last character index (from the input text).
/// The last character index (from the input text), inclusive.
/// </summary>
API_FIELD() int32 LastCharIndex;
};
@@ -152,9 +152,9 @@ struct TIsPODType<FontLineCache>
/// <summary>
/// The cached font character entry (read for rendering and further processing).
/// </summary>
API_STRUCT(NoDefault) struct FontCharacterEntry
API_STRUCT(NoDefault) struct FLAXENGINE_API FontCharacterEntry
{
DECLARE_SCRIPTING_TYPE_MINIMAL(FontCharacterEntry);
DECLARE_SCRIPTING_TYPE_MINIMAL(FontCharacterEntry);
/// <summary>
/// The character represented by this entry.
@@ -210,6 +210,11 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(FontCharacterEntry);
/// The slot in texture atlas, containing the pixel data of the glyph.
/// </summary>
API_FIELD() const FontTextureAtlasSlot* Slot;
/// <summary>
/// The owner font.
/// </summary>
API_FIELD() const class Font* Font;
};
template<>
@@ -223,10 +228,10 @@ struct TIsPODType<FontCharacterEntry>
/// </summary>
API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API Font : public ManagedScriptingObject
{
DECLARE_SCRIPTING_TYPE_NO_SPAWN(Font);
DECLARE_SCRIPTING_TYPE_NO_SPAWN(Font);
friend FontAsset;
private:
private:
FontAsset* _asset;
float _size;
int32 _height;
@@ -238,7 +243,6 @@ private:
mutable Dictionary<uint32, int32> _kerningTable;
public:
/// <summary>
/// Initializes a new instance of the <see cref="Font"/> class.
/// </summary>
@@ -252,6 +256,10 @@ public:
~Font();
public:
/// <summary>
/// The active fallback fonts.
/// </summary>
API_FIELD() static Array<AssetReference<FontAsset>, HeapAllocation> FallbackFonts;
/// <summary>
/// Gets parent font asset that contains font family used by this font.
@@ -302,13 +310,13 @@ public:
}
public:
/// <summary>
/// Gets character entry.
/// </summary>
/// <param name="c">The character.</param>
/// <param name="result">The output character entry.</param>
void GetCharacter(Char c, FontCharacterEntry& result);
/// <param name="enableFallback">True if fallback to secondary font when the primary font doesn't contains this character.</param>
void GetCharacter(Char c, FontCharacterEntry& result, bool enableFallback = true);
/// <summary>
/// Gets the kerning amount for a pair of characters.
@@ -330,7 +338,6 @@ public:
API_FUNCTION() void Invalidate();
public:
/// <summary>
/// Processes text to get cached lines for rendering.
/// </summary>
@@ -524,7 +531,6 @@ public:
void FlushFaceSize() const;
public:
// [Object]
String ToString() const override;
};

View File

@@ -199,14 +199,29 @@ bool FontAsset::Save(const StringView& path)
#endif
bool FontAsset::ContainsChar(Char c) const
{
return FT_Get_Char_Index(_face, c) > 0;
}
void FontAsset::Invalidate()
{
ScopeLock lock(Locker);
for (auto font : _fonts)
{
font->Invalidate();
}
}
uint64 FontAsset::GetMemoryUsage() const
{
Locker.Lock();
uint64 result = BinaryAsset::GetMemoryUsage();
result += sizeof(FontAsset) - sizeof(BinaryAsset);
result += sizeof(FT_FaceRec);
result += _fontFile.Length();
for (auto font : _fonts)
result += sizeof(Font);
Locker.Unlock();
return result;
}
bool FontAsset::init(AssetInitData& initData)

View File

@@ -93,6 +93,7 @@ API_CLASS(NoSpawn) class FLAXENGINE_API FontAsset : public BinaryAsset
{
DECLARE_BINARY_ASSET_HEADER(FontAsset, 3);
friend Font;
private:
FT_Face _face;
FontOptions _options;
@@ -174,11 +175,22 @@ public:
API_FUNCTION() bool Save(const StringView& path = StringView::Empty);
#endif
/// <summary>
/// Check if the font contains the glyph of a char.
/// </summary>
/// <param name="c">The char to test.</param>
/// <returns>True if the font contains the glyph of the char, otherwise false.</returns>
API_FUNCTION() bool ContainsChar(Char c) const;
/// <summary>
/// Invalidates all cached dynamic font atlases using this font. Can be used to reload font characters after changing font asset options.
/// </summary>
API_FUNCTION() void Invalidate();
public:
// [BinaryAsset]
uint64 GetMemoryUsage() const override;
protected:
// [BinaryAsset]
bool init(AssetInitData& initData) override;

View File

@@ -27,7 +27,6 @@ using namespace FontManagerImpl;
class FontManagerService : public EngineService
{
public:
FontManagerService()
: EngineService(TEXT("Font Manager"), -700)
{
@@ -155,6 +154,12 @@ bool FontManager::AddNewEntry(Font* font, Char c, FontCharacterEntry& entry)
// Get the index to the glyph in the font face
const FT_UInt glyphIndex = FT_Get_Char_Index(face, c);
#if !BUILD_RELEASE
if (glyphIndex == 0)
{
LOG(Warning, "Font `{}` doesn't contain character `\\u{:x}`, consider choosing another font. ", String(face->family_name), c);
}
#endif
// Load the glyph
const FT_Error error = FT_Load_Glyph(face, glyphIndex, glyphFlags);
@@ -284,6 +289,7 @@ bool FontManager::AddNewEntry(Font* font, Char c, FontCharacterEntry& entry)
entry.UVSize.X = static_cast<float>(slot->Width - 2 * padding);
entry.UVSize.Y = static_cast<float>(slot->Height - 2 * padding);
entry.Slot = slot;
entry.Font = font;
return false;
}

View File

@@ -27,11 +27,11 @@
#if USE_EDITOR
#define RENDER2D_CHECK_RENDERING_STATE \
if (!Render2D::IsRendering()) \
{ \
LOG(Error, "Calling Render2D is only valid during rendering."); \
return; \
}
if (!Render2D::IsRendering()) \
{ \
LOG(Error, "Calling Render2D is only valid during rendering."); \
return; \
}
#else
#define RENDER2D_CHECK_RENDERING_STATE
#endif
@@ -180,7 +180,7 @@ struct ClipMask
Rectangle Bounds;
};
Render2D::RenderingFeatures Render2D::Features = RenderingFeatures::VertexSnapping;
Render2D::RenderingFeatures Render2D::Features = RenderingFeatures::VertexSnapping | RenderingFeatures::FallbackFonts;
namespace
{
@@ -1137,8 +1137,8 @@ void DrawBatch(int32 startIndex, int32 count)
}
// Draw
Context->BindVB(ToSpan(&vb, 1)); // TODO: reduce bindings frequency
Context->BindIB(ib); // TODO: reduce bindings frequency
Context->BindVB(ToSpan(&vb, 1));
Context->BindIB(ib);
Context->DrawIndexed(countIb, 0, d.StartIB);
}
@@ -1159,6 +1159,7 @@ void Render2D::DrawText(Font* font, const StringView& text, const Color& color,
FontCharacterEntry previous;
int32 kerning;
float scale = 1.0f / FontManager::FontScale;
const bool enableFallbackFonts = EnumHasAllFlags(Features, RenderingFeatures::FallbackFonts);
// Render all characters
FontCharacterEntry entry;
@@ -1183,7 +1184,7 @@ void Render2D::DrawText(Font* font, const StringView& text, const Color& color,
if (currentChar != '\n')
{
// Get character entry
font->GetCharacter(currentChar, entry);
font->GetCharacter(currentChar, entry, enableFallbackFonts);
// Check if need to select/change font atlas (since characters even in the same font may be located in different atlases)
if (fontAtlas == nullptr || entry.TextureIndex != fontAtlasIndex)
@@ -1210,7 +1211,7 @@ void Render2D::DrawText(Font* font, const StringView& text, const Color& color,
// Get kerning
if (!isWhitespace && previous.IsValid)
{
kerning = font->GetKerning(previous.Character, entry.Character);
kerning = entry.Font->GetKerning(previous.Character, entry.Character);
}
else
{
@@ -1273,6 +1274,7 @@ void Render2D::DrawText(Font* font, const StringView& text, const Color& color,
FontCharacterEntry previous;
int32 kerning;
float scale = layout.Scale / FontManager::FontScale;
const bool enableFallbackFonts = EnumHasAllFlags(Features, RenderingFeatures::FallbackFonts);
// Process text to get lines
Lines.Clear();
@@ -1299,10 +1301,14 @@ void Render2D::DrawText(Font* font, const StringView& text, const Color& color,
// Render all characters from the line
for (int32 charIndex = line.FirstCharIndex; charIndex <= line.LastCharIndex; charIndex++)
{
const Char c = text[charIndex];
if (c != '\n')
// Cache current character
const Char currentChar = text[charIndex];
// Check if it isn't a newline character
if (currentChar != '\n')
{
font->GetCharacter(c, entry);
// Get character entry
font->GetCharacter(currentChar, entry, enableFallbackFonts);
// Check if need to select/change font atlas (since characters even in the same font may be located in different atlases)
if (fontAtlas == nullptr || entry.TextureIndex != fontAtlasIndex)
@@ -1324,10 +1330,10 @@ void Render2D::DrawText(Font* font, const StringView& text, const Color& color,
}
// Get kerning
const bool isWhitespace = StringUtils::IsWhitespace(c);
const bool isWhitespace = StringUtils::IsWhitespace(currentChar);
if (!isWhitespace && previous.IsValid)
{
kerning = font->GetKerning(previous.Character, entry.Character);
kerning = entry.Font->GetKerning(previous.Character, entry.Character);
}
else
{
@@ -1931,7 +1937,7 @@ void Render2D::DrawBlur(const Rectangle& rect, float blurStrength)
void Render2D::DrawTexturedTriangles(GPUTexture* t, const Span<Float2>& vertices, const Span<Float2>& uvs)
{
RENDER2D_CHECK_RENDERING_STATE;
CHECK(vertices.Length() == uvs.Length())
CHECK(vertices.Length() == uvs.Length());
Render2DDrawCall& drawCall = DrawCalls.AddOne();
drawCall.Type = DrawCallType::FillTexture;

View File

@@ -44,6 +44,11 @@ API_CLASS(Static) class FLAXENGINE_API Render2D
/// Enables automatic geometry vertices snapping to integer coordinates in screen space. Reduces aliasing and sampling artifacts. Might be disabled for 3D projection viewport or for complex UI transformations.
/// </summary>
VertexSnapping = 1,
/// <summary>
/// Enables automatic characters usage from fallback fonts.
/// </summary>
FallbackFonts = 2,
};
struct CustomData
@@ -452,3 +457,5 @@ public:
/// <param name="color">The color.</param>
API_FUNCTION() static void FillTriangle(const Float2& p0, const Float2& p1, const Float2& p2, const Color& color);
};
DECLARE_ENUM_OPERATORS(Render2D::RenderingFeatures);

View File

@@ -0,0 +1,25 @@
using System;
namespace FlaxEngine;
/// <summary>
/// This attribute is used to check for if a script requires an Actor type.
/// </summary>
[Serializable]
[AttributeUsage(AttributeTargets.Class)]
public class RequireActorAttribute : Attribute
{
/// <summary>
/// The required type.
/// </summary>
public Type RequiredType;
/// <summary>
/// Initializes a new instance of the <see cref="RequireActorAttribute"/> class.
/// </summary>
/// <param name="type">The required type.</param>
public RequireActorAttribute(Type type)
{
RequiredType = type;
}
}

View File

@@ -0,0 +1,34 @@
using System;
namespace FlaxEngine;
/// <summary>
/// This attribute is used to check for if a script requires other script types.
/// </summary>
[Serializable]
[AttributeUsage(AttributeTargets.Class)]
public class RequireScriptAttribute : Attribute
{
/// <summary>
/// The required types.
/// </summary>
public Type[] RequiredTypes;
/// <summary>
/// Initializes a new instance of the <see cref="RequireScriptAttribute"/> class.
/// </summary>
/// <param name="type">The required type.</param>
public RequireScriptAttribute(Type type)
{
RequiredTypes = new[] { type };
}
/// <summary>
/// Initializes a new instance of the <see cref="RequireScriptAttribute"/> class.
/// </summary>
/// <param name="types">The required types.</param>
public RequireScriptAttribute(Type[] types)
{
RequiredTypes = types;
}
}

View File

@@ -610,6 +610,7 @@ FORCE_INLINE byte GetPhysicalMaterial(const Color32& raw, const TerrainDataUpdat
uint8 layer = 0;
uint8 layerWeight = 0;
const int32 splatmapTextureIndex = (chunkZ * info.ChunkSize + z) * info.HeightmapSize + chunkX * info.ChunkSize + x;
ASSERT(splatmapTextureIndex < info.HeightmapLength);
for (int32 splatIndex = 0; splatIndex < TERRAIN_MAX_SPLATMAPS_COUNT; splatIndex++)
{
for (int32 channelIndex = 0; channelIndex < 4; channelIndex++)

View File

@@ -239,7 +239,7 @@ void TextRender::UpdateLayout()
const bool isWhitespace = StringUtils::IsWhitespace(c);
if (!isWhitespace && previous.IsValid)
{
kerning = font->GetKerning(previous.Character, entry.Character);
kerning = entry.Font->GetKerning(previous.Character, entry.Character);
}
else
{

View File

@@ -450,7 +450,7 @@ namespace FlaxEngine
{
camera.GetMatrices(out tmp1, out var tmp3, ref viewport);
Matrix.Multiply(ref tmp1, ref tmp3, out tmp2);
var frustum = new BoundingFrustum(tmp2);
var frustum = new BoundingFrustum(ref tmp2);
_guiRoot.Size = new Float2(frustum.GetWidthAtDepth(Distance), frustum.GetHeightAtDepth(Distance));
}
else

View File

@@ -9,32 +9,30 @@ namespace Flax.Build
/// </summary>
public static class FileCache
{
private static Dictionary<string, FileInfo> fileInfoCache = new Dictionary<string, FileInfo>();
private static readonly Dictionary<string, FileInfo> _cache = new();
public static void FileRemoveFromCache(string path)
{
//fileInfoCache[path].Refresh();
fileInfoCache.Remove(path);
_cache.Remove(path);
}
public static bool Exists(string path)
{
if (fileInfoCache.TryGetValue(path, out var fileInfo))
if (_cache.TryGetValue(path, out var fileInfo))
return fileInfo.Exists;
fileInfo = new FileInfo(path);
fileInfoCache.Add(path, fileInfo);
_cache.Add(path, fileInfo);
return fileInfo.Exists;
}
public static DateTime GetLastWriteTime(string path)
{
if (fileInfoCache.TryGetValue(path, out var fileInfo))
if (_cache.TryGetValue(path, out var fileInfo))
return fileInfo.LastWriteTime;
fileInfo = new FileInfo(path);
fileInfoCache.Add(path, fileInfo);
_cache.Add(path, fileInfo);
return fileInfo.LastWriteTime;
}
}

View File

@@ -77,14 +77,10 @@ namespace Flax.Build
var architectureId = RuntimeInformation.ProcessArchitecture;
switch (architectureId)
{
case Architecture.X86:
return TargetArchitecture.x86;
case Architecture.X64:
return TargetArchitecture.x64;
case Architecture.Arm:
return TargetArchitecture.ARM;
case Architecture.Arm64:
return TargetArchitecture.ARM64;
case Architecture.X86: return TargetArchitecture.x86;
case Architecture.X64: return TargetArchitecture.x64;
case Architecture.Arm: return TargetArchitecture.ARM;
case Architecture.Arm64: return TargetArchitecture.ARM64;
default: throw new NotImplementedException(string.Format("Unsupported build platform {0}.", architectureId));
}
}
@@ -290,12 +286,9 @@ namespace Flax.Build
var subdir = "Binaries/Editor/";
switch (Platform.BuildTargetPlatform)
{
case TargetPlatform.Windows:
return subdir + "Win64";
case TargetPlatform.Linux:
return subdir + "Linux";
case TargetPlatform.Mac:
return subdir + "Mac";
case TargetPlatform.Windows: return subdir + "Win64";
case TargetPlatform.Linux: return subdir + "Linux";
case TargetPlatform.Mac: return subdir + "Mac";
}
throw new NotImplementedException();
}

View File

@@ -58,7 +58,7 @@ namespace Flax.Deploy
DeployFile(src, dst, buildToolExe);
CodeSign(Path.Combine(dst, buildToolExe));
var buildToolDll = "Flax.Build.dll";
DeployFile(src, dst,buildToolDll);
DeployFile(src, dst, buildToolDll);
CodeSign(Path.Combine(dst, buildToolDll));
DeployFile(src, dst, "Flax.Build.xml", true);
DeployFile(src, dst, "Flax.Build.pdb");

View File

@@ -128,7 +128,7 @@ namespace Flax.Deps.Dependencies
case TargetPlatform.Mac:
{
// Build for Mac
foreach (var architecture in new []{ TargetArchitecture.x64, TargetArchitecture.ARM64 })
foreach (var architecture in new[] { TargetArchitecture.x64, TargetArchitecture.ARM64 })
{
RunCmake(root, platform, architecture, " -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF " + globalConfig);
Utilities.Run("make", null, null, root, Utilities.RunOptions.ThrowExceptionOnError);

View File

@@ -172,7 +172,7 @@ namespace Flax.Deps.Dependencies
var buildDir = Path.Combine(root, "build");
// Build for Mac
foreach (var architecture in new []{ TargetArchitecture.x64, TargetArchitecture.ARM64 })
foreach (var architecture in new[] { TargetArchitecture.x64, TargetArchitecture.ARM64 })
{
SetupDirectory(buildDir, true);
RunCmake(buildDir, platform, architecture, ".. -DLIBTYPE=STATIC -DCMAKE_BUILD_TYPE=Release " + config);

View File

@@ -95,7 +95,7 @@ namespace Flax.Deps.Dependencies
case TargetPlatform.Linux:
{
// Build for Linux
var settings = new []
var settings = new[]
{
"--without-librtmp",
"--without-ssl",
@@ -126,7 +126,7 @@ namespace Flax.Deps.Dependencies
case TargetPlatform.Mac:
{
// Build for Mac
var settings = new []
var settings = new[]
{
"--with-secure-transport",
"--without-librtmp",
@@ -137,7 +137,7 @@ namespace Flax.Deps.Dependencies
"--enable-static",
"-disable-ldap --disable-sspi --disable-ftp --disable-file --disable-dict --disable-telnet --disable-tftp --disable-rtsp --disable-pop3 --disable-imap --disable-smtp --disable-gopher --disable-smb",
};
foreach (var architecture in new []{ TargetArchitecture.x64, TargetArchitecture.ARM64 })
foreach (var architecture in new[] { TargetArchitecture.x64, TargetArchitecture.ARM64 })
{
var arch = GetAppleArchName(architecture);
var archName = arch + "-apple-darwin19";

View File

@@ -247,7 +247,7 @@ namespace Flax.Deps.Dependencies
case TargetPlatform.Mac:
{
// Build for Mac
foreach (var architecture in new []{ TargetArchitecture.x64, TargetArchitecture.ARM64 })
foreach (var architecture in new[] { TargetArchitecture.x64, TargetArchitecture.ARM64 })
{
SetupDirectory(buildDir, true);
RunCmake(buildDir, platform, architecture, ".. -DCMAKE_BUILD_TYPE=Release");

View File

@@ -130,7 +130,7 @@ namespace Flax.Deps.Dependencies
};
// Build for Mac
foreach (var architecture in new []{ TargetArchitecture.x64, TargetArchitecture.ARM64 })
foreach (var architecture in new[] { TargetArchitecture.x64, TargetArchitecture.ARM64 })
{
RunCmake(root, platform, architecture, cmakeArgs);
Utilities.Run("cmake", string.Format("--build . --config {0} --target install", configuration), null, buildDir, Utilities.RunOptions.None);

View File

@@ -217,7 +217,7 @@ namespace Flax.Deps.Dependencies
case TargetPlatform.Mac:
{
// Build for Mac
foreach (var architecture in new []{ TargetArchitecture.x64, TargetArchitecture.ARM64 })
foreach (var architecture in new[] { TargetArchitecture.x64, TargetArchitecture.ARM64 })
{
SetupDirectory(buildDir, true);
RunCmake(buildDir, platform, architecture, ".. -DCMAKE_BUILD_TYPE=Release");

View File

@@ -376,7 +376,7 @@ namespace Flax.Deps.Dependencies
GitCheckout(oggRoot, "master", "4380566a44b8d5e85ad511c9c17eb04197863ec5");
// Build for Mac
foreach (var architecture in new []{ TargetArchitecture.x64, TargetArchitecture.ARM64 })
foreach (var architecture in new[] { TargetArchitecture.x64, TargetArchitecture.ARM64 })
{
SetupDirectory(oggBuildDir, true);
RunCmake(oggBuildDir, platform, architecture, ".. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=\"../install\"");

View File

@@ -105,8 +105,7 @@ namespace Flax.Deps
if (totalBytes.HasValue)
progress.Update(totalBytesRead, totalBytes.Value);
}
}
while (hasMoreToRead);
} while (hasMoreToRead);
}
}
}

View File

@@ -18,7 +18,7 @@ namespace Flax.Build.Platforms
public static readonly AndroidSdk Instance = new AndroidSdk();
/// <inheritdoc />
public override TargetPlatform[] Platforms => new []
public override TargetPlatform[] Platforms => new[]
{
TargetPlatform.Windows,
TargetPlatform.Linux,

View File

@@ -77,15 +77,15 @@ namespace Flax.Build.Platforms
/// Returns true if running an x64 binary an arm64 host machine.
/// </summary>
public unsafe static bool GetProcessIsTranslated()
{
int ret = 0;
ulong size = sizeof(int);
if (sysctlbyname("sysctl.proc_translated", &ret, &size, null, 0) == -1)
return false;
return ret != 0;
}
{
int ret = 0;
ulong size = sizeof(int);
if (sysctlbyname("sysctl.proc_translated", &ret, &size, null, 0) == -1)
return false;
return ret != 0;
}
[DllImport("c")]
private static unsafe extern int sysctlbyname(string name, void* oldp, ulong* oldlenp, void* newp, ulong newlen);
private static unsafe extern int sysctlbyname(string name, void* oldp, ulong* oldlenp, void* newp, ulong newlen);
}
}

View File

@@ -410,8 +410,7 @@ namespace Flax.Build.Projects.VisualStudioCode
json.AddField("stopAtEntry", false);
json.AddField("externalConsole", true);
break;
case TargetPlatform.Linux:
break;
case TargetPlatform.Linux: break;
}
}
json.EndObject();

View File

@@ -79,8 +79,7 @@ namespace Flax.Build
}
}
break;
default:
throw new InvalidPlatformException(buildData.Platform.Target);
default: throw new InvalidPlatformException(buildData.Platform.Target);
}
var result = sb.ToString();
BindingsGenerator.PutStringBuilder(sb);