diff --git a/.gitignore b/.gitignore index b7e11e554..30c2caeb2 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/Content/Editor/Fonts/NotoSansSC-Regular.flax b/Content/Editor/Fonts/NotoSansSC-Regular.flax new file mode 100644 index 000000000..39964e6c5 --- /dev/null +++ b/Content/Editor/Fonts/NotoSansSC-Regular.flax @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:19fa43eb7b31ee3936348b1f271c464c79d7020a21d33e3cdbe54f98c3b14304 +size 10560899 diff --git a/Flax.sln.DotSettings b/Flax.sln.DotSettings index ff396d824..80cf8fa1e 100644 --- a/Flax.sln.DotSettings +++ b/Flax.sln.DotSettings @@ -73,8 +73,12 @@ <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> + AI LO + RPC + SDK VS + <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> diff --git a/Source/Editor/Content/Proxy/ScriptProxy.cs b/Source/Editor/Content/Proxy/ScriptProxy.cs index f688f37df..d728dcc38 100644 --- a/Source/Editor/Content/Proxy/ScriptProxy.cs +++ b/Source/Editor/Content/Proxy/ScriptProxy.cs @@ -69,8 +69,7 @@ namespace FlaxEditor.Content /// 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; diff --git a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs index e1a358b6e..63374361d 100644 --- a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs @@ -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"; + } + } + /// /// Drag and drop scripts area control. /// @@ -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); + } + /// 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); + } + + /// + /// Attach a script to the actor. + /// + /// The script. + public void AddScript(ScriptType item) { var list = new List(1) { item }; AddScripts(list); @@ -224,16 +333,67 @@ namespace FlaxEditor.CustomEditors.Dedicated private void AddScripts(List items) { - var actions = new List(4); + var actions = new List(); 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 /// public override IEnumerable UndoObjects => _scripts; + /// + /// Cached the newly created script name - used to add script after compilation. + /// + 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(); 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)) diff --git a/Source/Editor/EditorAssets.cs b/Source/Editor/EditorAssets.cs index eb2f21356..8b2049ebd 100644 --- a/Source/Editor/EditorAssets.cs +++ b/Source/Editor/EditorAssets.cs @@ -54,6 +54,11 @@ namespace FlaxEditor /// public static string PrimaryFont = "Editor/Fonts/Roboto-Regular"; + /// + /// The secondary (fallback) font to use for missing characters rendering (CJK - Chinese/Japanese/Korean characters). + /// + public static string FallbackFont = "Editor/Fonts/NotoSansSC-Regular"; + /// /// The Inconsolata Regular font. /// diff --git a/Source/Editor/GUI/ItemsListContextMenu.cs b/Source/Editor/GUI/ItemsListContextMenu.cs index 42d236991..c8c2a9c22 100644 --- a/Source/Editor/GUI/ItemsListContextMenu.cs +++ b/Source/Editor/GUI/ItemsListContextMenu.cs @@ -189,6 +189,11 @@ namespace FlaxEditor.GUI /// public event Action ItemClicked; + /// + /// Event fired when search text in this popup menu gets changed. + /// + public event Action TextChanged; + /// /// The panel control where you should add your items. /// @@ -263,6 +268,7 @@ namespace FlaxEditor.GUI UnlockChildrenRecursive(); PerformLayout(true); _searchBox.Focus(); + TextChanged?.Invoke(_searchBox.Text); } /// @@ -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) { diff --git a/Source/Editor/GUI/Row.cs b/Source/Editor/GUI/Row.cs index ca45ec6f5..3e2bb63bd 100644 --- a/Source/Editor/GUI/Row.cs +++ b/Source/Editor/GUI/Row.cs @@ -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; } /// diff --git a/Source/Editor/Modules/UIModule.cs b/Source/Editor/Modules/UIModule.cs index 4537d732e..e71c93dcc 100644 --- a/Source/Editor/Modules/UIModule.cs +++ b/Source/Editor/Modules/UIModule.cs @@ -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) diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs index 95a273f19..c33cd3674 100644 --- a/Source/Editor/Options/InterfaceOptions.cs +++ b/Source/Editor/Options/InterfaceOptions.cs @@ -172,9 +172,9 @@ namespace FlaxEditor.Options set { if (value == null) - _outputLogFont = new FontReference(FlaxEngine.Content.LoadAsyncInternal(EditorAssets.InconsolataRegularFont), 10); + _outputLogFont = new FontReference(ConsoleFont, 10); else if (!value.Font) - _outputLogFont.Font = FlaxEngine.Content.LoadAsyncInternal(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(EditorAssets.PrimaryFont); + private static FontAsset ConsoleFont => FlaxEngine.Content.LoadAsyncInternal(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(EditorAssets.InconsolataRegularFont), 10); + private FontReference _outputLogFont = new FontReference(ConsoleFont, 10); + + /// + /// The list of fallback fonts to use when main text font is missing certain characters. Empty to use fonts from GraphicsSettings. + /// + [EditorDisplay("Fonts"), EditorOrder(650)] + public FontAsset[] FallbackFonts = new FontAsset[1] { FlaxEngine.Content.LoadAsyncInternal(EditorAssets.FallbackFont) }; /// /// Gets or sets the title font for editor UI. diff --git a/Source/Editor/Options/OptionsModule.cs b/Source/Editor/Options/OptionsModule.cs index 1137e4c37..bb90be6d9 100644 --- a/Source/Editor/Options/OptionsModule.cs +++ b/Source/Editor/Options/OptionsModule.cs @@ -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; @@ -217,12 +219,18 @@ namespace FlaxEditor.Options if (styleName == ThemeOptions.LightDefault) { Style.Current = CreateLightStyle(); - } + } else { 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().FallbackFonts; + Font.FallbackFonts = fallbackFonts; } /// diff --git a/Source/Editor/SceneGraph/Actors/SplineNode.cs b/Source/Editor/SceneGraph/Actors/SplineNode.cs index acd23130d..e6ff43e9f 100644 --- a/Source/Editor/SceneGraph/Actors/SplineNode.cs +++ b/Source/Editor/SceneGraph/Actors/SplineNode.cs @@ -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; /// 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); + } + } + /// 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.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.Keyframe() { Value = new Transform(Vector3.Forward * 100, Quaternion.Identity, Vector3.One), @@ -413,6 +546,39 @@ namespace FlaxEditor.SceneGraph.Actors } } + private static List GetSplinesInView() + { + var splines = Level.GetActors(true); + var result = new List(); + 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 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; diff --git a/Source/Editor/Surface/ContextMenu/VisjectCM.cs b/Source/Editor/Surface/ContextMenu/VisjectCM.cs index 930741807..ad4bf8372 100644 --- a/Source/Editor/Surface/ContextMenu/VisjectCM.cs +++ b/Source/Editor/Surface/ContextMenu/VisjectCM.cs @@ -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); diff --git a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs index 207875a92..9adfb881e 100644 --- a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs +++ b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs @@ -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 /// True if item's group header got a filter match and item should stay visible. 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(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(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(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(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(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(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; } /// diff --git a/Source/Editor/Tools/Terrain/PaintTerrainGizmoMode.cs b/Source/Editor/Tools/Terrain/PaintTerrainGizmoMode.cs index 4e7925dd9..7d6af355a 100644 --- a/Source/Editor/Tools/Terrain/PaintTerrainGizmoMode.cs +++ b/Source/Editor/Tools/Terrain/PaintTerrainGizmoMode.cs @@ -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(); } diff --git a/Source/Editor/Utilities/QueryFilterHelper.cs b/Source/Editor/Utilities/QueryFilterHelper.cs index e9e5e9ccb..f2db81009 100644 --- a/Source/Editor/Utilities/QueryFilterHelper.cs +++ b/Source/Editor/Utilities/QueryFilterHelper.cs @@ -140,8 +140,7 @@ namespace FlaxEditor.Utilities // Check if start the matching sequence if (matchStartPos == -1) { - if (ranges == null) - ranges = new List(); + ranges ??= new List(); 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; diff --git a/Source/Editor/Viewport/Cameras/FPSCamera.cs b/Source/Editor/Viewport/Cameras/FPSCamera.cs index bf2e840ea..0bbcfd0e8 100644 --- a/Source/Editor/Viewport/Cameras/FPSCamera.cs +++ b/Source/Editor/Viewport/Cameras/FPSCamera.cs @@ -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); diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs index 526a84c45..759c3736a 100644 --- a/Source/Editor/Viewport/EditorViewport.cs +++ b/Source/Editor/Viewport/EditorViewport.cs @@ -334,6 +334,22 @@ namespace FlaxEditor.Viewport } } + /// + /// Gets the bounding frustum of the current viewport camera. + /// + 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); + } + } + /// /// Gets or sets the yaw angle (in degrees). /// diff --git a/Source/Editor/Windows/Assets/FontWindow.cs b/Source/Editor/Windows/Assets/FontWindow.cs index ff4135165..bc91ca5e2 100644 --- a/Source/Editor/Windows/Assets/FontWindow.cs +++ b/Source/Editor/Windows/Assets/FontWindow.cs @@ -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); diff --git a/Source/Editor/Windows/GameWindow.cs b/Source/Editor/Windows/GameWindow.cs index 4a8c11176..9368a30fd 100644 --- a/Source/Editor/Windows/GameWindow.cs +++ b/Source/Editor/Windows/GameWindow.cs @@ -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"); diff --git a/Source/Engine/Core/Collections/Array.h b/Source/Engine/Core/Collections/Array.h index a8390f051..d67aecbc1 100644 --- a/Source/Engine/Core/Collections/Array.h +++ b/Source/Engine/Core/Collections/Array.h @@ -250,6 +250,16 @@ public: return _count == 0; } + /// + /// Determines if given index is valid. + /// + /// The index. + /// true if is valid a index; otherwise, false. + bool IsValidIndex(int32 index) const + { + return index < _count && index >= 0; + } + /// /// Gets the pointer to the first item in the collection (linear allocation). /// diff --git a/Source/Engine/Core/Config/GameSettings.cs b/Source/Engine/Core/Config/GameSettings.cs index 40d9f5dbc..76c968968 100644 --- a/Source/Engine/Core/Config/GameSettings.cs +++ b/Source/Engine/Core/Config/GameSettings.cs @@ -119,7 +119,7 @@ namespace FlaxEditor.Content.Settings /// /// 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(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 CustomSettings; #if FLAX_EDITOR || PLATFORM_WINDOWS diff --git a/Source/Engine/Core/Config/GraphicsSettings.h b/Source/Engine/Core/Config/GraphicsSettings.h index 81d80cb35..b639b9e64 100644 --- a/Source/Engine/Core/Config/GraphicsSettings.h +++ b/Source/Engine/Core/Config/GraphicsSettings.h @@ -6,6 +6,8 @@ #include "Engine/Graphics/Enums.h" #include "Engine/Graphics/PostProcessSettings.h" +class FontAsset; + /// /// Graphics rendering settings. /// @@ -13,6 +15,7 @@ API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings", NoConstructor) class { API_AUTO_SERIALIZATION(); DECLARE_SCRIPTING_TYPE_MINIMAL(GraphicsSettings); + public: /// /// 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; + /// + /// The list of fallback fonts used for text rendering. Ignored if empty. + /// + API_FIELD(Attributes="EditorOrder(5000), EditorDisplay(\"Text\")") + Array> FallbackFonts; + private: /// /// Renamed UeeHDRProbes into UseHDRProbes diff --git a/Source/Engine/Core/Math/BoundingFrustum.cs b/Source/Engine/Core/Math/BoundingFrustum.cs index 970957fbb..25cd0c33b 100644 --- a/Source/Engine/Core/Math/BoundingFrustum.cs +++ b/Source/Engine/Core/Math/BoundingFrustum.cs @@ -104,6 +104,16 @@ namespace FlaxEngine GetPlanesFromMatrix(ref pMatrix, out pNear, out pFar, out pLeft, out pRight, out pTop, out pBottom); } + /// + /// Creates a new instance of BoundingFrustum. + /// + /// Combined matrix that usually takes view × projection matrix. + public BoundingFrustum(ref Matrix matrix) + { + pMatrix = matrix; + GetPlanesFromMatrix(ref pMatrix, out pNear, out pFar, out pLeft, out pRight, out pTop, out pBottom); + } + /// /// Returns a hash code for this instance. /// diff --git a/Source/Engine/Debug/DebugDraw.cpp b/Source/Engine/Debug/DebugDraw.cpp index bd7a218a7..8f65e609d 100644 --- a/Source/Engine/Debug/DebugDraw.cpp +++ b/Source/Engine/Debug/DebugDraw.cpp @@ -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; diff --git a/Source/Engine/Debug/DebugDraw.cs b/Source/Engine/Debug/DebugDraw.cs index 8ff04d072..134c3f852 100644 --- a/Source/Engine/Debug/DebugDraw.cs +++ b/Source/Engine/Debug/DebugDraw.cs @@ -31,6 +31,17 @@ namespace FlaxEngine { } + /// + /// Draws the lines axis from direction. + /// + /// The origin of the line. + /// The direction of the line. + /// The color. + /// The size of the axis. + /// The duration (in seconds). Use 0 to draw it only once. + /// If set to true depth test will be performed, otherwise depth will be ignored. + public static void DrawAxisFromDirection(Vector3 origin, Vector3 direction, Color color ,float Size = 100.0f, float duration = 0.0f, bool depthTest = true){} + /// /// Draws the line in a direction. /// @@ -39,7 +50,28 @@ namespace FlaxEngine /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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){} + + /// + /// Draws the line in a direction. + /// + /// The origin of the line. + /// The direction of the line. + /// The color. + /// The length of the ray. + /// The duration (in seconds). Use 0 to draw it only once. + /// If set to true depth test will be performed, otherwise depth will be ignored. + public static void DrawRay(Vector3 origin, Vector3 direction, Color color, float length = 3.402823466e+38f, float duration = 0.0f, bool depthTest = true){} + + /// + /// Draws the line in a direction. + /// + /// The ray. + /// The color. + /// The length of the ray. + /// The duration (in seconds). Use 0 to draw it only once. + /// If set to true depth test will be performed, otherwise depth will be ignored. + public static void DrawRay(Ray ray,Color color, float length = 3.402823466e+38f, float duration = 0.0f, bool depthTest = true) { } diff --git a/Source/Engine/Debug/DebugDraw.h b/Source/Engine/Debug/DebugDraw.h index 30feb4440..8d44b81e6 100644 --- a/Source/Engine/Debug/DebugDraw.h +++ b/Source/Engine/Debug/DebugDraw.h @@ -24,7 +24,6 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw DECLARE_SCRIPTING_TYPE_NO_SPAWN(DebugDraw); #if USE_EDITOR - /// /// Allocates the context for Debug Drawing. Can be use to redirect debug shapes collecting to a separate container (instead of global state). /// @@ -49,7 +48,6 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// /// The context or null. API_FUNCTION() static void SetContext(void* context); - #endif /// @@ -69,6 +67,16 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// True if draw all debug shapes from scenes too or false if draw just from specified actor list. API_FUNCTION() static void DrawActors(Actor** selectedActors, int32 selectedActorsCount, bool drawScenes); + /// + /// Draws the lines axis from direction. + /// + /// The origin of the line. + /// The direction of the line. + /// The size of the axis. + /// The duration (in seconds). Use 0 to draw it only once. + /// If set to true depth test will be performed, otherwise depth will be ignored. + API_FUNCTION() static void DrawAxisFromDirection(const Vector3& origin, const Vector3& direction, float size = 100.0f, float duration = 0.0f, bool depthTest = true); + /// /// Draws the line in a direction. /// @@ -77,7 +85,28 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); + + /// + /// Draws the line in a direction. + /// + /// The origin of the line. + /// The direction of the line. + /// The color. + /// The length of the ray. + /// The duration (in seconds). Use 0 to draw it only once. + /// If set to true depth test will be performed, otherwise depth will be ignored. + 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); + + /// + /// Draws the line in a direction. + /// + /// The ray. + /// The color. + /// The length of the ray. + /// The duration (in seconds). Use 0 to draw it only once. + /// If set to true depth test will be performed, otherwise depth will be ignored. + API_FUNCTION() static void DrawRay(const Ray& ray, const Color& color = Color::White, float length = MAX_float, float duration = 0.0f, bool depthTest = true); /// /// Draws the line. @@ -87,7 +116,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the line. @@ -108,7 +137,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - API_FUNCTION() static void DrawLines(const Span& lines, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true); + API_FUNCTION() static void DrawLines(const Span& lines, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// 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 /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - static void DrawLines(const Array& lines, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true); + static void DrawLines(const Array& lines, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// 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 /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - API_FUNCTION() static void DrawLines(const Span& lines, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true); + API_FUNCTION() static void DrawLines(const Span& lines, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// 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 /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - static void DrawLines(const Array& lines, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true); + static void DrawLines(const Array& lines, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws a Bezier curve. @@ -150,7 +179,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The line color /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the circle. @@ -161,7 +190,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the wireframe triangle. @@ -172,7 +201,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the triangle. @@ -183,7 +212,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the triangles. @@ -192,7 +221,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - API_FUNCTION() static void DrawTriangles(const Span& vertices, const Color& color, float duration = 0.0f, bool depthTest = true); + API_FUNCTION() static void DrawTriangles(const Span& vertices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the triangles. @@ -202,7 +231,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - API_FUNCTION() static void DrawTriangles(const Span& vertices, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true); + API_FUNCTION() static void DrawTriangles(const Span& vertices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the triangles. @@ -211,7 +240,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - static void DrawTriangles(const Array& vertices, const Color& color, float duration = 0.0f, bool depthTest = true); + static void DrawTriangles(const Array& vertices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the triangles. @@ -221,7 +250,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - static void DrawTriangles(const Array& vertices, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true); + static void DrawTriangles(const Array& vertices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the triangles using the given index buffer. @@ -231,7 +260,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - API_FUNCTION() static void DrawTriangles(const Span& vertices, const Span& indices, const Color& color, float duration = 0.0f, bool depthTest = true); + API_FUNCTION() static void DrawTriangles(const Span& vertices, const Span& indices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the triangles using the given index buffer. @@ -242,7 +271,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - API_FUNCTION() static void DrawTriangles(const Span& vertices, const Span& indices, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true); + API_FUNCTION() static void DrawTriangles(const Span& vertices, const Span& indices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the triangles using the given index buffer. @@ -252,7 +281,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - static void DrawTriangles(const Array& vertices, const Array& indices, const Color& color, float duration = 0.0f, bool depthTest = true); + static void DrawTriangles(const Array& vertices, const Array& indices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the triangles using the given index buffer. @@ -263,7 +292,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - static void DrawTriangles(const Array& vertices, const Array& indices, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true); + static void DrawTriangles(const Array& vertices, const Array& indices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the triangles. @@ -272,7 +301,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - API_FUNCTION() static void DrawTriangles(const Span& vertices, const Color& color, float duration = 0.0f, bool depthTest = true); + API_FUNCTION() static void DrawTriangles(const Span& vertices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the triangles. @@ -282,7 +311,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - API_FUNCTION() static void DrawTriangles(const Span& vertices, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true); + API_FUNCTION() static void DrawTriangles(const Span& vertices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the triangles. @@ -291,7 +320,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - static void DrawTriangles(const Array& vertices, const Color& color, float duration = 0.0f, bool depthTest = true); + static void DrawTriangles(const Array& vertices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the triangles. @@ -301,7 +330,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - static void DrawTriangles(const Array& vertices, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true); + static void DrawTriangles(const Array& vertices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the triangles using the given index buffer. @@ -311,7 +340,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - API_FUNCTION() static void DrawTriangles(const Span& vertices, const Span& indices, const Color& color, float duration = 0.0f, bool depthTest = true); + API_FUNCTION() static void DrawTriangles(const Span& vertices, const Span& indices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the triangles using the given index buffer. @@ -322,7 +351,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - API_FUNCTION() static void DrawTriangles(const Span& vertices, const Span& indices, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true); + API_FUNCTION() static void DrawTriangles(const Span& vertices, const Span& indices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the triangles using the given index buffer. @@ -332,7 +361,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - static void DrawTriangles(const Array& vertices, const Array& indices, const Color& color, float duration = 0.0f, bool depthTest = true); + static void DrawTriangles(const Array& vertices, const Array& indices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the triangles using the given index buffer. @@ -343,7 +372,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - static void DrawTriangles(const Array& vertices, const Array& indices, const Matrix& transform, const Color& color, float duration = 0.0f, bool depthTest = true); + static void DrawTriangles(const Array& vertices, const Array& indices, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the wireframe triangles. @@ -352,7 +381,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - API_FUNCTION() static void DrawWireTriangles(const Span& vertices, const Color& color, float duration = 0.0f, bool depthTest = true); + API_FUNCTION() static void DrawWireTriangles(const Span& vertices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the wireframe triangles. @@ -361,7 +390,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - static void DrawWireTriangles(const Array& vertices, const Color& color, float duration = 0.0f, bool depthTest = true); + static void DrawWireTriangles(const Array& vertices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the wireframe triangles using the given index buffer. @@ -371,7 +400,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - API_FUNCTION() static void DrawWireTriangles(const Span& vertices, const Span& indices, const Color& color, float duration = 0.0f, bool depthTest = true); + API_FUNCTION() static void DrawWireTriangles(const Span& vertices, const Span& indices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the wireframe triangles using the given index buffer. @@ -381,7 +410,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - static void DrawWireTriangles(const Array& vertices, const Array& indices, const Color& color, float duration = 0.0f, bool depthTest = true); + static void DrawWireTriangles(const Array& vertices, const Array& indices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the wireframe triangles. @@ -390,7 +419,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - API_FUNCTION() static void DrawWireTriangles(const Span& vertices, const Color& color, float duration = 0.0f, bool depthTest = true); + API_FUNCTION() static void DrawWireTriangles(const Span& vertices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the wireframe triangles. @@ -399,7 +428,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - static void DrawWireTriangles(const Array& vertices, const Color& color, float duration = 0.0f, bool depthTest = true); + static void DrawWireTriangles(const Array& vertices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the wireframe triangles using the given index buffer. @@ -409,7 +438,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - API_FUNCTION() static void DrawWireTriangles(const Span& vertices, const Span& indices, const Color& color, float duration = 0.0f, bool depthTest = true); + API_FUNCTION() static void DrawWireTriangles(const Span& vertices, const Span& indices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the wireframe triangles using the given index buffer. @@ -419,7 +448,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - static void DrawWireTriangles(const Array& vertices, const Array& indices, const Color& color, float duration = 0.0f, bool depthTest = true); + static void DrawWireTriangles(const Array& vertices, const Array& indices, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true); /// /// Draws the wireframe box. @@ -428,7 +457,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the wireframe frustum. @@ -437,7 +466,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the wireframe box. @@ -446,7 +475,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the wireframe sphere. @@ -455,7 +484,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the sphere. @@ -464,7 +493,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the tube. @@ -476,7 +505,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the wireframe tube. @@ -488,7 +517,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the cylinder. @@ -500,7 +529,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the wireframe cylinder. @@ -512,7 +541,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the cone. @@ -525,7 +554,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the wireframe cone. @@ -538,7 +567,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the arc. @@ -550,7 +579,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the wireframe arc. @@ -562,7 +591,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the wireframe arrow. @@ -574,7 +603,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the box. @@ -583,7 +612,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the box. @@ -592,7 +621,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The duration (in seconds). Use 0 to draw it only once. /// If set to true depth test will be performed, otherwise depth will be ignored. - 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); /// /// Draws the text on a screen (2D). @@ -602,7 +631,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The font size. /// The duration (in seconds). Use 0 to draw it only once. - 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); /// /// Draws the text (3D) that automatically faces the camera. @@ -613,7 +642,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The font size. /// The duration (in seconds). Use 0 to draw it only once. /// The text scale. - 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); /// /// Draws the text (3D). @@ -623,39 +652,45 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw /// The color. /// The font size. /// The duration (in seconds). Use 0 to draw it only once. - 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) diff --git a/Source/Engine/Graphics/Graphics.cpp b/Source/Engine/Graphics/Graphics.cpp index f91c58cea..a9bfef470 100644 --- a/Source/Engine/Graphics/Graphics.cpp +++ b/Source/Engine/Graphics/Graphics.cpp @@ -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() diff --git a/Source/Engine/Graphics/RenderView.cs b/Source/Engine/Graphics/RenderView.cs index b770037a3..72cfe3577 100644 --- a/Source/Engine/Graphics/RenderView.cs +++ b/Source/Engine/Graphics/RenderView.cs @@ -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; } diff --git a/Source/Engine/Level/Actor.cpp b/Source/Engine/Level/Actor.cpp index 7e2329389..64ad37b8e 100644 --- a/Source/Engine/Level/Actor.cpp +++ b/Source/Engine/Level/Actor.cpp @@ -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(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(this); for (auto child : Children) { - const auto actor = child->FindActor(type, tag); + const auto actor = child->FindActor(type, tag, activeOnly); if (actor) return actor; } diff --git a/Source/Engine/Level/Actor.cs b/Source/Engine/Level/Actor.cs index 1d64ff5ae..5b9d365d3 100644 --- a/Source/Engine/Level/Actor.cs +++ b/Source/Engine/Level/Actor.cs @@ -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). /// /// Type of the object. + /// Finds only a active actor. /// Actor instance if found, null otherwise. - public T FindActor() where T : Actor + public T FindActor(bool activeOnly = false) where T : Actor { - return FindActor(typeof(T)) as T; + return FindActor(typeof(T), activeOnly) as T; } /// @@ -275,10 +276,11 @@ namespace FlaxEngine /// /// A tag on the object. /// Type of the object. + /// Finds only an active actor. /// Actor instance if found, null otherwise. - public T FindActor(Tag tag) where T : Actor + public T FindActor(Tag tag, bool activeOnly = false) where T : Actor { - return FindActor(typeof(T), tag) as T; + return FindActor(typeof(T), tag, activeOnly) as T; } /// diff --git a/Source/Engine/Level/Actor.h b/Source/Engine/Level/Actor.h index f66d13f40..ddf6f0587 100644 --- a/Source/Engine/Level/Actor.h +++ b/Source/Engine/Level/Actor.h @@ -737,6 +737,12 @@ public: /// API_PROPERTY() bool IsPrefabRoot() const; + /// + /// Gets the root of the prefab this actor is attached to. + /// + /// The root prefab object, or null if this actor is not a prefab. + API_FUNCTION() Actor* GetPrefabRoot(); + public: /// /// 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). /// /// Type of the actor to search for. Includes any actors derived from the type. + /// Finds only a active actor. /// Actor instance if found, null otherwise. - 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; /// /// 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: /// /// Type of the actor to search for. Includes any actors derived from the type. /// The tag of the actor to search for. + /// Finds only an active actor. /// Actor instance if found, null otherwise. - 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; /// /// Tries to find the actor of the given type in this actor hierarchy (checks this actor and all children hierarchy). @@ -788,7 +796,7 @@ public: { return (T*)FindActor(T::GetStaticClass(), name); } - + /// /// Tries to find the actor of the given type and tag in this actor hierarchy (checks this actor and all children hierarchy). /// diff --git a/Source/Engine/Level/Level.cpp b/Source/Engine/Level/Level.cpp index 41033876d..f4d9e428b 100644 --- a/Source/Engine/Level/Level.cpp +++ b/Source/Engine/Level/Level.cpp @@ -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& 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& result) + void GetActors(const MClass* type, Actor* actor, bool activeOnly, Array& 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& result) @@ -1583,13 +1589,13 @@ namespace } } -Array Level::GetActors(const MClass* type) +Array Level::GetActors(const MClass* type, bool activeOnly) { Array 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; } diff --git a/Source/Engine/Level/Level.cs b/Source/Engine/Level/Level.cs index 1e8524f2c..3e367195e 100644 --- a/Source/Engine/Level/Level.cs +++ b/Source/Engine/Level/Level.cs @@ -109,6 +109,8 @@ namespace FlaxEngine public static T[] GetScripts() where T : Script { var scripts = GetScripts(typeof(T)); + if (scripts.Length == 0) + return Array.Empty(); 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. /// /// Type of the object. + /// Finds only active actors. /// Found actors list. - public static T[] GetActors() where T : Actor + public static T[] GetActors(bool activeOnly = false) where T : Actor { - var actors = GetActors(typeof(T)); + var actors = GetActors(typeof(T), activeOnly); + if (actors.Length == 0) + return Array.Empty(); var result = new T[actors.Length]; for (int i = 0; i < actors.Length; i++) result[i] = actors[i] as T; diff --git a/Source/Engine/Level/Level.h b/Source/Engine/Level/Level.h index e09f8e376..ac6a14238 100644 --- a/Source/Engine/Level/Level.h +++ b/Source/Engine/Level/Level.h @@ -360,8 +360,9 @@ public: /// Tries to find the actor of the given type in all the loaded scenes. /// /// Type of the actor to search for. Includes any actors derived from the type. + /// Finds only an active actor. /// Found actor or null. - 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); /// /// 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). /// /// The tag of the actor to search for. + /// Finds only an active actor. /// The custom root actor to start searching from (hierarchical), otherwise null to search all loaded scenes. /// Found actor or null. - 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); /// /// Tries to find the actor of the given type and tag in all the loaded scenes. /// /// Type of the actor to search for. Includes any actors derived from the type. /// The tag of the actor to search for. + /// Finds only an active actor. /// The custom root actor to start searching from (hierarchical), otherwise null to search all loaded scenes. /// Actor instance if found, null otherwise. - 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); /// /// 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. /// /// Type of the actor to search for. Includes any actors derived from the type. + /// Finds only active actors in the scene. /// Found actors list. - API_FUNCTION() static Array GetActors(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type); + API_FUNCTION() static Array GetActors(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, bool activeOnly = false); /// /// Finds all the scripts of the given type in all the loaded scenes. diff --git a/Source/Engine/Physics/Colliders/CharacterController.cpp b/Source/Engine/Physics/Colliders/CharacterController.cpp index e9f86ebab..db15dd46f 100644 --- a/Source/Engine/Physics/Colliders/CharacterController.cpp +++ b/Source/Engine/Physics/Colliders/CharacterController.cpp @@ -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(); } diff --git a/Source/Engine/Render2D/Font.cpp b/Source/Engine/Render2D/Font.cpp index 90423f5ce..71eca1f59 100644 --- a/Source/Engine/Render2D/Font.cpp +++ b/Source/Engine/Render2D/Font.cpp @@ -7,6 +7,8 @@ #include "Engine/Threading/Threading.h" #include "IncludeFreeType.h" +Array, 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& 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(_height) * layout.BaseLinesGapScale * scale; @@ -157,7 +175,7 @@ void Font::ProcessText(const StringView& text, Array& 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& 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& 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; diff --git a/Source/Engine/Render2D/Font.h b/Source/Engine/Render2D/Font.h index 90f723cd8..c55bb58a1 100644 --- a/Source/Engine/Render2D/Font.h +++ b/Source/Engine/Render2D/Font.h @@ -18,9 +18,9 @@ struct FontTextureAtlasSlot; /// /// The text range. /// -API_STRUCT(NoDefault) struct TextRange +API_STRUCT(NoDefault) struct FLAXENGINE_API TextRange { -DECLARE_SCRIPTING_TYPE_MINIMAL(TextRange); + DECLARE_SCRIPTING_TYPE_MINIMAL(TextRange); /// /// The start index (inclusive). @@ -35,7 +35,7 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(TextRange); /// /// Gets the range length. /// - int32 Length() const + FORCE_INLINE int32 Length() const { return EndIndex - StartIndex; } @@ -43,7 +43,7 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(TextRange); /// /// Gets a value indicating whether range is empty. /// - bool IsEmpty() const + FORCE_INLINE bool IsEmpty() const { return (EndIndex - StartIndex) <= 0; } @@ -53,7 +53,7 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(TextRange); /// /// The index. /// true if range contains the specified character index; otherwise, false. - bool Contains(int32 index) const + FORCE_INLINE bool Contains(int32 index) const { return index >= StartIndex && index < EndIndex; } @@ -88,9 +88,9 @@ struct TIsPODType /// /// The font line info generated during text processing. /// -API_STRUCT(NoDefault) struct FontLineCache +API_STRUCT(NoDefault) struct FLAXENGINE_API FontLineCache { -DECLARE_SCRIPTING_TYPE_MINIMAL(FontLineCache); + DECLARE_SCRIPTING_TYPE_MINIMAL(FontLineCache); /// /// The root position of the line (upper left corner). @@ -108,7 +108,7 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(FontLineCache); API_FIELD() int32 FirstCharIndex; /// - /// The last character index (from the input text). + /// The last character index (from the input text), inclusive. /// API_FIELD() int32 LastCharIndex; }; @@ -152,9 +152,9 @@ struct TIsPODType /// /// The cached font character entry (read for rendering and further processing). /// -API_STRUCT(NoDefault) struct FontCharacterEntry +API_STRUCT(NoDefault) struct FLAXENGINE_API FontCharacterEntry { -DECLARE_SCRIPTING_TYPE_MINIMAL(FontCharacterEntry); + DECLARE_SCRIPTING_TYPE_MINIMAL(FontCharacterEntry); /// /// 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. /// API_FIELD() const FontTextureAtlasSlot* Slot; + + /// + /// The owner font. + /// + API_FIELD() const class Font* Font; }; template<> @@ -223,10 +228,10 @@ struct TIsPODType /// 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 _kerningTable; public: - /// /// Initializes a new instance of the class. /// @@ -252,6 +256,10 @@ public: ~Font(); public: + /// + /// The active fallback fonts. + /// + API_FIELD() static Array, HeapAllocation> FallbackFonts; /// /// Gets parent font asset that contains font family used by this font. @@ -302,13 +310,13 @@ public: } public: - /// /// Gets character entry. /// /// The character. /// The output character entry. - void GetCharacter(Char c, FontCharacterEntry& result); + /// True if fallback to secondary font when the primary font doesn't contains this character. + void GetCharacter(Char c, FontCharacterEntry& result, bool enableFallback = true); /// /// Gets the kerning amount for a pair of characters. @@ -330,7 +338,6 @@ public: API_FUNCTION() void Invalidate(); public: - /// /// Processes text to get cached lines for rendering. /// @@ -524,7 +531,6 @@ public: void FlushFaceSize() const; public: - // [Object] String ToString() const override; }; diff --git a/Source/Engine/Render2D/FontAsset.cpp b/Source/Engine/Render2D/FontAsset.cpp index a477e5f4d..53fbdc930 100644 --- a/Source/Engine/Render2D/FontAsset.cpp +++ b/Source/Engine/Render2D/FontAsset.cpp @@ -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) diff --git a/Source/Engine/Render2D/FontAsset.h b/Source/Engine/Render2D/FontAsset.h index 4dea84a5b..a93276bf1 100644 --- a/Source/Engine/Render2D/FontAsset.h +++ b/Source/Engine/Render2D/FontAsset.h @@ -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 + /// + /// Check if the font contains the glyph of a char. + /// + /// The char to test. + /// True if the font contains the glyph of the char, otherwise false. + API_FUNCTION() bool ContainsChar(Char c) const; + /// /// Invalidates all cached dynamic font atlases using this font. Can be used to reload font characters after changing font asset options. /// API_FUNCTION() void Invalidate(); +public: + // [BinaryAsset] + uint64 GetMemoryUsage() const override; + protected: // [BinaryAsset] bool init(AssetInitData& initData) override; diff --git a/Source/Engine/Render2D/FontManager.cpp b/Source/Engine/Render2D/FontManager.cpp index bb7edf974..2e1ba8c6b 100644 --- a/Source/Engine/Render2D/FontManager.cpp +++ b/Source/Engine/Render2D/FontManager.cpp @@ -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(slot->Width - 2 * padding); entry.UVSize.Y = static_cast(slot->Height - 2 * padding); entry.Slot = slot; + entry.Font = font; return false; } diff --git a/Source/Engine/Render2D/Render2D.cpp b/Source/Engine/Render2D/Render2D.cpp index b56c3e1a2..34cb2c693 100644 --- a/Source/Engine/Render2D/Render2D.cpp +++ b/Source/Engine/Render2D/Render2D.cpp @@ -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& vertices, const Span& uvs) { RENDER2D_CHECK_RENDERING_STATE; - CHECK(vertices.Length() == uvs.Length()) + CHECK(vertices.Length() == uvs.Length()); Render2DDrawCall& drawCall = DrawCalls.AddOne(); drawCall.Type = DrawCallType::FillTexture; @@ -1977,7 +1983,7 @@ void Render2D::DrawTexturedTriangles(GPUTexture* t, const Span& indices, drawCall.StartIB = IBIndex; drawCall.CountIB = indices.Length(); drawCall.AsTexture.Ptr = t; - + for (int32 i = 0; i < indices.Length();) { const uint16 i0 = indices.Get()[i++]; diff --git a/Source/Engine/Render2D/Render2D.h b/Source/Engine/Render2D/Render2D.h index 2b890ced9..5e5e952dc 100644 --- a/Source/Engine/Render2D/Render2D.h +++ b/Source/Engine/Render2D/Render2D.h @@ -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. /// VertexSnapping = 1, + + /// + /// Enables automatic characters usage from fallback fonts. + /// + FallbackFonts = 2, }; struct CustomData @@ -452,3 +457,5 @@ public: /// The color. API_FUNCTION() static void FillTriangle(const Float2& p0, const Float2& p1, const Float2& p2, const Color& color); }; + +DECLARE_ENUM_OPERATORS(Render2D::RenderingFeatures); diff --git a/Source/Engine/Scripting/Attributes/Editor/RequireActorAttribute.cs b/Source/Engine/Scripting/Attributes/Editor/RequireActorAttribute.cs new file mode 100644 index 000000000..6e08217bf --- /dev/null +++ b/Source/Engine/Scripting/Attributes/Editor/RequireActorAttribute.cs @@ -0,0 +1,25 @@ +using System; + +namespace FlaxEngine; + +/// +/// This attribute is used to check for if a script requires an Actor type. +/// +[Serializable] +[AttributeUsage(AttributeTargets.Class)] +public class RequireActorAttribute : Attribute +{ + /// + /// The required type. + /// + public Type RequiredType; + + /// + /// Initializes a new instance of the class. + /// + /// The required type. + public RequireActorAttribute(Type type) + { + RequiredType = type; + } +} diff --git a/Source/Engine/Scripting/Attributes/Editor/RequireScriptAttribute.cs b/Source/Engine/Scripting/Attributes/Editor/RequireScriptAttribute.cs new file mode 100644 index 000000000..414a13aeb --- /dev/null +++ b/Source/Engine/Scripting/Attributes/Editor/RequireScriptAttribute.cs @@ -0,0 +1,34 @@ +using System; + +namespace FlaxEngine; + +/// +/// This attribute is used to check for if a script requires other script types. +/// +[Serializable] +[AttributeUsage(AttributeTargets.Class)] +public class RequireScriptAttribute : Attribute +{ + /// + /// The required types. + /// + public Type[] RequiredTypes; + + /// + /// Initializes a new instance of the class. + /// + /// The required type. + public RequireScriptAttribute(Type type) + { + RequiredTypes = new[] { type }; + } + + /// + /// Initializes a new instance of the class. + /// + /// The required types. + public RequireScriptAttribute(Type[] types) + { + RequiredTypes = types; + } +} diff --git a/Source/Engine/Terrain/TerrainPatch.cpp b/Source/Engine/Terrain/TerrainPatch.cpp index c5d1ace05..e24376f1f 100644 --- a/Source/Engine/Terrain/TerrainPatch.cpp +++ b/Source/Engine/Terrain/TerrainPatch.cpp @@ -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++) diff --git a/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs b/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs index 044c65044..b4351da75 100644 --- a/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs +++ b/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs @@ -280,7 +280,7 @@ namespace FlaxEngine.GUI foreach (var id in ids) { var path = Content.GetEditorAssetPath(id); - if (!string.IsNullOrEmpty(path) && + if (!string.IsNullOrEmpty(path) && string.Equals(name, System.IO.Path.GetFileNameWithoutExtension(path), System.StringComparison.OrdinalIgnoreCase)) { return Content.LoadAsync(id, type); diff --git a/Source/Engine/UI/GUI/Common/TextBoxBase.cs b/Source/Engine/UI/GUI/Common/TextBoxBase.cs index 55b58634d..35819da79 100644 --- a/Source/Engine/UI/GUI/Common/TextBoxBase.cs +++ b/Source/Engine/UI/GUI/Common/TextBoxBase.cs @@ -280,13 +280,13 @@ namespace FlaxEngine.GUI /// [EditorDisplay("Border Style"), EditorOrder(2010), Tooltip("Whether to have a border."), ExpandGroups] public bool HasBorder { get; set; } = true; - + /// /// Gets or sets the border thickness. /// [EditorDisplay("Border Style"), EditorOrder(2011), Tooltip("The thickness of the border."), Limit(0)] public float BorderThickness { get; set; } = 1.0f; - + /// /// Gets or sets the color of the border (Transparent if not used). /// diff --git a/Source/Engine/UI/TextRender.cpp b/Source/Engine/UI/TextRender.cpp index aa49dac45..d190f1123 100644 --- a/Source/Engine/UI/TextRender.cpp +++ b/Source/Engine/UI/TextRender.cpp @@ -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 { diff --git a/Source/Engine/UI/UICanvas.cs b/Source/Engine/UI/UICanvas.cs index bc8c360d1..dda941745 100644 --- a/Source/Engine/UI/UICanvas.cs +++ b/Source/Engine/UI/UICanvas.cs @@ -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 diff --git a/Source/Tools/Flax.Build/Build/FileCache.cs b/Source/Tools/Flax.Build/Build/FileCache.cs index a11b53415..d21e0848a 100644 --- a/Source/Tools/Flax.Build/Build/FileCache.cs +++ b/Source/Tools/Flax.Build/Build/FileCache.cs @@ -9,32 +9,30 @@ namespace Flax.Build /// public static class FileCache { - private static Dictionary fileInfoCache = new Dictionary(); + private static readonly Dictionary _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; } } diff --git a/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs b/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs index 3efe33b38..f6586c910 100644 --- a/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs +++ b/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs @@ -808,11 +808,11 @@ namespace Flax.Build foreach (var moduleName in moduleOptions.PrivateDependencies.Concat(moduleOptions.PublicDependencies)) { var dependencyModule = buildData.Rules.GetModule(moduleName); - if (dependencyModule != null && - !string.IsNullOrEmpty(dependencyModule.BinaryModuleName) && - dependencyModule.BinaryModuleName != binaryModule.Key && + if (dependencyModule != null && + !string.IsNullOrEmpty(dependencyModule.BinaryModuleName) && + dependencyModule.BinaryModuleName != binaryModule.Key && !moduleNamesUsed.Contains(dependencyModule.BinaryModuleName) && - GetModuleProject(dependencyModule, project) != null && + GetModuleProject(dependencyModule, project) != null && buildData.Modules.TryGetValue(dependencyModule, out var dependencyOptions)) { // Import symbols from referenced binary module diff --git a/Source/Tools/Flax.Build/Build/Platform.cs b/Source/Tools/Flax.Build/Build/Platform.cs index f458225fa..6b0d48dba 100644 --- a/Source/Tools/Flax.Build/Build/Platform.cs +++ b/Source/Tools/Flax.Build/Build/Platform.cs @@ -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(); } diff --git a/Source/Tools/Flax.Build/Deploy/Deployment.Editor.cs b/Source/Tools/Flax.Build/Deploy/Deployment.Editor.cs index e1f2ab4e6..75f43fd68 100644 --- a/Source/Tools/Flax.Build/Deploy/Deployment.Editor.cs +++ b/Source/Tools/Flax.Build/Deploy/Deployment.Editor.cs @@ -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"); diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/Assimp.cs b/Source/Tools/Flax.Build/Deps/Dependencies/Assimp.cs index 528256f69..bc501c3a5 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/Assimp.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/Assimp.cs @@ -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); diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs b/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs index 6e565b94c..bb42fc253 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs @@ -49,7 +49,7 @@ namespace Flax.Deps.Dependencies } } } - + /// public override void Build(BuildOptions options) { @@ -185,16 +185,16 @@ namespace Flax.Deps.Dependencies // Print the NvCloth version Log.Info($"Building {File.ReadAllLines(Path.Combine(root, "README.md"))[0].Trim()} to {platform} {architecture}"); - + // Generate project files SetupDirectory(buildFolder, false); Utilities.FileDelete(Path.Combine(cmakeFolder, "CMakeCache.txt")); cmakeArgs += $" -DPX_STATIC_LIBRARIES=1 -DPX_OUTPUT_DLL_DIR=\"{Path.Combine(buildFolder, "bin")}\" -DPX_OUTPUT_LIB_DIR=\"{Path.Combine(buildFolder, "lib")}\" -DPX_OUTPUT_EXE_DIR=\"{Path.Combine(buildFolder, "bin")}\""; RunCmake(cmakeFolder, platform, architecture, " -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF " + cmakeArgs, envVars); - + // Run build Utilities.Run("cmake", "--build . --config Release", null, cmakeFolder, Utilities.RunOptions.ThrowExceptionOnError, envVars); - + // Deploy binaries var libs = new[] { diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs b/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs index 1adb73bb3..f9f5d7ed2 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs @@ -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); diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/curl.cs b/Source/Tools/Flax.Build/Deps/Dependencies/curl.cs index 382c5707c..651c849d8 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/curl.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/curl.cs @@ -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"; @@ -146,7 +146,7 @@ namespace Flax.Deps.Dependencies var compilerFlags = string.Format("-mmacosx-version-min={0} -arch {1}", Configuration.MacOSXMinVer, arch); var envVars = new Dictionary { - { "CC", "clang" }, + { "CC", "clang" }, { "CXX", "clang" }, { "CFLAGS", compilerFlags }, { "CXXFLAGS", compilerFlags }, diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/freetype.cs b/Source/Tools/Flax.Build/Deps/Dependencies/freetype.cs index 165317180..6be0d3397 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/freetype.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/freetype.cs @@ -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"); diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/glslang.cs b/Source/Tools/Flax.Build/Deps/Dependencies/glslang.cs index f88ded6a1..5d11c4728 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/glslang.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/glslang.cs @@ -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); diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/ogg.cs b/Source/Tools/Flax.Build/Deps/Dependencies/ogg.cs index fe6800001..4fefceb09 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/ogg.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/ogg.cs @@ -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"); diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/vorbis.cs b/Source/Tools/Flax.Build/Deps/Dependencies/vorbis.cs index 75b2810be..847ff8872 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/vorbis.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/vorbis.cs @@ -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\""); diff --git a/Source/Tools/Flax.Build/Deps/Downloader.cs b/Source/Tools/Flax.Build/Deps/Downloader.cs index dcba01780..19135d634 100644 --- a/Source/Tools/Flax.Build/Deps/Downloader.cs +++ b/Source/Tools/Flax.Build/Deps/Downloader.cs @@ -105,8 +105,7 @@ namespace Flax.Deps if (totalBytes.HasValue) progress.Update(totalBytesRead, totalBytes.Value); } - } - while (hasMoreToRead); + } while (hasMoreToRead); } } } diff --git a/Source/Tools/Flax.Build/Deps/ProgressDisplay.cs b/Source/Tools/Flax.Build/Deps/ProgressDisplay.cs index 5ad6e10d3..cce10f2eb 100644 --- a/Source/Tools/Flax.Build/Deps/ProgressDisplay.cs +++ b/Source/Tools/Flax.Build/Deps/ProgressDisplay.cs @@ -96,7 +96,7 @@ namespace Flax.Deps Console.WriteLine(); return false; } - + return true; */ } diff --git a/Source/Tools/Flax.Build/Platforms/Android/AndroidSdk.cs b/Source/Tools/Flax.Build/Platforms/Android/AndroidSdk.cs index a023d33b2..0fd5b6a41 100644 --- a/Source/Tools/Flax.Build/Platforms/Android/AndroidSdk.cs +++ b/Source/Tools/Flax.Build/Platforms/Android/AndroidSdk.cs @@ -18,7 +18,7 @@ namespace Flax.Build.Platforms public static readonly AndroidSdk Instance = new AndroidSdk(); /// - public override TargetPlatform[] Platforms => new [] + public override TargetPlatform[] Platforms => new[] { TargetPlatform.Windows, TargetPlatform.Linux, diff --git a/Source/Tools/Flax.Build/Platforms/Mac/MacPlatform.cs b/Source/Tools/Flax.Build/Platforms/Mac/MacPlatform.cs index 4a8115fcd..4173e160b 100644 --- a/Source/Tools/Flax.Build/Platforms/Mac/MacPlatform.cs +++ b/Source/Tools/Flax.Build/Platforms/Mac/MacPlatform.cs @@ -77,15 +77,15 @@ namespace Flax.Build.Platforms /// Returns true if running an x64 binary an arm64 host machine. /// 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); } } diff --git a/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioProjectGenerator.cs index 3438f8960..7bd5495b2 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudio/VisualStudioProjectGenerator.cs @@ -702,7 +702,7 @@ namespace Flax.Build.Projects.VisualStudio { // Build command for the build tool var buildToolPath = Path.ChangeExtension(typeof(Builder).Assembly.Location, null); - + var targetsFileContent = new StringBuilder(); targetsFileContent.AppendLine(""); targetsFileContent.AppendLine(" "); diff --git a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs index 15b236972..7f3b11e15 100644 --- a/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs +++ b/Source/Tools/Flax.Build/Projects/VisualStudioCode/VisualStudioCodeProjectGenerator.cs @@ -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(); @@ -622,7 +621,7 @@ namespace Flax.Build.Projects.VisualStudioCode json.AddField("**/Output", true); json.AddField("**/*.flax", true); json.EndObject(); - + // Extension settings json.AddField("omnisharp.useModernNet", true); diff --git a/Source/Tools/Flax.Build/Utilities/CppNameMangling.cs b/Source/Tools/Flax.Build/Utilities/CppNameMangling.cs index 1d0166a72..ba00db071 100644 --- a/Source/Tools/Flax.Build/Utilities/CppNameMangling.cs +++ b/Source/Tools/Flax.Build/Utilities/CppNameMangling.cs @@ -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); diff --git a/Source/Tools/Flax.Build/Utilities/WinAPI.cs b/Source/Tools/Flax.Build/Utilities/WinAPI.cs index ae0c5a5fb..47939fc1f 100644 --- a/Source/Tools/Flax.Build/Utilities/WinAPI.cs +++ b/Source/Tools/Flax.Build/Utilities/WinAPI.cs @@ -130,7 +130,7 @@ namespace Flax.Build System = 0x00001000, Task = 0x00002000 } - + public enum Icon : uint { Warning = 0x00000030,