From 7cae9b4ce5aa2116826bfded9a8f139aeb58d9e6 Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Sat, 24 Sep 2022 13:46:55 +0200 Subject: [PATCH 01/25] Fixed - Windows, launcher use a uppercase D:\ , if you try to start your project from VS/Shortcut and use a lowercase d:\ it would ruin your project as it assign new asset IDs without remapping. --- Source/Engine/Content/Cache/AssetsCache.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Source/Engine/Content/Cache/AssetsCache.cpp b/Source/Engine/Content/Cache/AssetsCache.cpp index 459a9f31f..44461a68b 100644 --- a/Source/Engine/Content/Cache/AssetsCache.cpp +++ b/Source/Engine/Content/Cache/AssetsCache.cpp @@ -379,8 +379,27 @@ void AssetsCache::RegisterAssets(FlaxStorage* storage) // Check if storage contains ID which has been already registered if (FindAsset(e.ID, info)) { + #if PLATFORM_WINDOWS + //PE: Windows - if you start your project using a shortcut/VS commandline -project , and using a upper/lower drive letter, it could ruin your scene. + //PE: On windows case do not matter so... + if (storagePath.ToLower() != info.Path.ToLower()) + { + LOG(Warning, "Founded duplicated asset \'{0}\'. Locations: \'{1}\' and \'{2}\'", e.ID, storagePath, info.Path); + duplicatedEntries.Add(i); + } + else + { + //PE: Remove from _registry so we can add it again later with the original ID, so we dont loose relations. + for (auto i = _registry.Begin(); i.IsNotEnd(); ++i) + { + if (i->Value.Info.Path.ToLower() == storagePath.ToLower()) + _registry.Remove(i); + } + } + #else LOG(Warning, "Founded duplicated asset \'{0}\'. Locations: \'{1}\' and \'{2}\'", e.ID, storagePath, info.Path); duplicatedEntries.Add(i); + #endif } } From e98d2c8a270e0dbbfa5172885f9b7969d7cc48cb Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Sun, 25 Sep 2022 09:33:23 +0200 Subject: [PATCH 02/25] Added - aiProcess_SortByPType to importer, i seen many object that have a small mesh with point faces that are not part of the object, so just ignoring these make the objects import. --- Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp index 26d79cfc4..cc0c68d79 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp @@ -641,6 +641,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ImportedModelData& data, Opti aiProcess_JoinIdenticalVertices | aiProcess_LimitBoneWeights | aiProcess_Triangulate | + aiProcess_SortByPType | //PE: Added aiProcess_SortByPType so we can ignore meshes with non triangle faces. aiProcess_GenUVCoords | aiProcess_FindDegenerates | aiProcess_FindInvalidData | From ea9695ac160240783da57698bf2c5c575d5a8e4a Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Sun, 25 Sep 2022 10:31:25 +0200 Subject: [PATCH 03/25] Added - Support for LOD meshes using _ , like LOD_0... --- Source/Engine/Tools/ModelTool/ModelTool.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp index b5a4282c2..571c9a7bd 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp @@ -1552,10 +1552,14 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op int32 ModelTool::DetectLodIndex(const String& nodeName) { - const int32 index = nodeName.FindLast(TEXT("LOD")); + int32 index = nodeName.FindLast(TEXT("LOD")); if (index != -1) { int32 num; + //PE: Many models use LOD_0... to indentify LOD levels. + if (nodeName.Length() > 4 && nodeName[3] == '_') + index++; + if (!StringUtils::Parse(nodeName.Get() + index + 3, &num)) { if (num >= 0 && num < MODEL_MAX_LODS) From f237d424fadb7fe52471972af2fa740243c56fde Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Mon, 26 Sep 2022 09:19:15 +0200 Subject: [PATCH 04/25] Fixed - Gizmo draw order ( https://github.com/FlaxEngine/FlaxEngine/issues/680 ) --- Source/Editor/Gizmo/TransformGizmoBase.Draw.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs index 5fb5c12f2..6957a9525 100644 --- a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs +++ b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs @@ -54,7 +54,12 @@ namespace FlaxEditor.Gizmo if (!_isActive || !IsActive) return; - Matrix m1, m2, m3; + //PE: As all axisMesh have the same pivot, add a little offset to the x axisMesh, + //PE: This way SortDrawCalls is able to sort the draw order. + //PE: https://github.com/FlaxEngine/FlaxEngine/issues/680 + //PE: @Artist To fix the rotate, add new "wider" circleMesh, so direction is visible. + + Matrix m1, m2, m3 , mx1; bool isXAxis = _activeAxis == Axis.X || _activeAxis == Axis.XY || _activeAxis == Axis.ZX; bool isYAxis = _activeAxis == Axis.Y || _activeAxis == Axis.XY || _activeAxis == Axis.YZ; bool isZAxis = _activeAxis == Axis.Z || _activeAxis == Axis.YZ || _activeAxis == Axis.ZX; @@ -70,6 +75,8 @@ namespace FlaxEditor.Gizmo break; Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3); Matrix.Multiply(ref m3, ref world, out m1); + mx1 = m1; + mx1.M41 += 0.05f; var axisMesh = _modelTranslateAxis.LODs[0].Meshes[0]; var boxMesh = _modelBox.LODs[0].Meshes[0]; var boxSize = 10.0f; @@ -90,7 +97,7 @@ namespace FlaxEditor.Gizmo boxMesh.Draw(ref renderContext, _activeAxis == Axis.YZ ? _materialWireFocus : _materialWire, ref m3); // X axis - axisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m1); + axisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref mx1); // Y axis Matrix.RotationZ(Mathf.PiOverTwo, out m2); @@ -143,12 +150,15 @@ namespace FlaxEditor.Gizmo break; Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3); Matrix.Multiply(ref m3, ref world, out m1); + mx1 = m1; + mx1.M41 -= 0.05f; + var axisMesh = _modelScaleAxis.LODs[0].Meshes[0]; var boxMesh = _modelBox.LODs[0].Meshes[0]; // X axis Matrix.RotationY(-Mathf.PiOverTwo, out m2); - Matrix.Multiply(ref m2, ref m1, out m3); + Matrix.Multiply(ref m2, ref mx1, out m3); axisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3); // Y axis From 2efc97b64f7602aaa8b0372cb6423f0861152467 Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Tue, 11 Oct 2022 10:45:28 +0200 Subject: [PATCH 05/25] Added: ScriptingObject* TryFindObject(MClass* mclass), Allow you from c++ to use MAssembly GetBinaryModuleGame, and get a monoobject from a class, monoobject is needed later to Invoke a method from the class. --- Source/Engine/Scripting/Scripting.cpp | 17 +++++++++++++++++ Source/Engine/Scripting/Scripting.h | 8 ++++++++ 2 files changed, 25 insertions(+) diff --git a/Source/Engine/Scripting/Scripting.cpp b/Source/Engine/Scripting/Scripting.cpp index cc128c548..5af41502a 100644 --- a/Source/Engine/Scripting/Scripting.cpp +++ b/Source/Engine/Scripting/Scripting.cpp @@ -868,6 +868,23 @@ ScriptingObject* Scripting::TryFindObject(Guid id, MClass* type) return result; } +ScriptingObject* Scripting::TryFindObject(MClass* mclass) +{ + if (mclass == nullptr) + return nullptr; + + ScopeLock lock(_objectsLocker); + + for (auto i = _objectsDictionary.Begin(); i.IsNotEnd(); ++i) + { + const auto obj = i->Value; + if(obj->GetClass() == mclass) + return obj; + } + return nullptr; + +} + ScriptingObject* Scripting::FindObject(const MObject* managedInstance) { if (managedInstance == nullptr) diff --git a/Source/Engine/Scripting/Scripting.h b/Source/Engine/Scripting/Scripting.h index 81739e1c8..41e5d7119 100644 --- a/Source/Engine/Scripting/Scripting.h +++ b/Source/Engine/Scripting/Scripting.h @@ -144,6 +144,14 @@ public: /// The found object or null if missing. static ScriptingObject* FindObject(Guid id, MClass* type = nullptr); + + /// + /// Tries to find the object by the given class. + /// + /// The found object or null if missing. + static ScriptingObject* TryFindObject(MClass* type = nullptr); + + /// /// Tries to find the object by the given identifier. /// From b3bb8601953dc715ab4e85f9a10909440682ea70 Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Sun, 23 Oct 2022 09:45:27 +0200 Subject: [PATCH 06/25] PE: Added - Use "R" key to rotate selections by 45 degrees. --- Source/Editor/Options/InputOptions.cs | 4 ++ .../Viewport/MainEditorGizmoViewport.cs | 44 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/Source/Editor/Options/InputOptions.cs b/Source/Editor/Options/InputOptions.cs index 0a1a78cab..f02d91da4 100644 --- a/Source/Editor/Options/InputOptions.cs +++ b/Source/Editor/Options/InputOptions.cs @@ -68,6 +68,10 @@ namespace FlaxEditor.Options [EditorDisplay("Common"), EditorOrder(220)] public InputBinding ContentFinder = new InputBinding(KeyboardKeys.O, KeyboardKeys.Control); + [DefaultValue(typeof(InputBinding), "R")] + [EditorDisplay("Common"), EditorOrder(230)] + public InputBinding RotateSelection = new InputBinding(KeyboardKeys.R); + #endregion #region Scene diff --git a/Source/Editor/Viewport/MainEditorGizmoViewport.cs b/Source/Editor/Viewport/MainEditorGizmoViewport.cs index eb82a42bf..bf72bc1c0 100644 --- a/Source/Editor/Viewport/MainEditorGizmoViewport.cs +++ b/Source/Editor/Viewport/MainEditorGizmoViewport.cs @@ -362,6 +362,7 @@ namespace FlaxEditor.Viewport InputActions.Add(options => options.RotateMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Rotate); InputActions.Add(options => options.ScaleMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Scale); InputActions.Add(options => options.FocusSelection, FocusSelection); + InputActions.Add(options => options.RotateSelection, RotateSelection); InputActions.Add(options => options.Delete, _editor.SceneEditing.Delete); } @@ -666,6 +667,49 @@ namespace FlaxEditor.Viewport Gizmos.ForEach(x => x.OnSelectionChanged(selection)); } + /// + /// Press "R" to rotate the selected gizmo objects 45 degrees. + /// + public void RotateSelection() + { + var win = (WindowRootControl)Root; + var selection = _editor.SceneEditing.Selection; + var IsShiftDown = win.GetKey(KeyboardKeys.Shift); + + Quaternion rotationDelta; + if(IsShiftDown) + rotationDelta = Quaternion.Euler(0.0f, -45.0f, 0.0f); + else + rotationDelta = Quaternion.Euler(0.0f, 45.0f, 0.0f); + + bool useObjCenter = TransformGizmo.ActivePivot == TransformGizmoBase.PivotType.ObjectCenter; + Vector3 gizmoPosition = TransformGizmo.Position; + + //PE: Rotate selected objects. + bool isPlayMode = Editor.Instance.StateMachine.IsPlayMode; + for (int i = 0; i < selection.Count; i++) + { + var obj = selection[i]; + if (isPlayMode && obj.CanTransform == false) + continue; + var trans = obj.Transform; + Vector3 pivotOffset = trans.Translation - gizmoPosition; + if (useObjCenter || pivotOffset.IsZero) + { + trans.Orientation *= Quaternion.Invert(trans.Orientation) * rotationDelta * trans.Orientation; + } + else + { + Matrix.RotationQuaternion(ref trans.Orientation, out var transWorld); + Matrix.RotationQuaternion(ref rotationDelta, out var deltaWorld); + Matrix world = transWorld * Matrix.Translation(pivotOffset) * deltaWorld * Matrix.Translation(-pivotOffset); + trans.SetRotation(ref world); + trans.Translation += world.TranslationVector; + } + obj.Transform = trans; + } + } + /// /// Focuses the viewport on the current selection of the gizmo. /// From edf339a942162a33c0ed047bec861eaee21738ee Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Sun, 23 Oct 2022 09:48:18 +0200 Subject: [PATCH 07/25] PE: Added - Bounding Box Snapping, it dont matter what size objects are they will always snap perfectly. --- Source/Editor/Gizmo/TransformGizmoBase.cs | 27 ++++++++++++++++--- .../Viewport/MainEditorGizmoViewport.cs | 9 ++++++- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/Source/Editor/Gizmo/TransformGizmoBase.cs b/Source/Editor/Gizmo/TransformGizmoBase.cs index 02b9c1e8f..42f7b9b48 100644 --- a/Source/Editor/Gizmo/TransformGizmoBase.cs +++ b/Source/Editor/Gizmo/TransformGizmoBase.cs @@ -289,10 +289,29 @@ namespace FlaxEditor.Gizmo { float snapValue = isScaling ? ScaleSnapValue : TranslationSnapValue; _translationScaleSnapDelta += delta; - delta = new Vector3( - (int)(_translationScaleSnapDelta.X / snapValue) * snapValue, - (int)(_translationScaleSnapDelta.Y / snapValue) * snapValue, - (int)(_translationScaleSnapDelta.Z / snapValue) * snapValue); + if (!isScaling && snapValue < 0) + { + //PE: Snap to object bounding box + GetSelectedObjectsBounds(out var b, out _); + float X, Y, Z; + if (b.Minimum.X < 0) X = Math.Abs(b.Minimum.X) + b.Maximum.X; + else X = b.Minimum.X - b.Maximum.X; + if (b.Minimum.Y < 0) Y = Math.Abs(b.Minimum.Y) + b.Maximum.Y; + else Y = b.Minimum.Y - b.Maximum.Y; + if (b.Minimum.Z < 0) Z = Math.Abs(b.Minimum.Z) + b.Maximum.Z; + else Z = b.Minimum.Z - b.Maximum.Z; + delta = new Vector3( + (int)(_translationScaleSnapDelta.X / X) * X, + (int)(_translationScaleSnapDelta.Y / Y) * Y, + (int)(_translationScaleSnapDelta.Z / Z) * Z); + } + else + { + delta = new Vector3( + (int)(_translationScaleSnapDelta.X / snapValue) * snapValue, + (int)(_translationScaleSnapDelta.Y / snapValue) * snapValue, + (int)(_translationScaleSnapDelta.Z / snapValue) * snapValue); + } _translationScaleSnapDelta -= delta; } diff --git a/Source/Editor/Viewport/MainEditorGizmoViewport.cs b/Source/Editor/Viewport/MainEditorGizmoViewport.cs index bf72bc1c0..7fc03531e 100644 --- a/Source/Editor/Viewport/MainEditorGizmoViewport.cs +++ b/Source/Editor/Viewport/MainEditorGizmoViewport.cs @@ -310,6 +310,10 @@ namespace FlaxEditor.Viewport var button = translateSnappingCM.AddButton(v.ToString()); button.Tag = v; } + var buttonBB = translateSnappingCM.AddButton("Bounding Box"); + buttonBB.Tag = -1.0f; + + translateSnappingCM.ButtonClicked += OnWidgetTranslateSnapClick; translateSnappingCM.VisibleChanged += OnWidgetTranslateSnapShowHide; _translateSnapping.Parent = translateSnappingWidget; @@ -640,7 +644,10 @@ namespace FlaxEditor.Viewport { var v = (float)button.Tag; TransformGizmo.TranslationSnapValue = v; - _translateSnapping.Text = v.ToString(); + if (v < 0.0f) + _translateSnapping.Text = "Bounding Box"; + else + _translateSnapping.Text = v.ToString(); } private void OnWidgetTranslateSnapShowHide(Control control) From 2a7e59ae5dbacb651d7a5773bce98fd00485cbb0 Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Sun, 23 Oct 2022 12:20:01 +0200 Subject: [PATCH 08/25] PE: Fix issue with using "shift" to duplicate object, this only worked every second time if using a large grid. --- Source/Editor/Gizmo/TransformGizmoBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/Gizmo/TransformGizmoBase.cs b/Source/Editor/Gizmo/TransformGizmoBase.cs index 42f7b9b48..86135b338 100644 --- a/Source/Editor/Gizmo/TransformGizmoBase.cs +++ b/Source/Editor/Gizmo/TransformGizmoBase.cs @@ -465,7 +465,7 @@ namespace FlaxEditor.Gizmo } // Apply transformation (but to the parents, not whole selection pool) - if (anyValid) + if (anyValid || (!_isTransforming && Owner.UseDuplicate) ) { StartTransforming(); From 56c9ed3197aafe36e5ceced3e6ad09d10c57db0a Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Mon, 24 Oct 2022 09:10:15 +0200 Subject: [PATCH 09/25] PE: Fix - Linux error "implicitly convert type 'double' to 'float'." --- Source/Editor/Gizmo/TransformGizmoBase.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/Editor/Gizmo/TransformGizmoBase.cs b/Source/Editor/Gizmo/TransformGizmoBase.cs index 86135b338..13ebece7c 100644 --- a/Source/Editor/Gizmo/TransformGizmoBase.cs +++ b/Source/Editor/Gizmo/TransformGizmoBase.cs @@ -289,17 +289,17 @@ namespace FlaxEditor.Gizmo { float snapValue = isScaling ? ScaleSnapValue : TranslationSnapValue; _translationScaleSnapDelta += delta; - if (!isScaling && snapValue < 0) + if (!isScaling && snapValue < 0.0f) { //PE: Snap to object bounding box GetSelectedObjectsBounds(out var b, out _); float X, Y, Z; - if (b.Minimum.X < 0) X = Math.Abs(b.Minimum.X) + b.Maximum.X; - else X = b.Minimum.X - b.Maximum.X; - if (b.Minimum.Y < 0) Y = Math.Abs(b.Minimum.Y) + b.Maximum.Y; - else Y = b.Minimum.Y - b.Maximum.Y; - if (b.Minimum.Z < 0) Z = Math.Abs(b.Minimum.Z) + b.Maximum.Z; - else Z = b.Minimum.Z - b.Maximum.Z; + if (b.Minimum.X < 0.0f) X = (float) Math.Abs(b.Minimum.X) + b.Maximum.X; + else X = (float) b.Minimum.X - b.Maximum.X; + if (b.Minimum.Y < 0.0f) Y = (float) Math.Abs(b.Minimum.Y) + b.Maximum.Y; + else Y = (float) b.Minimum.Y - b.Maximum.Y; + if (b.Minimum.Z < 0.0f) Z = (float) Math.Abs(b.Minimum.Z) + b.Maximum.Z; + else Z = (float) b.Minimum.Z - b.Maximum.Z; delta = new Vector3( (int)(_translationScaleSnapDelta.X / X) * X, (int)(_translationScaleSnapDelta.Y / Y) * Y, From 87a0c671f6684e331d29d92700603420190d10db Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Mon, 24 Oct 2022 09:01:40 -0500 Subject: [PATCH 10/25] Adjusted only the bounds for content items to be floored. --- Source/Editor/Content/GUI/ContentView.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Editor/Content/GUI/ContentView.cs b/Source/Editor/Content/GUI/ContentView.cs index a7dc7b18f..9085042dc 100644 --- a/Source/Editor/Content/GUI/ContentView.cs +++ b/Source/Editor/Content/GUI/ContentView.cs @@ -720,14 +720,14 @@ namespace FlaxEditor.Content.GUI if (itemsToFit < 1) itemsToFit = 1; float itemsWidth = width / Mathf.Max(itemsToFit, 1); - itemsWidth = Mathf.Floor(itemsWidth); + var flooredItemsWidth = Mathf.Floor(itemsWidth); float itemsHeight = itemsWidth / defaultItemsWidth * (ContentItem.DefaultHeight * viewScale); - itemsHeight = Mathf.Floor(itemsHeight); + var flooredItemsHeight = Mathf.Floor(itemsHeight); x = itemsToFit == 1 ? 0 : itemsWidth / itemsToFit; for (int i = 0; i < _children.Count; i++) { var c = _children[i]; - c.Bounds = new Rectangle(x, y, itemsWidth, itemsHeight); + c.Bounds = new Rectangle(x, y, flooredItemsWidth, flooredItemsHeight); x += itemsWidth + itemsWidth / itemsToFit; if (x + itemsWidth > width) From f078499dfbac5f2cbe0dd2c6cb6572beb0e76f89 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 24 Oct 2022 16:44:11 +0200 Subject: [PATCH 11/25] Another adjustment to have position aligned too #796 --- Source/Editor/Content/GUI/ContentView.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Editor/Content/GUI/ContentView.cs b/Source/Editor/Content/GUI/ContentView.cs index 9085042dc..06df7d2a2 100644 --- a/Source/Editor/Content/GUI/ContentView.cs +++ b/Source/Editor/Content/GUI/ContentView.cs @@ -720,14 +720,14 @@ namespace FlaxEditor.Content.GUI if (itemsToFit < 1) itemsToFit = 1; float itemsWidth = width / Mathf.Max(itemsToFit, 1); - var flooredItemsWidth = Mathf.Floor(itemsWidth); float itemsHeight = itemsWidth / defaultItemsWidth * (ContentItem.DefaultHeight * viewScale); + var flooredItemsWidth = Mathf.Floor(itemsWidth); var flooredItemsHeight = Mathf.Floor(itemsHeight); x = itemsToFit == 1 ? 0 : itemsWidth / itemsToFit; for (int i = 0; i < _children.Count; i++) { var c = _children[i]; - c.Bounds = new Rectangle(x, y, flooredItemsWidth, flooredItemsHeight); + c.Bounds = new Rectangle(Mathf.Floor(x), Mathf.Floor(y), flooredItemsWidth, flooredItemsHeight); x += itemsWidth + itemsWidth / itemsToFit; if (x + itemsWidth > width) From 616379c54b5f0306645d29bd1450b47329b2f330 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Mon, 24 Oct 2022 14:00:56 -0500 Subject: [PATCH 12/25] Added an event to subscribe to in TextBoxBase that gets fired when a key is down. --- Source/Engine/UI/GUI/Common/TextBoxBase.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/Engine/UI/GUI/Common/TextBoxBase.cs b/Source/Engine/UI/GUI/Common/TextBoxBase.cs index 41d8b9b44..0930fa138 100644 --- a/Source/Engine/UI/GUI/Common/TextBoxBase.cs +++ b/Source/Engine/UI/GUI/Common/TextBoxBase.cs @@ -129,6 +129,11 @@ namespace FlaxEngine.GUI /// public event Action TextBoxEditEnd; + /// + /// Event fired when a key is down. + /// + public event Action KeyDown; + /// /// Gets or sets a value indicating whether this is a multiline text box control. /// @@ -1174,6 +1179,7 @@ namespace FlaxEngine.GUI var window = Root; bool shiftDown = window.GetKey(KeyboardKeys.Shift); bool ctrDown = window.GetKey(KeyboardKeys.Control); + KeyDown?.Invoke(key); switch (key) { From a79b64261398216f40f2dc6126a0b8c11cf2a01a Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Mon, 24 Oct 2022 14:11:34 -0500 Subject: [PATCH 13/25] Added KeyUp event in TextBoxBase --- Source/Engine/UI/GUI/Common/TextBoxBase.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Source/Engine/UI/GUI/Common/TextBoxBase.cs b/Source/Engine/UI/GUI/Common/TextBoxBase.cs index 0930fa138..92ea513a6 100644 --- a/Source/Engine/UI/GUI/Common/TextBoxBase.cs +++ b/Source/Engine/UI/GUI/Common/TextBoxBase.cs @@ -134,6 +134,11 @@ namespace FlaxEngine.GUI /// public event Action KeyDown; + /// + /// Event fired when a key is up. + /// + public event Action KeyUp; + /// /// Gets or sets a value indicating whether this is a multiline text box control. /// @@ -1173,6 +1178,13 @@ namespace FlaxEngine.GUI return true; } + /// + public override void OnKeyUp(KeyboardKeys key) + { + base.OnKeyUp(key); + KeyUp?.Invoke(key); + } + /// public override bool OnKeyDown(KeyboardKeys key) { From 748c58d52ed66fbb7c572b0ba9dbd68f189a7895 Mon Sep 17 00:00:00 2001 From: PrecisionRender Date: Mon, 24 Oct 2022 19:36:16 -0500 Subject: [PATCH 14/25] Initial commit --- Source/Editor/Surface/Archetypes/Textures.cs | 2 +- .../Tools/MaterialGenerator/MaterialGenerator.Textures.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Editor/Surface/Archetypes/Textures.cs b/Source/Editor/Surface/Archetypes/Textures.cs index 2b566b0bd..6e4e34f43 100644 --- a/Source/Editor/Surface/Archetypes/Textures.cs +++ b/Source/Editor/Surface/Archetypes/Textures.cs @@ -400,7 +400,7 @@ namespace FlaxEditor.Surface.Archetypes Elements = new[] { NodeElementArchetype.Factory.Input(0, "Texture", true, typeof(FlaxEngine.Object), 0), - NodeElementArchetype.Factory.Input(1, "Scale", true, typeof(float), 1, 0), + NodeElementArchetype.Factory.Input(1, "Scale", true, typeof(Float3), 1, 0), NodeElementArchetype.Factory.Input(2, "Blend", true, typeof(float), 2, 1), NodeElementArchetype.Factory.Output(0, "Color", typeof(Float3), 3) } diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp index a29b3d0d9..0c71dc1ba 100644 --- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp +++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Textures.cpp @@ -467,7 +467,7 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value) } const auto texture = eatBox(textureBox->GetParent(), textureBox->FirstConnection()); - const auto scale = tryGetValue(scaleBox, node->Values[0]).AsFloat(); + const auto scale = tryGetValue(scaleBox, node->Values[0]).AsFloat3(); const auto blend = tryGetValue(blendBox, node->Values[1]).AsFloat(); auto result = writeLocal(Value::InitForZero(ValueType::Float4), node); From 2297ba3c866a551625212fd9a5c0eb0d78d76579 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Tue, 25 Oct 2022 16:38:23 -0500 Subject: [PATCH 15/25] moved where hiding the tooltip is called when starting to drag for better response --- Source/Engine/UI/GUI/Control.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Source/Engine/UI/GUI/Control.cs b/Source/Engine/UI/GUI/Control.cs index 86c242609..890908c0e 100644 --- a/Source/Engine/UI/GUI/Control.cs +++ b/Source/Engine/UI/GUI/Control.cs @@ -948,10 +948,6 @@ namespace FlaxEngine.GUI { // Set flag _isDragOver = true; - - // Hide tooltip - Tooltip?.Hide(); - return DragDropEffect.None; } @@ -998,6 +994,8 @@ namespace FlaxEngine.GUI [NoAnimate] public virtual void DoDragDrop(DragData data) { + // Hide tooltip + Tooltip?.Hide(); Root.DoDragDrop(data); } From fd831f569c542a7100702f162e704e1bd3e59f5a Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Wed, 26 Oct 2022 09:54:10 +0200 Subject: [PATCH 16/25] PE: Fix - Streaming audio could not loop. ( https://github.com/FlaxEngine/FlaxEngine/issues/786 ) --- Source/Engine/Audio/AudioSource.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/Engine/Audio/AudioSource.cpp b/Source/Engine/Audio/AudioSource.cpp index 870a1f41a..c01e20692 100644 --- a/Source/Engine/Audio/AudioSource.cpp +++ b/Source/Engine/Audio/AudioSource.cpp @@ -130,6 +130,10 @@ void AudioSource::Play() { // Request faster streaming update Clip->RequestStreamingUpdate(); + + // PE: If we are looping and streaming also update streaming buffers. + if(_loop) + RequestStreamingBuffersUpdate(); } } else From 6a5efdeb29db0b9fb3f30420425480ac6d89b338 Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Wed, 26 Oct 2022 10:00:16 +0200 Subject: [PATCH 17/25] PE: Fix - Ansi is max 7 bit, assimp/openfbx only support ansi paths. ( https://github.com/FlaxEngine/FlaxEngine/issues/806 ) --- Source/Engine/Core/Types/String.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Core/Types/String.cpp b/Source/Engine/Core/Types/String.cpp index 43fbcf051..7a8f1b1ed 100644 --- a/Source/Engine/Core/Types/String.cpp +++ b/Source/Engine/Core/Types/String.cpp @@ -215,7 +215,8 @@ bool String::IsANSI() const bool result = true; for (int32 i = 0; i < _length; i++) { - if (_data[i] > 255) + //PE: Ansi is max 7 bit so... + if (_data[i] > 127) { result = false; break; From 5cfe3b88c744a5adc54162158b9b8066006bf68b Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 29 Oct 2022 11:38:20 +0200 Subject: [PATCH 18/25] Add unit test for `ModelTool::DetectLodIndex` and improve LOD index detection further #765 --- Source/Engine/Tests/TestModelTool.cpp | 24 +++++++++++++++++++++ Source/Engine/Tests/Tests.Build.cs | 9 ++++++++ Source/Engine/Tools/ModelTool/ModelTool.cpp | 12 ++++------- 3 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 Source/Engine/Tests/TestModelTool.cpp diff --git a/Source/Engine/Tests/TestModelTool.cpp b/Source/Engine/Tests/TestModelTool.cpp new file mode 100644 index 000000000..13aa2bf15 --- /dev/null +++ b/Source/Engine/Tests/TestModelTool.cpp @@ -0,0 +1,24 @@ +// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. + +#include "Engine/Tools/ModelTool/ModelTool.h" +#include + +TEST_CASE("ModelTool") +{ + SECTION("Test DetectLodIndex") + { + CHECK(ModelTool::DetectLodIndex(TEXT("mesh")) == 0); + CHECK(ModelTool::DetectLodIndex(TEXT("mesh LOD")) == 0); + CHECK(ModelTool::DetectLodIndex(TEXT("mesh LOD0")) == 0); + CHECK(ModelTool::DetectLodIndex(TEXT("mesh LOD1")) == 1); + CHECK(ModelTool::DetectLodIndex(TEXT("mesh_LOD1")) == 1); + CHECK(ModelTool::DetectLodIndex(TEXT("mesh_lod1")) == 1); + CHECK(ModelTool::DetectLodIndex(TEXT("mesh_lod2")) == 2); + CHECK(ModelTool::DetectLodIndex(TEXT("lod0")) == 0); + CHECK(ModelTool::DetectLodIndex(TEXT("lod1")) == 1); + CHECK(ModelTool::DetectLodIndex(TEXT("lod_2")) == 2); + CHECK(ModelTool::DetectLodIndex(TEXT("mesh_lod_0")) == 0); + CHECK(ModelTool::DetectLodIndex(TEXT("mesh_lod_1")) == 1); + CHECK(ModelTool::DetectLodIndex(TEXT("mesh lod_2")) == 2); + } +} diff --git a/Source/Engine/Tests/Tests.Build.cs b/Source/Engine/Tests/Tests.Build.cs index 3d91dc7fd..ad64962a0 100644 --- a/Source/Engine/Tests/Tests.Build.cs +++ b/Source/Engine/Tests/Tests.Build.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using Flax.Build; +using Flax.Build.NativeCpp; /// /// Engine tests module. @@ -14,6 +15,14 @@ public class Tests : EngineModule Deploy = false; } + /// + public override void Setup(BuildOptions options) + { + base.Setup(options); + + options.PrivateDependencies.Add("ModelTool"); + } + /// public override void GetFilesToDeploy(List files) { diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp index 571c9a7bd..53fd90de4 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp @@ -1552,25 +1552,21 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op int32 ModelTool::DetectLodIndex(const String& nodeName) { - int32 index = nodeName.FindLast(TEXT("LOD")); + int32 index = nodeName.FindLast(TEXT("LOD"), StringSearchCase::IgnoreCase); if (index != -1) { - int32 num; - //PE: Many models use LOD_0... to indentify LOD levels. - if (nodeName.Length() > 4 && nodeName[3] == '_') + // Some models use LOD_0 to identify LOD levels + if (nodeName.Length() > index + 4 && nodeName[index + 3] == '_') index++; + int32 num; if (!StringUtils::Parse(nodeName.Get() + index + 3, &num)) { if (num >= 0 && num < MODEL_MAX_LODS) - { return num; - } - LOG(Warning, "Invalid mesh level of detail index at node \'{0}\'. Maximum supported amount of LODs is {1}.", nodeName, MODEL_MAX_LODS); } } - return 0; } From c41248f4024873ccb31a6a68cb6b83d8fdddfa81 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 29 Oct 2022 11:42:06 +0200 Subject: [PATCH 19/25] Optimize asset registry paths check to use `StringUtils::CompareIgnoreCase` instead of `String::ToLower`ToLower #765 --- Source/Engine/Content/Cache/AssetsCache.cpp | 28 +++++++-------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/Source/Engine/Content/Cache/AssetsCache.cpp b/Source/Engine/Content/Cache/AssetsCache.cpp index 44461a68b..efff16a38 100644 --- a/Source/Engine/Content/Cache/AssetsCache.cpp +++ b/Source/Engine/Content/Cache/AssetsCache.cpp @@ -281,7 +281,6 @@ bool AssetsCache::FindAsset(const StringView& path, AssetInfo& info) auto& e = i->Value; if (e.Info.Path == path) { - // Validate file exists if (!IsEntryValid(e)) { LOG(Warning, "Missing file from registry: \'{0}\':{1}:{2}", e.Info.Path, e.Info.ID, e.Info.TypeName); @@ -304,15 +303,11 @@ bool AssetsCache::FindAsset(const StringView& path, AssetInfo& info) bool AssetsCache::FindAsset(const Guid& id, AssetInfo& info) { PROFILE_CPU(); - bool result = false; - ScopeLock lock(_locker); - auto e = _registry.TryGet(id); if (e != nullptr) { - // Validate entry if (!IsEntryValid(*e)) { LOG(Warning, "Missing file from registry: \'{0}\':{1}:{2}", e->Info.Path, e->Info.ID, e->Info.TypeName); @@ -325,7 +320,6 @@ bool AssetsCache::FindAsset(const Guid& id, AssetInfo& info) info = e->Info; } } - return result; } @@ -379,27 +373,26 @@ void AssetsCache::RegisterAssets(FlaxStorage* storage) // Check if storage contains ID which has been already registered if (FindAsset(e.ID, info)) { - #if PLATFORM_WINDOWS - //PE: Windows - if you start your project using a shortcut/VS commandline -project , and using a upper/lower drive letter, it could ruin your scene. - //PE: On windows case do not matter so... - if (storagePath.ToLower() != info.Path.ToLower()) +#if PLATFORM_WINDOWS + // On Windows - if you start your project using a shortcut/VS commandline -project, and using a upper/lower drive letter, it could the cache (case doesn't matter on OS) + if (StringUtils::CompareIgnoreCase(storagePath.GetText(), info.Path.GetText()) != 0) { LOG(Warning, "Founded duplicated asset \'{0}\'. Locations: \'{1}\' and \'{2}\'", e.ID, storagePath, info.Path); duplicatedEntries.Add(i); } else { - //PE: Remove from _registry so we can add it again later with the original ID, so we dont loose relations. - for (auto i = _registry.Begin(); i.IsNotEnd(); ++i) + // Remove from registry so we can add it again later with the original ID, so we don't loose relations + for (auto j = _registry.Begin(); j.IsNotEnd(); ++j) { - if (i->Value.Info.Path.ToLower() == storagePath.ToLower()) - _registry.Remove(i); + if (StringUtils::CompareIgnoreCase(j->Value.Info.Path.GetText(), storagePath.GetText()) == 0) + _registry.Remove(j); } } - #else +#else LOG(Warning, "Founded duplicated asset \'{0}\'. Locations: \'{1}\' and \'{2}\'", e.ID, storagePath, info.Path); duplicatedEntries.Add(i); - #endif +#endif } } @@ -570,7 +563,6 @@ bool AssetsCache::RenameAsset(const StringView& oldPath, const StringView& newPa bool AssetsCache::IsEntryValid(Entry& e) { #if ENABLE_ASSETS_DISCOVERY - // Check if file exists if (FileSystem::FileExists(e.Info.Path)) { @@ -620,10 +612,8 @@ bool AssetsCache::IsEntryValid(Entry& e) return false; #else - // In game we don't care about it because all cached asset entries are valid (precached) // Skip only entries with missing file return e.Info.Path.HasChars(); - #endif } From f67d1412dee1eff6ef3ce8085c8a45349d5ad79f Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 29 Oct 2022 11:50:16 +0200 Subject: [PATCH 20/25] Add undo/redo and navmesh dirtying when using selection rotate shortcut (R key) #765 --- Source/Editor/Gizmo/TransformGizmoBase.cs | 4 ++-- Source/Editor/Viewport/MainEditorGizmoViewport.cs | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Source/Editor/Gizmo/TransformGizmoBase.cs b/Source/Editor/Gizmo/TransformGizmoBase.cs index 13ebece7c..c3ba6a165 100644 --- a/Source/Editor/Gizmo/TransformGizmoBase.cs +++ b/Source/Editor/Gizmo/TransformGizmoBase.cs @@ -86,7 +86,7 @@ namespace FlaxEditor.Gizmo /// /// Starts the objects transforming (optionally with duplicate). /// - protected void StartTransforming() + public void StartTransforming() { // Check if can start new action var count = SelectionCount; @@ -119,7 +119,7 @@ namespace FlaxEditor.Gizmo /// /// Ends the objects transforming. /// - protected void EndTransforming() + public void EndTransforming() { // Check if wasn't working at all if (!_isTransforming) diff --git a/Source/Editor/Viewport/MainEditorGizmoViewport.cs b/Source/Editor/Viewport/MainEditorGizmoViewport.cs index 066ab1c00..1e9453bc5 100644 --- a/Source/Editor/Viewport/MainEditorGizmoViewport.cs +++ b/Source/Editor/Viewport/MainEditorGizmoViewport.cs @@ -329,7 +329,6 @@ namespace FlaxEditor.Viewport var buttonBB = translateSnappingCM.AddButton("Bounding Box"); buttonBB.Tag = -1.0f; - translateSnappingCM.ButtonClicked += OnWidgetTranslateSnapClick; translateSnappingCM.VisibleChanged += OnWidgetTranslateSnapShowHide; _translateSnapping.Parent = translateSnappingWidget; @@ -711,10 +710,10 @@ namespace FlaxEditor.Viewport { var win = (WindowRootControl)Root; var selection = _editor.SceneEditing.Selection; - var IsShiftDown = win.GetKey(KeyboardKeys.Shift); + var isShiftDown = win.GetKey(KeyboardKeys.Shift); Quaternion rotationDelta; - if(IsShiftDown) + if (isShiftDown) rotationDelta = Quaternion.Euler(0.0f, -45.0f, 0.0f); else rotationDelta = Quaternion.Euler(0.0f, 45.0f, 0.0f); @@ -722,15 +721,16 @@ namespace FlaxEditor.Viewport bool useObjCenter = TransformGizmo.ActivePivot == TransformGizmoBase.PivotType.ObjectCenter; Vector3 gizmoPosition = TransformGizmo.Position; - //PE: Rotate selected objects. + // Rotate selected objects bool isPlayMode = Editor.Instance.StateMachine.IsPlayMode; + TransformGizmo.StartTransforming(); for (int i = 0; i < selection.Count; i++) { var obj = selection[i]; if (isPlayMode && obj.CanTransform == false) continue; var trans = obj.Transform; - Vector3 pivotOffset = trans.Translation - gizmoPosition; + var pivotOffset = trans.Translation - gizmoPosition; if (useObjCenter || pivotOffset.IsZero) { trans.Orientation *= Quaternion.Invert(trans.Orientation) * rotationDelta * trans.Orientation; @@ -745,6 +745,7 @@ namespace FlaxEditor.Viewport } obj.Transform = trans; } + TransformGizmo.EndTransforming(); } /// From 4ba93d9d861b7779a1fd616388a2185e62740784 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 29 Oct 2022 12:04:42 +0200 Subject: [PATCH 21/25] Code cleanup #765 --- .../Editor/Gizmo/TransformGizmoBase.Draw.cs | 6 +-- Source/Editor/Gizmo/TransformGizmoBase.cs | 43 +++++++++---------- .../Viewport/MainEditorGizmoViewport.cs | 11 ++--- Source/Engine/Audio/AudioSource.cpp | 2 +- Source/Engine/Core/Types/String.cpp | 1 - Source/Engine/Scripting/Scripting.cpp | 5 +-- Source/Engine/Scripting/Scripting.h | 6 +-- .../Tools/ModelTool/ModelTool.Assimp.cpp | 2 +- 8 files changed, 30 insertions(+), 46 deletions(-) diff --git a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs index 6957a9525..b3609783f 100644 --- a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs +++ b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs @@ -54,10 +54,8 @@ namespace FlaxEditor.Gizmo if (!_isActive || !IsActive) return; - //PE: As all axisMesh have the same pivot, add a little offset to the x axisMesh, - //PE: This way SortDrawCalls is able to sort the draw order. - //PE: https://github.com/FlaxEngine/FlaxEngine/issues/680 - //PE: @Artist To fix the rotate, add new "wider" circleMesh, so direction is visible. + // As all axisMesh have the same pivot, add a little offset to the x axisMesh, this way SortDrawCalls is able to sort the draw order + // https://github.com/FlaxEngine/FlaxEngine/issues/680 Matrix m1, m2, m3 , mx1; bool isXAxis = _activeAxis == Axis.X || _activeAxis == Axis.XY || _activeAxis == Axis.ZX; diff --git a/Source/Editor/Gizmo/TransformGizmoBase.cs b/Source/Editor/Gizmo/TransformGizmoBase.cs index c3ba6a165..221ab7e86 100644 --- a/Source/Editor/Gizmo/TransformGizmoBase.cs +++ b/Source/Editor/Gizmo/TransformGizmoBase.cs @@ -287,31 +287,29 @@ namespace FlaxEditor.Gizmo delta *= 0.5f; if ((isScaling ? ScaleSnapEnabled : TranslationSnapEnable) || Owner.UseSnapping) { - float snapValue = isScaling ? ScaleSnapValue : TranslationSnapValue; + var snapValue = new Vector3(isScaling ? ScaleSnapValue : TranslationSnapValue); _translationScaleSnapDelta += delta; - if (!isScaling && snapValue < 0.0f) + if (!isScaling && snapValue.X < 0.0f) { - //PE: Snap to object bounding box + // Snap to object bounding box GetSelectedObjectsBounds(out var b, out _); - float X, Y, Z; - if (b.Minimum.X < 0.0f) X = (float) Math.Abs(b.Minimum.X) + b.Maximum.X; - else X = (float) b.Minimum.X - b.Maximum.X; - if (b.Minimum.Y < 0.0f) Y = (float) Math.Abs(b.Minimum.Y) + b.Maximum.Y; - else Y = (float) b.Minimum.Y - b.Maximum.Y; - if (b.Minimum.Z < 0.0f) Z = (float) Math.Abs(b.Minimum.Z) + b.Maximum.Z; - else Z = (float) b.Minimum.Z - b.Maximum.Z; - delta = new Vector3( - (int)(_translationScaleSnapDelta.X / X) * X, - (int)(_translationScaleSnapDelta.Y / Y) * Y, - (int)(_translationScaleSnapDelta.Z / Z) * Z); - } - else - { - delta = new Vector3( - (int)(_translationScaleSnapDelta.X / snapValue) * snapValue, - (int)(_translationScaleSnapDelta.Y / snapValue) * snapValue, - (int)(_translationScaleSnapDelta.Z / snapValue) * snapValue); + if (b.Minimum.X < 0.0f) + snapValue.X = (Real)Math.Abs(b.Minimum.X) + b.Maximum.X; + else + snapValue.X = (Real)b.Minimum.X - b.Maximum.X; + if (b.Minimum.Y < 0.0f) + snapValue.Y = (Real)Math.Abs(b.Minimum.Y) + b.Maximum.Y; + else + snapValue.Y = (Real)b.Minimum.Y - b.Maximum.Y; + if (b.Minimum.Z < 0.0f) + snapValue.Z = (Real)Math.Abs(b.Minimum.Z) + b.Maximum.Z; + else + snapValue.Z = (Real)b.Minimum.Z - b.Maximum.Z; } + delta = new Vector3( + (int)(_translationScaleSnapDelta.X / snapValue.X) * snapValue.X, + (int)(_translationScaleSnapDelta.Y / snapValue.Y) * snapValue.Y, + (int)(_translationScaleSnapDelta.Z / snapValue.Z) * snapValue.Z); _translationScaleSnapDelta -= delta; } @@ -465,10 +463,9 @@ namespace FlaxEditor.Gizmo } // Apply transformation (but to the parents, not whole selection pool) - if (anyValid || (!_isTransforming && Owner.UseDuplicate) ) + if (anyValid || (!_isTransforming && Owner.UseDuplicate)) { StartTransforming(); - LastDelta = new Transform(translationDelta, rotationDelta, scaleDelta); OnApplyTransformation(ref translationDelta, ref rotationDelta, ref scaleDelta); } diff --git a/Source/Editor/Viewport/MainEditorGizmoViewport.cs b/Source/Editor/Viewport/MainEditorGizmoViewport.cs index 1e9453bc5..c725c3b8b 100644 --- a/Source/Editor/Viewport/MainEditorGizmoViewport.cs +++ b/Source/Editor/Viewport/MainEditorGizmoViewport.cs @@ -319,6 +319,8 @@ namespace FlaxEditor.Viewport { TooltipText = "Position snapping values" }; + if (TransformGizmo.TranslationSnapValue < 0.0f) + _translateSnapping.Text = "Bounding Box"; for (int i = 0; i < EditorViewportTranslateSnapValues.Length; i++) { @@ -326,7 +328,7 @@ namespace FlaxEditor.Viewport var button = translateSnappingCM.AddButton(v.ToString()); button.Tag = v; } - var buttonBB = translateSnappingCM.AddButton("Bounding Box"); + var buttonBB = translateSnappingCM.AddButton("Bounding Box").LinkTooltip("Snaps the selection based on it's bounding volume"); buttonBB.Tag = -1.0f; translateSnappingCM.ButtonClicked += OnWidgetTranslateSnapClick; @@ -543,28 +545,24 @@ namespace FlaxEditor.Viewport private void OnTranslateSnappingToggle(ViewportWidgetButton button) { TransformGizmo.TranslationSnapEnable = !TransformGizmo.TranslationSnapEnable; - // cache value _editor.ProjectCache.SetCustomData("TranslateSnapState", TransformGizmo.TranslationSnapEnable.ToString()); } private void OnRotateSnappingToggle(ViewportWidgetButton button) { TransformGizmo.RotationSnapEnabled = !TransformGizmo.RotationSnapEnabled; - // cache value _editor.ProjectCache.SetCustomData("RotationSnapState", TransformGizmo.RotationSnapEnabled.ToString()); } private void OnScaleSnappingToggle(ViewportWidgetButton button) { TransformGizmo.ScaleSnapEnabled = !TransformGizmo.ScaleSnapEnabled; - // cache value _editor.ProjectCache.SetCustomData("ScaleSnapState", TransformGizmo.ScaleSnapEnabled.ToString()); } private void OnTransformSpaceToggle(ViewportWidgetButton button) { TransformGizmo.ToggleTransformSpace(); - // cache value _editor.ProjectCache.SetCustomData("TransformSpaceState", TransformGizmo.ActiveTransformSpace.ToString()); } @@ -595,7 +593,6 @@ namespace FlaxEditor.Viewport var v = (float)button.Tag; TransformGizmo.ScaleSnapValue = v; _scaleSnapping.Text = v.ToString(); - // cache value _editor.ProjectCache.SetCustomData("ScaleSnapValue", TransformGizmo.ScaleSnapValue.ToString("N")); } @@ -634,7 +631,6 @@ namespace FlaxEditor.Viewport var v = (float)button.Tag; TransformGizmo.RotationSnapValue = v; _rotateSnapping.Text = v.ToString(); - // cache value _editor.ProjectCache.SetCustomData("RotationSnapValue", TransformGizmo.RotationSnapValue.ToString("N")); } @@ -675,7 +671,6 @@ namespace FlaxEditor.Viewport _translateSnapping.Text = "Bounding Box"; else _translateSnapping.Text = v.ToString(); - // cache value _editor.ProjectCache.SetCustomData("TranslateSnapValue", TransformGizmo.TranslationSnapValue.ToString("N")); } diff --git a/Source/Engine/Audio/AudioSource.cpp b/Source/Engine/Audio/AudioSource.cpp index c01e20692..59d14e7d9 100644 --- a/Source/Engine/Audio/AudioSource.cpp +++ b/Source/Engine/Audio/AudioSource.cpp @@ -131,7 +131,7 @@ void AudioSource::Play() // Request faster streaming update Clip->RequestStreamingUpdate(); - // PE: If we are looping and streaming also update streaming buffers. + // If we are looping and streaming also update streaming buffers if(_loop) RequestStreamingBuffersUpdate(); } diff --git a/Source/Engine/Core/Types/String.cpp b/Source/Engine/Core/Types/String.cpp index 7a8f1b1ed..340430d32 100644 --- a/Source/Engine/Core/Types/String.cpp +++ b/Source/Engine/Core/Types/String.cpp @@ -215,7 +215,6 @@ bool String::IsANSI() const bool result = true; for (int32 i = 0; i < _length; i++) { - //PE: Ansi is max 7 bit so... if (_data[i] > 127) { result = false; diff --git a/Source/Engine/Scripting/Scripting.cpp b/Source/Engine/Scripting/Scripting.cpp index 5af41502a..ac7a6f8e8 100644 --- a/Source/Engine/Scripting/Scripting.cpp +++ b/Source/Engine/Scripting/Scripting.cpp @@ -872,17 +872,14 @@ ScriptingObject* Scripting::TryFindObject(MClass* mclass) { if (mclass == nullptr) return nullptr; - ScopeLock lock(_objectsLocker); - for (auto i = _objectsDictionary.Begin(); i.IsNotEnd(); ++i) { const auto obj = i->Value; - if(obj->GetClass() == mclass) + if (obj->GetClass() == mclass) return obj; } return nullptr; - } ScriptingObject* Scripting::FindObject(const MObject* managedInstance) diff --git a/Source/Engine/Scripting/Scripting.h b/Source/Engine/Scripting/Scripting.h index 41e5d7119..dc13b696c 100644 --- a/Source/Engine/Scripting/Scripting.h +++ b/Source/Engine/Scripting/Scripting.h @@ -85,7 +85,7 @@ public: /// The full name of the type eg: System.Int64. /// The MClass object or null if missing. static MClass* FindClass(const StringAnsiView& fullname); - + #if USE_MONO /// /// Finds the class from the given Mono class object within whole assembly. @@ -144,13 +144,11 @@ public: /// The found object or null if missing. static ScriptingObject* FindObject(Guid id, MClass* type = nullptr); - /// /// Tries to find the object by the given class. /// /// The found object or null if missing. - static ScriptingObject* TryFindObject(MClass* type = nullptr); - + static ScriptingObject* TryFindObject(MClass* type); /// /// Tries to find the object by the given identifier. diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp index cc0c68d79..6d06961dd 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp @@ -641,7 +641,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ImportedModelData& data, Opti aiProcess_JoinIdenticalVertices | aiProcess_LimitBoneWeights | aiProcess_Triangulate | - aiProcess_SortByPType | //PE: Added aiProcess_SortByPType so we can ignore meshes with non triangle faces. + aiProcess_SortByPType | aiProcess_GenUVCoords | aiProcess_FindDegenerates | aiProcess_FindInvalidData | From 6379171fa6af794ce54187140c656829a3bf722b Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 29 Oct 2022 18:56:21 +0200 Subject: [PATCH 22/25] Fix crash due to bdb69d57dd4cc37513105d1c6ecb8b59f7c66647 (Mono typenames are invalid after dll unloaded) --- Source/Engine/Scripting/BinaryModule.cpp | 12 ++++++++++-- Source/Engine/Scripting/BinaryModule.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Scripting/BinaryModule.cpp b/Source/Engine/Scripting/BinaryModule.cpp index 8a7f8ddbe..1fd9517da 100644 --- a/Source/Engine/Scripting/BinaryModule.cpp +++ b/Source/Engine/Scripting/BinaryModule.cpp @@ -697,6 +697,7 @@ ManagedBinaryModule::ManagedBinaryModule(MAssembly* assembly) // Bind for C# assembly events assembly->Loading.Bind(this); assembly->Loaded.Bind(this); + assembly->Unloading.Bind(this); assembly->Unloaded.Bind(this); if (Assembly->IsLoaded()) @@ -1095,17 +1096,24 @@ void ManagedBinaryModule::InitType(MClass* mclass) #endif } -void ManagedBinaryModule::OnUnloaded(MAssembly* assembly) +void ManagedBinaryModule::OnUnloading(MAssembly* assembly) { PROFILE_CPU(); - // Clear managed-only types + // Clear managed types typenames for (int32 i = _firstManagedTypeIndex; i < Types.Count(); i++) { const ScriptingType& type = Types[i]; const MString typeName(type.Fullname.Get(), type.Fullname.Length()); TypeNameToTypeIndex.Remove(typeName); } +} + +void ManagedBinaryModule::OnUnloaded(MAssembly* assembly) +{ + PROFILE_CPU(); + + // Clear managed-only types Types.Resize(_firstManagedTypeIndex); for (int32 i = 0; i < _managedMemoryBlocks.Count(); i++) Allocator::Free(_managedMemoryBlocks[i]); diff --git a/Source/Engine/Scripting/BinaryModule.h b/Source/Engine/Scripting/BinaryModule.h index ede625cc1..7c69a2dc6 100644 --- a/Source/Engine/Scripting/BinaryModule.h +++ b/Source/Engine/Scripting/BinaryModule.h @@ -309,6 +309,7 @@ private: void OnLoading(MAssembly* assembly); void OnLoaded(MAssembly* assembly); void InitType(MClass* mclass); + void OnUnloading(MAssembly* assembly); void OnUnloaded(MAssembly* assembly); public: From 57e812d336e6470ce2b853e916fd4a31f36ca360 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 29 Oct 2022 18:57:57 +0200 Subject: [PATCH 23/25] Fix audio clips streaming to be thread-safe when audio sources play #786 --- Source/Editor/Gizmo/TransformGizmoBase.Draw.cs | 2 +- Source/Engine/Audio/AudioClip.cpp | 6 +++--- Source/Engine/Audio/AudioSource.cpp | 5 ++++- Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp | 2 ++ 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs index b3609783f..f149185f1 100644 --- a/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs +++ b/Source/Editor/Gizmo/TransformGizmoBase.Draw.cs @@ -57,7 +57,7 @@ namespace FlaxEditor.Gizmo // As all axisMesh have the same pivot, add a little offset to the x axisMesh, this way SortDrawCalls is able to sort the draw order // https://github.com/FlaxEngine/FlaxEngine/issues/680 - Matrix m1, m2, m3 , mx1; + Matrix m1, m2, m3, mx1; bool isXAxis = _activeAxis == Axis.X || _activeAxis == Axis.XY || _activeAxis == Axis.ZX; bool isYAxis = _activeAxis == Axis.Y || _activeAxis == Axis.XY || _activeAxis == Axis.YZ; bool isZAxis = _activeAxis == Axis.Z || _activeAxis == Axis.YZ || _activeAxis == Axis.ZX; diff --git a/Source/Engine/Audio/AudioClip.cpp b/Source/Engine/Audio/AudioClip.cpp index 9efe88a2a..fd8311132 100644 --- a/Source/Engine/Audio/AudioClip.cpp +++ b/Source/Engine/Audio/AudioClip.cpp @@ -20,10 +20,11 @@ bool AudioClip::StreamingTask::Run() { AssetReference ref = _asset.Get(); if (ref == nullptr) - { return true; - } + ScopeLock lock(ref->Locker); const auto& queue = ref->StreamingQueue; + if (queue.Count() == 0) + return false; auto clip = ref.Get(); // Update the buffers @@ -108,7 +109,6 @@ bool AudioClip::StreamingTask::Run() for (int32 sourceIndex = 0; sourceIndex < Audio::Sources.Count(); sourceIndex++) { // TODO: collect refs to audio clip from sources and use faster iteration (but do it thread-safe) - const auto src = Audio::Sources[sourceIndex]; if (src->Clip == clip && src->GetState() == AudioSource::States::Playing) { diff --git a/Source/Engine/Audio/AudioSource.cpp b/Source/Engine/Audio/AudioSource.cpp index 59d14e7d9..10e2cf429 100644 --- a/Source/Engine/Audio/AudioSource.cpp +++ b/Source/Engine/Audio/AudioSource.cpp @@ -132,7 +132,7 @@ void AudioSource::Play() Clip->RequestStreamingUpdate(); // If we are looping and streaming also update streaming buffers - if(_loop) + if (_loop) RequestStreamingBuffersUpdate(); } } @@ -372,6 +372,7 @@ void AudioSource::Update() if (!UseStreaming() || SourceIDs.IsEmpty()) return; auto clip = Clip.Get(); + clip->Locker.Lock(); // Handle streaming buffers queue submit (ensure that clip has loaded the first chunk with audio data) if (_needToUpdateStreamingBuffers && clip->Buffers[_streamingFirstChunk] != AUDIO_BUFFER_ID_INVALID) @@ -441,6 +442,8 @@ void AudioSource::Update() clip->RequestStreamingUpdate(); } } + + clip->Locker.Unlock(); } void AudioSource::OnEnable() diff --git a/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp b/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp index aa607421e..ef1e84675 100644 --- a/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp +++ b/Source/Engine/Audio/OpenAL/AudioBackendOAL.cpp @@ -139,10 +139,12 @@ namespace ALC alSourcef(sourceID, AL_GAIN, source->GetVolume()); alSourcef(sourceID, AL_PITCH, source->GetPitch()); + alSourcef(sourceID, AL_SEC_OFFSET, 0.0f); alSourcef(sourceID, AL_REFERENCE_DISTANCE, source->GetMinDistance()); alSourcef(sourceID, AL_ROLLOFF_FACTOR, source->GetAttenuation()); alSourcei(sourceID, AL_LOOPING, loop); alSourcei(sourceID, AL_SOURCE_RELATIVE, !is3D); + alSourcei(sourceID, AL_BUFFER, 0); alSource3f(sourceID, AL_POSITION, FLAX_POS_TO_OAL(position)); alSource3f(sourceID, AL_VELOCITY, FLAX_POS_TO_OAL(velocity)); } From 7ddc1a155392f0e7c2005f444f2fdf61653f185f Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 29 Oct 2022 19:05:35 +0200 Subject: [PATCH 24/25] Code style fix --- Source/Engine/UI/GUI/Common/TextBoxBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/UI/GUI/Common/TextBoxBase.cs b/Source/Engine/UI/GUI/Common/TextBoxBase.cs index 92ea513a6..d78bd3d6b 100644 --- a/Source/Engine/UI/GUI/Common/TextBoxBase.cs +++ b/Source/Engine/UI/GUI/Common/TextBoxBase.cs @@ -137,7 +137,7 @@ namespace FlaxEngine.GUI /// /// Event fired when a key is up. /// - public event Action KeyUp; + public event Action KeyUp; /// /// Gets or sets a value indicating whether this is a multiline text box control. From e1836a222c9597d57ad27af74d38082cbab2ff63 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 29 Oct 2022 19:33:34 +0200 Subject: [PATCH 25/25] Fix bug with `Screen.CursorVisible` set in script `OnStart` #799 --- Source/Editor/Windows/GameWindow.cs | 36 ++++++++++++++++++++--------- Source/Engine/Engine/Screen.cpp | 20 ++++++++++------ 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/Source/Editor/Windows/GameWindow.cs b/Source/Editor/Windows/GameWindow.cs index 4f9a18218..23558c396 100644 --- a/Source/Editor/Windows/GameWindow.cs +++ b/Source/Editor/Windows/GameWindow.cs @@ -21,7 +21,8 @@ namespace FlaxEditor.Windows private readonly GameRoot _guiRoot; private bool _showGUI = true; private bool _showDebugDraw = false; - private bool _isMaximized = false; + private bool _isMaximized = false, _isUnlockingMouse = false; + private bool _cursorVisible = true; private float _gameStartTime; private GUI.Docking.DockState _maximizeRestoreDockState; private GUI.Docking.DockPanel _maximizeRestoreDockTo; @@ -460,14 +461,20 @@ namespace FlaxEditor.Windows { if (Editor.StateMachine.IsPlayMode) { - Screen.CursorVisible = true; - Focus(null); - Editor.Windows.MainWindow.Focus(); - if (Editor.Windows.PropertiesWin.IsDocked) - Editor.Windows.PropertiesWin.Focus(); + // Cache cursor + _cursorVisible = Screen.CursorVisible; + _cursorLockMode = Screen.CursorLock; Screen.CursorVisible = true; if (Screen.CursorLock == CursorLockMode.Clipped) Screen.CursorLock = CursorLockMode.None; + + // Defocus + _isUnlockingMouse = true; + Focus(null); + _isUnlockingMouse = false; + Editor.Windows.MainWindow.Focus(); + if (Editor.Windows.PropertiesWin.IsDocked) + Editor.Windows.PropertiesWin.Focus(); } } @@ -552,9 +559,11 @@ namespace FlaxEditor.Windows Root.MousePosition = center; } - // Restore lock mode + // Restore cursor if (_cursorLockMode != CursorLockMode.None) Screen.CursorLock = _cursorLockMode; + if (!_cursorVisible) + Screen.CursorVisible = false; } } @@ -563,11 +572,16 @@ namespace FlaxEditor.Windows { base.OnEndContainsFocus(); - // Restore cursor visibility (could be hidden by the game) - Screen.CursorVisible = true; + if (!_isUnlockingMouse) + { + // Cache cursor + _cursorVisible = Screen.CursorVisible; + _cursorLockMode = Screen.CursorLock; - // Cache lock mode - _cursorLockMode = Screen.CursorLock; + // Restore cursor visibility (could be hidden by the game) + if (!_cursorVisible) + Screen.CursorVisible = true; + } } /// diff --git a/Source/Engine/Engine/Screen.cpp b/Source/Engine/Engine/Screen.cpp index b6cec67c6..a527bbcfe 100644 --- a/Source/Engine/Engine/Screen.cpp +++ b/Source/Engine/Engine/Screen.cpp @@ -15,7 +15,8 @@ Nullable Fullscreen; Nullable Size; -static CursorLockMode CursorLock = CursorLockMode::None; +bool CursorVisible = true; +CursorLockMode CursorLock = CursorLockMode::None; class ScreenService : public EngineService { @@ -25,6 +26,7 @@ public: { } + void Update() override; void Draw() override; }; @@ -88,12 +90,7 @@ Float2 Screen::GameViewportToScreen(const Float2& viewportPos) bool Screen::GetCursorVisible() { -#if USE_EDITOR - const auto win = Editor::Managed->GetGameWindow(true); -#else - const auto win = Engine::MainWindow; -#endif - return win ? win->GetCursor() != CursorType::Hidden : true; + return CursorVisible; } void Screen::SetCursorVisible(const bool value) @@ -107,6 +104,7 @@ void Screen::SetCursorVisible(const bool value) { win->SetCursor(value ? CursorType::Default : CursorType::Hidden); } + CursorVisible = value; } CursorLockMode Screen::GetCursorLock() @@ -137,6 +135,14 @@ void Screen::SetCursorLock(CursorLockMode mode) CursorLock = mode; } +void ScreenService::Update() +{ +#if USE_EDITOR + // Sync current cursor state in Editor (eg. when viewport focus can change) + Screen::SetCursorVisible(CursorVisible); +#endif +} + void ScreenService::Draw() { #if USE_EDITOR