From 7cae9b4ce5aa2116826bfded9a8f139aeb58d9e6 Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Sat, 24 Sep 2022 13:46:55 +0200 Subject: [PATCH 01/11] 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/11] 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/11] 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/11] 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/11] 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/11] 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/11] 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/11] 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/11] 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 fd831f569c542a7100702f162e704e1bd3e59f5a Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Wed, 26 Oct 2022 09:54:10 +0200 Subject: [PATCH 10/11] 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 11/11] 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;