diff --git a/Development/Documentation/mono.md b/Development/Documentation/mono.md
index d292ebb3d..4a880b7a0 100644
--- a/Development/Documentation/mono.md
+++ b/Development/Documentation/mono.md
@@ -2,6 +2,8 @@
Custom fork: [https://github.com/FlaxEngine/mono](https://github.com/FlaxEngine/mono) with custom features for C# assemblies hot-reloading at runtime without domain unload (more: [https://flaxengine.com/blog/flax-facts-16-scripts-hot-reload/](https://flaxengine.com/blog/flax-facts-16-scripts-hot-reload/)).
+Startup docs about building mono: [https://www.mono-project.com/docs/compiling-mono/](https://www.mono-project.com/docs/compiling-mono/)
+
### Notes
Some useful notes and tips for devs:
diff --git a/Source/Editor/Cooker/Steps/CookAssetsStep.cpp b/Source/Editor/Cooker/Steps/CookAssetsStep.cpp
index 1396214ca..aee282024 100644
--- a/Source/Editor/Cooker/Steps/CookAssetsStep.cpp
+++ b/Source/Editor/Cooker/Steps/CookAssetsStep.cpp
@@ -221,6 +221,7 @@ void CookAssetsStep::CacheData::Load(CookingData& data)
{
const auto settings = WindowsPlatformSettings::Get();
const bool modified =
+ Settings.Windows.SupportDX12 != settings->SupportDX12 ||
Settings.Windows.SupportDX11 != settings->SupportDX11 ||
Settings.Windows.SupportDX10 != settings->SupportDX10 ||
Settings.Windows.SupportVulkan != settings->SupportVulkan;
@@ -1025,6 +1026,7 @@ bool CookAssetsStep::Perform(CookingData& data)
#if PLATFORM_TOOLS_WINDOWS
{
const auto settings = WindowsPlatformSettings::Get();
+ cache.Settings.Windows.SupportDX12 = settings->SupportDX12;
cache.Settings.Windows.SupportDX11 = settings->SupportDX11;
cache.Settings.Windows.SupportDX10 = settings->SupportDX10;
cache.Settings.Windows.SupportVulkan = settings->SupportVulkan;
diff --git a/Source/Editor/Cooker/Steps/CookAssetsStep.h b/Source/Editor/Cooker/Steps/CookAssetsStep.h
index 36d0734eb..7a6163700 100644
--- a/Source/Editor/Cooker/Steps/CookAssetsStep.h
+++ b/Source/Editor/Cooker/Steps/CookAssetsStep.h
@@ -75,6 +75,7 @@ public:
{
struct
{
+ bool SupportDX12;
bool SupportDX11;
bool SupportDX10;
bool SupportVulkan;
diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs
index d4afdd693..50de80e88 100644
--- a/Source/Editor/Editor.cs
+++ b/Source/Editor/Editor.cs
@@ -891,10 +891,10 @@ namespace FlaxEditor
if (asset == null)
throw new ArgumentNullException(nameof(asset));
if (asset.WaitForLoaded())
- throw new FlaxException("Failed to load asset.");
+ throw new Exception("Failed to load asset.");
var source = Internal_GetShaderAssetSourceCode(FlaxEngine.Object.GetUnmanagedPtr(asset));
if (source == null)
- throw new FlaxException("Failed to get source code.");
+ throw new Exception("Failed to get source code.");
return source;
}
diff --git a/Source/Editor/GUI/Timeline/Tracks/AnimationEventTrack.cs b/Source/Editor/GUI/Timeline/Tracks/AnimationEventTrack.cs
index 1fe3bb763..4e813fe38 100644
--- a/Source/Editor/GUI/Timeline/Tracks/AnimationEventTrack.cs
+++ b/Source/Editor/GUI/Timeline/Tracks/AnimationEventTrack.cs
@@ -30,6 +30,8 @@ namespace FlaxEditor.GUI.Timeline.Tracks
base.Initialize(layout);
var instance = (AnimEvent)Values[0];
+ if (instance == null)
+ return;
var scriptType = TypeUtils.GetObjectType(instance);
var editor = CustomEditorsUtil.CreateEditor(scriptType, false);
layout.Object(Values, editor);
@@ -125,6 +127,52 @@ namespace FlaxEditor.GUI.Timeline.Tracks
}
}
+ internal void InitMissing(string typeName, byte[] data)
+ {
+ Type = ScriptType.Null;
+ IsContinuous = false;
+ CanDelete = true;
+ CanSplit = false;
+ CanResize = false;
+ TooltipText = $"Missing Anim Event Type '{typeName}'";
+ Instance = null;
+ BackgroundColor = Color.Red;
+ _instanceTypeName = typeName;
+ _instanceData = data;
+ }
+
+ internal void Load(BinaryReader stream)
+ {
+ StartFrame = (int)stream.ReadSingle();
+ DurationFrames = (int)stream.ReadSingle();
+ var typeName = stream.ReadStrAnsi(13);
+ var type = TypeUtils.GetType(typeName);
+ if (type == ScriptType.Null)
+ {
+ InitMissing(typeName, stream.ReadJsonBytes());
+ return;
+ }
+ Init(type);
+ stream.ReadJson(Instance);
+ }
+
+ internal void Save(BinaryWriter stream)
+ {
+ stream.Write((float)StartFrame);
+ stream.Write((float)DurationFrames);
+ if (Type != ScriptType.Null)
+ {
+ stream.WriteStrAnsi(Type.TypeName, 13);
+ stream.WriteJson(Instance);
+ }
+ else
+ {
+ // Missing
+ stream.WriteStrAnsi(_instanceTypeName, 13);
+ stream.WriteJsonBytes(_instanceData);
+ }
+ }
+
///
protected override void OnDurationFramesChanged()
{
@@ -137,6 +185,8 @@ namespace FlaxEditor.GUI.Timeline.Tracks
///
public override void OnDestroy()
{
+ _instanceData = null;
+ _instanceTypeName = null;
Type = ScriptType.Null;
Object.Destroy(ref Instance);
if (_isRegisteredForScriptsReload)
@@ -181,14 +231,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
for (int i = 0; i < count; i++)
{
var m = (AnimationEventMedia)e.Media[i];
- m.StartFrame = (int)stream.ReadSingle();
- m.DurationFrames = (int)stream.ReadSingle();
- var typeName = stream.ReadStrAnsi(13);
- var type = TypeUtils.GetType(typeName);
- if (type == ScriptType.Null)
- throw new Exception($"Unknown type {typeName}.");
- m.Init(type);
- stream.ReadJson(m.Instance);
+ m.Load(stream);
}
}
@@ -200,10 +243,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
for (int i = 0; i < count; i++)
{
var m = (AnimationEventMedia)e.Media[i];
- stream.Write((float)m.StartFrame);
- stream.Write((float)m.DurationFrames);
- stream.WriteStrAnsi(m.Type.TypeName, 13);
- stream.WriteJson(m.Instance);
+ m.Save(stream);
}
}
diff --git a/Source/Editor/GUI/Timeline/Tracks/CameraCutTrack.cs b/Source/Editor/GUI/Timeline/Tracks/CameraCutTrack.cs
index 96e858a9a..b5026b1b1 100644
--- a/Source/Editor/GUI/Timeline/Tracks/CameraCutTrack.cs
+++ b/Source/Editor/GUI/Timeline/Tracks/CameraCutTrack.cs
@@ -631,7 +631,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
}
}
if (spriteIndex == -1)
- throw new FlaxException();
+ throw new Exception();
atlas.Count++;
_atlases[atlasIndex] = atlas;
var sprite = new SpriteHandle(atlas.Texture, spriteIndex);
diff --git a/Source/Editor/Modules/PrefabsModule.cs b/Source/Editor/Modules/PrefabsModule.cs
index 94ae8d736..71531df2d 100644
--- a/Source/Editor/Modules/PrefabsModule.cs
+++ b/Source/Editor/Modules/PrefabsModule.cs
@@ -212,7 +212,7 @@ namespace FlaxEditor.Modules
// Call backend
if (PrefabManager.Internal_ApplyAll(FlaxEngine.Object.GetUnmanagedPtr(instance)))
- throw new FlaxException("Failed to apply the prefab. See log to learn more.");
+ throw new Exception("Failed to apply the prefab. See log to learn more.");
PrefabApplied?.Invoke(prefab, instance);
}
diff --git a/Source/Editor/Surface/Archetypes/Constants.cs b/Source/Editor/Surface/Archetypes/Constants.cs
index cb01b4c09..8e1d98e1f 100644
--- a/Source/Editor/Surface/Archetypes/Constants.cs
+++ b/Source/Editor/Surface/Archetypes/Constants.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
using System;
+using System.Reflection;
using FlaxEditor.CustomEditors.Editors;
using FlaxEditor.GUI;
using FlaxEditor.Scripting;
@@ -421,13 +422,23 @@ namespace FlaxEditor.Surface.Archetypes
TryParseText = (string filterText, out object[] data) =>
{
data = null;
- if (!filterText.StartsWith("#"))
- return false;
- if (Color.TryParseHex(filterText, out var color))
+ if (filterText.StartsWith("#") && Color.TryParseHex(filterText, out var color))
{
+ // Color constant from hex
data = new object[] { color };
return true;
}
+ if (filterText.Length > 2)
+ {
+ var fieldName = char.ToUpperInvariant(filterText[0]) + filterText.Substring(1).ToLowerInvariant();
+ var field = typeof(Color).GetField(fieldName, BindingFlags.Public | BindingFlags.Static);
+ if (field != null && fieldName != "Zero")
+ {
+ // Color constant in-built
+ data = new object[] { field.GetValue(null) };
+ return true;
+ }
+ }
return false;
}
},
diff --git a/Source/Editor/Tools/Terrain/Paint/Mode.cs b/Source/Editor/Tools/Terrain/Paint/Mode.cs
index 23b3d47f1..e0eea6186 100644
--- a/Source/Editor/Tools/Terrain/Paint/Mode.cs
+++ b/Source/Editor/Tools/Terrain/Paint/Mode.cs
@@ -1,5 +1,6 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
+using System;
using FlaxEditor.Tools.Terrain.Brushes;
using FlaxEngine;
@@ -129,9 +130,7 @@ namespace FlaxEditor.Tools.Terrain.Paint
// Get the patch data (cached internally by the c++ core in editor)
var sourceData = TerrainTools.GetSplatMapData(terrain, ref patch.PatchCoord, splatmapIndex);
if (sourceData == null)
- {
- throw new FlaxException("Cannot modify terrain. Loading splatmap failed. See log for more info.");
- }
+ throw new Exception("Cannot modify terrain. Loading splatmap failed. See log for more info.");
// Record patch data before editing it
if (!gizmo.CurrentEditUndoAction.HashPatch(ref patch.PatchCoord))
diff --git a/Source/Editor/Tools/Terrain/Sculpt/Mode.cs b/Source/Editor/Tools/Terrain/Sculpt/Mode.cs
index 0708a2558..1e1ece566 100644
--- a/Source/Editor/Tools/Terrain/Sculpt/Mode.cs
+++ b/Source/Editor/Tools/Terrain/Sculpt/Mode.cs
@@ -1,5 +1,6 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
+using System;
using FlaxEditor.Tools.Terrain.Brushes;
using FlaxEngine;
@@ -128,9 +129,7 @@ namespace FlaxEditor.Tools.Terrain.Sculpt
float* sourceHeights = EditHoles ? null : TerrainTools.GetHeightmapData(terrain, ref patch.PatchCoord);
byte* sourceHoles = EditHoles ? TerrainTools.GetHolesMaskData(terrain, ref patch.PatchCoord) : null;
if (sourceHeights == null && sourceHoles == null)
- {
- throw new FlaxException("Cannot modify terrain. Loading heightmap failed. See log for more info.");
- }
+ throw new Exception("Cannot modify terrain. Loading heightmap failed. See log for more info.");
// Record patch data before editing it
if (!gizmo.CurrentEditUndoAction.HashPatch(ref patch.PatchCoord))
diff --git a/Source/Editor/Tools/Terrain/Undo/EditTerrainHeightMapAction.cs b/Source/Editor/Tools/Terrain/Undo/EditTerrainHeightMapAction.cs
index 833e2b8e9..252263902 100644
--- a/Source/Editor/Tools/Terrain/Undo/EditTerrainHeightMapAction.cs
+++ b/Source/Editor/Tools/Terrain/Undo/EditTerrainHeightMapAction.cs
@@ -37,7 +37,7 @@ namespace FlaxEditor.Tools.Terrain.Undo
var offset = Int2.Zero;
var size = new Int2((int)Mathf.Sqrt(_heightmapLength));
if (TerrainTools.ModifyHeightMap(Terrain, ref patchCoord, (float*)data, ref offset, ref size))
- throw new FlaxException("Failed to modify the heightmap.");
+ throw new Exception("Failed to modify the heightmap.");
}
}
}
diff --git a/Source/Editor/Tools/Terrain/Undo/EditTerrainHolesMapAction.cs b/Source/Editor/Tools/Terrain/Undo/EditTerrainHolesMapAction.cs
index 9f81f14ba..d8ebe425d 100644
--- a/Source/Editor/Tools/Terrain/Undo/EditTerrainHolesMapAction.cs
+++ b/Source/Editor/Tools/Terrain/Undo/EditTerrainHolesMapAction.cs
@@ -37,7 +37,7 @@ namespace FlaxEditor.Tools.Terrain.Undo
var offset = Int2.Zero;
var size = new Int2((int)Mathf.Sqrt(_heightmapLength));
if (TerrainTools.ModifyHolesMask(Terrain, ref patchCoord, (byte*)data, ref offset, ref size))
- throw new FlaxException("Failed to modify the terrain holes.");
+ throw new Exception("Failed to modify the terrain holes.");
}
}
}
diff --git a/Source/Editor/Tools/Terrain/Undo/EditTerrainSplatMapAction.cs b/Source/Editor/Tools/Terrain/Undo/EditTerrainSplatMapAction.cs
index b4b1d3e97..dfe6e553d 100644
--- a/Source/Editor/Tools/Terrain/Undo/EditTerrainSplatMapAction.cs
+++ b/Source/Editor/Tools/Terrain/Undo/EditTerrainSplatMapAction.cs
@@ -37,7 +37,7 @@ namespace FlaxEditor.Tools.Terrain.Undo
var offset = Int2.Zero;
var size = new Int2((int)Mathf.Sqrt(_heightmapLength));
if (TerrainTools.ModifySplatMap(Terrain, ref patchCoord, (int)tag, (Color32*)data, ref offset, ref size))
- throw new FlaxException("Failed to modify the splatmap.");
+ throw new Exception("Failed to modify the splatmap.");
}
}
}
diff --git a/Source/Editor/Undo/Actions/BreakPrefabLinkAction.cs b/Source/Editor/Undo/Actions/BreakPrefabLinkAction.cs
index a471c166b..d2db66792 100644
--- a/Source/Editor/Undo/Actions/BreakPrefabLinkAction.cs
+++ b/Source/Editor/Undo/Actions/BreakPrefabLinkAction.cs
@@ -68,7 +68,7 @@ namespace FlaxEditor.Actions
if (actor == null)
throw new ArgumentNullException(nameof(actor));
if (!actor.HasPrefabLink)
- throw new FlaxException("Cannot register missing prefab link.");
+ throw new Exception("Cannot register missing prefab link.");
return new BreakPrefabLinkAction(false, actor);
}
@@ -102,11 +102,11 @@ namespace FlaxEditor.Actions
private void DoLink()
{
if (_prefabObjectIds == null)
- throw new FlaxException("Cannot link prefab. Missing objects Ids mapping.");
+ throw new Exception("Cannot link prefab. Missing objects Ids mapping.");
var actor = Object.Find(ref _actorId);
if (actor == null)
- throw new FlaxException("Cannot link prefab. Missing actor.");
+ throw new Exception("Cannot link prefab. Missing actor.");
// Restore cached links
foreach (var e in _prefabObjectIds)
@@ -149,9 +149,9 @@ namespace FlaxEditor.Actions
{
var actor = Object.Find(ref _actorId);
if (actor == null)
- throw new FlaxException("Cannot break prefab link. Missing actor.");
+ throw new Exception("Cannot break prefab link. Missing actor.");
if (!actor.HasPrefabLink)
- throw new FlaxException("Cannot break missing prefab link.");
+ throw new Exception("Cannot break missing prefab link.");
if (_prefabObjectIds == null)
_prefabObjectIds = new Dictionary(1024);
diff --git a/Source/Editor/Utilities/DuplicateScenes.cs b/Source/Editor/Utilities/DuplicateScenes.cs
index 87a375e1b..e9ff1b6f9 100644
--- a/Source/Editor/Utilities/DuplicateScenes.cs
+++ b/Source/Editor/Utilities/DuplicateScenes.cs
@@ -72,7 +72,7 @@ namespace FlaxEditor.Utilities
if (Level.UnloadAllScenes())
{
Profiler.EndEvent();
- throw new FlaxException("Failed to unload scenes.");
+ throw new Exception("Failed to unload scenes.");
}
FlaxEngine.Scripting.FlushRemovedObjects();
@@ -82,7 +82,7 @@ namespace FlaxEditor.Utilities
if (noScenes != null && noScenes.Length != 0)
{
Profiler.EndEvent();
- throw new FlaxException("Failed to unload scenes.");
+ throw new Exception("Failed to unload scenes.");
}
}
@@ -110,7 +110,7 @@ namespace FlaxEditor.Utilities
if (scene == null)
{
Profiler.EndEvent();
- throw new FlaxException("Failed to deserialize scene");
+ throw new Exception("Failed to deserialize scene");
}
}
@@ -131,7 +131,7 @@ namespace FlaxEditor.Utilities
if (Level.UnloadAllScenes())
{
Profiler.EndEvent();
- throw new FlaxException("Failed to unload scenes.");
+ throw new Exception("Failed to unload scenes.");
}
FlaxEngine.Scripting.FlushRemovedObjects();
Profiler.EndEvent();
@@ -154,7 +154,7 @@ namespace FlaxEditor.Utilities
if (scene == null)
{
Profiler.EndEvent();
- throw new FlaxException("Failed to deserialize scene");
+ throw new Exception("Failed to deserialize scene");
}
// Restore `dirty` state
diff --git a/Source/Editor/Viewport/Previews/IESProfilePreview.cs b/Source/Editor/Viewport/Previews/IESProfilePreview.cs
index 9ed66c1bf..aaec77bc6 100644
--- a/Source/Editor/Viewport/Previews/IESProfilePreview.cs
+++ b/Source/Editor/Viewport/Previews/IESProfilePreview.cs
@@ -1,6 +1,8 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
+using System;
using FlaxEngine;
+using Object = FlaxEngine.Object;
namespace FlaxEditor.Viewport.Previews
{
@@ -39,7 +41,7 @@ namespace FlaxEditor.Viewport.Previews
// Wait for base (don't want to async material parameters set due to async loading)
if (baseMaterial == null || baseMaterial.WaitForLoaded())
- throw new FlaxException("Cannot load IES Profile preview material.");
+ throw new Exception("Cannot load IES Profile preview material.");
// Create preview material (virtual)
_previewMaterial = baseMaterial.CreateVirtualInstance();
diff --git a/Source/Editor/Viewport/Previews/PrefabPreview.cs b/Source/Editor/Viewport/Previews/PrefabPreview.cs
index c5ad97455..7f908c141 100644
--- a/Source/Editor/Viewport/Previews/PrefabPreview.cs
+++ b/Source/Editor/Viewport/Previews/PrefabPreview.cs
@@ -1,5 +1,6 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
+using System;
using FlaxEngine;
using Object = FlaxEngine.Object;
@@ -54,7 +55,7 @@ namespace FlaxEditor.Viewport.Previews
if (instance == null)
{
_prefab = null;
- throw new FlaxException("Failed to spawn a prefab for the preview.");
+ throw new Exception("Failed to spawn a prefab for the preview.");
}
// Set instance
diff --git a/Source/Editor/Viewport/Previews/TexturePreview.cs b/Source/Editor/Viewport/Previews/TexturePreview.cs
index 278fd6c2b..09e7016e5 100644
--- a/Source/Editor/Viewport/Previews/TexturePreview.cs
+++ b/Source/Editor/Viewport/Previews/TexturePreview.cs
@@ -319,10 +319,10 @@ namespace FlaxEditor.Viewport.Previews
// Create preview material (virtual)
var baseMaterial = FlaxEngine.Content.LoadAsyncInternal("Editor/TexturePreviewMaterial");
if (baseMaterial == null)
- throw new FlaxException("Cannot load texture preview material.");
+ throw new Exception("Cannot load texture preview material.");
_previewMaterial = baseMaterial.CreateVirtualInstance();
if (_previewMaterial == null)
- throw new FlaxException("Failed to create virtual material instance for preview material.");
+ throw new Exception("Failed to create virtual material instance for preview material.");
// Add widgets
if (useWidgets)
diff --git a/Source/Editor/Windows/OutputLogWindow.cs b/Source/Editor/Windows/OutputLogWindow.cs
index 1005bb136..b85a3f04c 100644
--- a/Source/Editor/Windows/OutputLogWindow.cs
+++ b/Source/Editor/Windows/OutputLogWindow.cs
@@ -482,7 +482,6 @@ namespace FlaxEditor.Windows
continue;
var startIndex = _textBuffer.Length;
-
switch (_timestampsFormats)
{
case InterfaceOptions.TimestampsFormats.Utc:
@@ -496,12 +495,12 @@ namespace FlaxEditor.Windows
_textBuffer.AppendFormat("[ {0:00}:{1:00}:{2:00}.{3:000} ]: ", diff.Hours, diff.Minutes, diff.Seconds, diff.Milliseconds);
break;
}
-
if (_showLogType)
{
_textBuffer.AppendFormat("[{0}] ", entry.Level);
}
+ var prefixLength = _textBuffer.Length - startIndex;
if (entry.Message.IndexOf('\r') != -1)
entry.Message = entry.Message.Replace("\r", "");
_textBuffer.Append(entry.Message);
@@ -548,27 +547,34 @@ namespace FlaxEditor.Windows
if (textBlock.Range.Length > 0)
{
// Parse compilation error/warning
- var match = _compileRegex.Match(entryText, line.FirstCharIndex, textBlock.Range.Length);
- if (match.Success)
+ var regexStart = line.FirstCharIndex;
+ if (j == 0)
+ regexStart += prefixLength;
+ var regexLength = line.LastCharIndex - regexStart;
+ if (regexLength > 0)
{
- switch (match.Groups["level"].Value)
+ var match = _compileRegex.Match(entryText, regexStart, regexLength);
+ if (match.Success)
{
- case "error":
- textBlock.Style = _output.ErrorStyle;
- break;
- case "warning":
- textBlock.Style = _output.WarningStyle;
- break;
+ switch (match.Groups["level"].Value)
+ {
+ case "error":
+ textBlock.Style = _output.ErrorStyle;
+ break;
+ case "warning":
+ textBlock.Style = _output.WarningStyle;
+ break;
+ }
+ textBlock.Tag = new TextBlockTag
+ {
+ Type = TextBlockTag.Types.CodeLocation,
+ Url = match.Groups["path"].Value,
+ Line = int.Parse(match.Groups["line"].Value),
+ };
}
- textBlock.Tag = new TextBlockTag
- {
- Type = TextBlockTag.Types.CodeLocation,
- Url = match.Groups["path"].Value,
- Line = int.Parse(match.Groups["line"].Value),
- };
+ // TODO: parsing hyperlinks with link
+ // TODO: parsing file paths with link
}
- // TODO: parsing hyperlinks with link
- // TODO: parsing file paths with link
}
prevBlockBottom += line.Size.Y;
diff --git a/Source/Editor/Windows/SceneTreeWindow.cs b/Source/Editor/Windows/SceneTreeWindow.cs
index 652cc2b6e..517f50252 100644
--- a/Source/Editor/Windows/SceneTreeWindow.cs
+++ b/Source/Editor/Windows/SceneTreeWindow.cs
@@ -326,7 +326,7 @@ namespace FlaxEditor.Windows
_isUpdatingSelection = false;
}
-
+
private bool ValidateDragAsset(AssetItem assetItem)
{
return assetItem.OnEditorDrag(this);
@@ -417,7 +417,7 @@ namespace FlaxEditor.Windows
public override DragDropEffect OnDragEnter(ref Vector2 location, DragData data)
{
var result = base.OnDragEnter(ref location, data);
- if (result == DragDropEffect.None && Editor.StateMachine.CurrentState.CanEditScene)
+ if (Editor.StateMachine.CurrentState.CanEditScene)
{
if (_dragHandlers == null)
_dragHandlers = new DragHandlers();
@@ -426,14 +426,14 @@ namespace FlaxEditor.Windows
_dragAssets = new DragAssets(ValidateDragAsset);
_dragHandlers.Add(_dragAssets);
}
- if (_dragAssets.OnDragEnter(data))
+ if (_dragAssets.OnDragEnter(data) && result == DragDropEffect.None)
return _dragAssets.Effect;
if (_dragActorType == null)
{
_dragActorType = new DragActorType(ValidateDragActorType);
_dragHandlers.Add(_dragActorType);
}
- if (_dragActorType.OnDragEnter(data))
+ if (_dragActorType.OnDragEnter(data) && result == DragDropEffect.None)
return _dragActorType.Effect;
}
return result;
diff --git a/Source/Engine/Content/JsonAsset.cpp b/Source/Engine/Content/JsonAsset.cpp
index e8aa901d9..2332181b9 100644
--- a/Source/Engine/Content/JsonAsset.cpp
+++ b/Source/Engine/Content/JsonAsset.cpp
@@ -281,9 +281,10 @@ bool JsonAsset::CreateInstance()
void JsonAsset::DeleteInstance()
{
- ASSERT_LOW_LAYER(Instance && _dtor);
- InstanceType = ScriptingTypeHandle();
+ if (!Instance || !_dtor)
+ return;
_dtor(Instance);
+ InstanceType = ScriptingTypeHandle();
Allocator::Free(Instance);
Instance = nullptr;
_dtor = nullptr;
diff --git a/Source/Engine/Engine/FlaxException.cs b/Source/Engine/Engine/FlaxException.cs
deleted file mode 100644
index 147b00c4c..000000000
--- a/Source/Engine/Engine/FlaxException.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
-
-using System;
-
-namespace FlaxEngine
-{
- ///
- /// Flax exception object.
- ///
- ///
- [Serializable]
- public class FlaxException : SystemException
- {
- ///
- /// Initializes a new instance of the class.
- ///
- public FlaxException()
- : base("A Flax runtime error occurred!")
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The message that describes the error.
- public FlaxException(string message)
- : base(message)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The error message that explains the reason for the exception.
- /// The exception that is the cause of the current exception. If the parameter is not a null reference (Nothing in Visual Basic), the current exception is raised in a catch block that handles the inner exception.
- public FlaxException(string message, Exception innerException)
- : base(message, innerException)
- {
- }
- }
-}
diff --git a/Source/Engine/Graphics/Mesh.cs b/Source/Engine/Graphics/Mesh.cs
index 2cdcc73b1..25129137c 100644
--- a/Source/Engine/Graphics/Mesh.cs
+++ b/Source/Engine/Graphics/Mesh.cs
@@ -154,7 +154,7 @@ namespace FlaxEngine
uv,
colors
))
- throw new FlaxException("Failed to update mesh data.");
+ throw new Exception("Failed to update mesh data.");
}
///
@@ -201,7 +201,7 @@ namespace FlaxEngine
Utils.ExtractArrayFromList(uv),
Utils.ExtractArrayFromList(colors)
))
- throw new FlaxException("Failed to update mesh data.");
+ throw new Exception("Failed to update mesh data.");
}
///
@@ -247,7 +247,7 @@ namespace FlaxEngine
uv,
colors
))
- throw new FlaxException("Failed to update mesh data.");
+ throw new Exception("Failed to update mesh data.");
}
///
@@ -294,7 +294,7 @@ namespace FlaxEngine
Utils.ExtractArrayFromList(uv),
Utils.ExtractArrayFromList(colors)
))
- throw new FlaxException("Failed to update mesh data.");
+ throw new Exception("Failed to update mesh data.");
}
///
@@ -341,7 +341,7 @@ namespace FlaxEngine
uv,
colors
))
- throw new FlaxException("Failed to update mesh data.");
+ throw new Exception("Failed to update mesh data.");
}
///
@@ -388,7 +388,7 @@ namespace FlaxEngine
Utils.ExtractArrayFromList(uv),
Utils.ExtractArrayFromList(colors)
))
- throw new FlaxException("Failed to update mesh data.");
+ throw new Exception("Failed to update mesh data.");
}
///
@@ -412,7 +412,7 @@ namespace FlaxEngine
triangles.Length / 3,
triangles
))
- throw new FlaxException("Failed to update mesh data.");
+ throw new Exception("Failed to update mesh data.");
}
///
@@ -436,7 +436,7 @@ namespace FlaxEngine
triangles.Count / 3,
Utils.ExtractArrayFromList(triangles)
))
- throw new FlaxException("Failed to update mesh data.");
+ throw new Exception("Failed to update mesh data.");
}
///
@@ -460,7 +460,7 @@ namespace FlaxEngine
triangles.Length / 3,
triangles
))
- throw new FlaxException("Failed to update mesh data.");
+ throw new Exception("Failed to update mesh data.");
}
///
@@ -484,7 +484,7 @@ namespace FlaxEngine
triangles.Count / 3,
Utils.ExtractArrayFromList(triangles)
))
- throw new FlaxException("Failed to update mesh data.");
+ throw new Exception("Failed to update mesh data.");
}
internal enum InternalBufferType
@@ -506,7 +506,7 @@ namespace FlaxEngine
var vertices = VertexCount;
var result = new Vertex0[vertices];
if (Internal_DownloadBuffer(__unmanagedPtr, forceGpu, result, (int)InternalBufferType.VB0))
- throw new FlaxException("Failed to download mesh data.");
+ throw new Exception("Failed to download mesh data.");
return result;
}
@@ -520,7 +520,7 @@ namespace FlaxEngine
var vertices = VertexCount;
var result = new Vertex1[vertices];
if (Internal_DownloadBuffer(__unmanagedPtr, forceGpu, result, (int)InternalBufferType.VB1))
- throw new FlaxException("Failed to download mesh data.");
+ throw new Exception("Failed to download mesh data.");
return result;
}
@@ -540,7 +540,7 @@ namespace FlaxEngine
var vertices = VertexCount;
var result = new Vertex2[vertices];
if (Internal_DownloadBuffer(__unmanagedPtr, forceGpu, result, (int)InternalBufferType.VB2))
- throw new FlaxException("Failed to download mesh data.");
+ throw new Exception("Failed to download mesh data.");
return result;
}
@@ -597,7 +597,7 @@ namespace FlaxEngine
var triangles = TriangleCount;
var result = new uint[triangles * 3];
if (Internal_DownloadBuffer(__unmanagedPtr, forceGpu, result, (int)InternalBufferType.IB32))
- throw new FlaxException("Failed to download mesh data.");
+ throw new Exception("Failed to download mesh data.");
return result;
}
@@ -612,7 +612,7 @@ namespace FlaxEngine
var triangles = TriangleCount;
var result = new ushort[triangles * 3];
if (Internal_DownloadBuffer(__unmanagedPtr, forceGpu, result, (int)InternalBufferType.IB16))
- throw new FlaxException("Failed to download mesh data.");
+ throw new Exception("Failed to download mesh data.");
return result;
}
}
diff --git a/Source/Engine/Graphics/SkinnedMesh.cs b/Source/Engine/Graphics/SkinnedMesh.cs
index d59f619a7..5ccb25e46 100644
--- a/Source/Engine/Graphics/SkinnedMesh.cs
+++ b/Source/Engine/Graphics/SkinnedMesh.cs
@@ -131,7 +131,7 @@ namespace FlaxEngine
throw new ArgumentOutOfRangeException(nameof(uv));
if (Internal_UpdateMeshUInt(__unmanagedPtr, vertices, triangles, blendIndices, blendWeights, normals, tangents, uv))
- throw new FlaxException("Failed to update mesh data.");
+ throw new Exception("Failed to update mesh data.");
}
///
@@ -167,7 +167,7 @@ namespace FlaxEngine
throw new ArgumentOutOfRangeException(nameof(uv));
if (Internal_UpdateMeshUInt(__unmanagedPtr, vertices, triangles, blendIndices, blendWeights, normals, tangents, uv))
- throw new FlaxException("Failed to update mesh data.");
+ throw new Exception("Failed to update mesh data.");
}
///
@@ -203,7 +203,7 @@ namespace FlaxEngine
throw new ArgumentOutOfRangeException(nameof(uv));
if (Internal_UpdateMeshUShort(__unmanagedPtr, vertices, triangles, blendIndices, blendWeights, normals, tangents, uv))
- throw new FlaxException("Failed to update mesh data.");
+ throw new Exception("Failed to update mesh data.");
}
internal enum InternalBufferType
@@ -223,7 +223,7 @@ namespace FlaxEngine
var vertices = VertexCount;
var result = new Vertex0[vertices];
if (Internal_DownloadBuffer(__unmanagedPtr, forceGpu, result, (int)InternalBufferType.VB0))
- throw new FlaxException("Failed to download mesh data.");
+ throw new Exception("Failed to download mesh data.");
return result;
}
@@ -268,7 +268,7 @@ namespace FlaxEngine
var triangles = TriangleCount;
var result = new uint[triangles * 3];
if (Internal_DownloadBuffer(__unmanagedPtr, forceGpu, result, (int)InternalBufferType.IB32))
- throw new FlaxException("Failed to download mesh data.");
+ throw new Exception("Failed to download mesh data.");
return result;
}
@@ -283,7 +283,7 @@ namespace FlaxEngine
var triangles = TriangleCount;
var result = new ushort[triangles * 3];
if (Internal_DownloadBuffer(__unmanagedPtr, forceGpu, result, (int)InternalBufferType.IB16))
- throw new FlaxException("Failed to download mesh data.");
+ throw new Exception("Failed to download mesh data.");
return result;
}
}
diff --git a/Source/Engine/Graphics/TextureBase.cs b/Source/Engine/Graphics/TextureBase.cs
index 63f17cc09..19ae402d7 100644
--- a/Source/Engine/Graphics/TextureBase.cs
+++ b/Source/Engine/Graphics/TextureBase.cs
@@ -177,7 +177,7 @@ namespace FlaxEngine
// Call backend
if (Internal_Init(__unmanagedPtr, new IntPtr(&t)))
- throw new FlaxException("Failed to init texture data.");
+ throw new Exception("Failed to init texture data.");
}
}
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp
index b0cfb30f8..1b08c06ec 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp
+++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp
@@ -266,6 +266,20 @@ bool GPUDeviceDX11::Init()
}
UpdateOutputs(adapter);
+ ComPtr factory5;
+ _factoryDXGI->QueryInterface(IID_PPV_ARGS(&factory5));
+ if (factory5)
+ {
+ BOOL allowTearing;
+ if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing)))
+ && allowTearing
+#if PLATFORM_WINDOWS
+ && GetModuleHandleA("renderdoc.dll") == nullptr // Disable tearing with RenderDoc (prevents crashing)
+#endif
+ )
+ AllowTearing = true;
+ }
+
// Get flags and device type base on current configuration
uint32 flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#if GPU_ENABLE_DIAGNOSTICS
@@ -276,18 +290,7 @@ bool GPUDeviceDX11::Init()
// Create DirectX device
D3D_FEATURE_LEVEL createdFeatureLevel = static_cast(0);
auto targetFeatureLevel = GetD3DFeatureLevel();
- VALIDATE_DIRECTX_RESULT(D3D11CreateDevice(
- adapter,
- D3D_DRIVER_TYPE_UNKNOWN,
- NULL,
- flags,
- &targetFeatureLevel,
- 1,
- D3D11_SDK_VERSION,
- &_device,
- &createdFeatureLevel,
- &_imContext
- ));
+ VALIDATE_DIRECTX_RESULT(D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, flags, &targetFeatureLevel, 1, D3D11_SDK_VERSION, &_device, &createdFeatureLevel, &_imContext));
// Validate result
ASSERT(_device);
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h
index de0132ea3..ec2ba0177 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h
+++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h
@@ -50,6 +50,10 @@ public:
GPUDeviceDX11(IDXGIFactory* dxgiFactory, GPUAdapterDX* adapter);
~GPUDeviceDX11();
+public:
+
+ bool AllowTearing = false;
+
public:
// Gets DX11 device
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.cpp
index 56fcfcc77..2986a15fd 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.cpp
+++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.cpp
@@ -17,6 +17,8 @@ GPUSwapChainDX11::GPUSwapChainDX11(GPUDeviceDX11* device, Window* window)
#endif
, _swapChain(nullptr)
, _backBuffer(nullptr)
+ , _allowTearing(false)
+ , _isFullscreen(false)
{
ASSERT(_windowHandle);
_window = window;
@@ -108,6 +110,18 @@ void GPUSwapChainDX11::SetFullscreen(bool isFullscreen)
{
LOG(Warning, "Cannot change fullscreen mode for '{0}' to {1}.", ToString(), isFullscreen);
}
+
+ _isFullscreen = isFullscreen;
+
+ // Buffers must be resized in flip presentation model
+ if (swapChainDesc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL ||
+ swapChainDesc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD)
+ {
+ const int32 width = _width;
+ const int32 height = _height;
+ _width = _height = 0;
+ Resize(width, height);
+ }
}
#else
LOG(Info, "Cannot change fullscreen mode on this platform");
@@ -123,7 +137,14 @@ void GPUSwapChainDX11::Present(bool vsync)
{
// Present frame
ASSERT(_swapChain);
- const HRESULT result = _swapChain->Present(vsync ? 1 : 0, 0);
+ UINT presentFlags = 0;
+#if PLATFORM_WINDOWS
+ if (!vsync && !_isFullscreen && _allowTearing)
+ {
+ presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
+ }
+#endif
+ const HRESULT result = _swapChain->Present(vsync ? 1 : 0, presentFlags);
LOG_DIRECTX_RESULT(result);
// Base
@@ -140,6 +161,9 @@ bool GPUSwapChainDX11::Resize(int32 width, int32 height)
_device->WaitForGPU();
GPUDeviceLock lock(_device);
+#if PLATFORM_WINDOWS
+ _allowTearing = _device->AllowTearing;
+#endif
_format = GPU_BACK_BUFFER_PIXEL_FORMAT;
#if PLATFORM_WINDOWS
@@ -177,6 +201,11 @@ bool GPUSwapChainDX11::Resize(int32 width, int32 height)
swapChainDesc.Windowed = TRUE;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+ if (_allowTearing)
+ {
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
+ swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
+ }
#else
swapChainDesc.Width = width;
swapChainDesc.Height = height;
@@ -202,7 +231,7 @@ bool GPUSwapChainDX11::Resize(int32 width, int32 height)
ASSERT(_swapChain);
// Disable DXGI changes to the window
- VALIDATE_DIRECTX_RESULT(dxgi->MakeWindowAssociation(_windowHandle, 0));
+ VALIDATE_DIRECTX_RESULT(dxgi->MakeWindowAssociation(_windowHandle, DXGI_MWA_NO_ALT_ENTER));
#else
auto dxgiFactory = (IDXGIFactory2*)_device->GetDXGIFactory();
VALIDATE_DIRECTX_RESULT(dxgiFactory->CreateSwapChainForCoreWindow(_device->GetDevice(), static_cast(_windowHandle), &swapChainDesc, nullptr, &_swapChain));
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.h b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.h
index f0a785930..35688affc 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.h
+++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUSwapChainDX11.h
@@ -23,6 +23,7 @@ private:
#if PLATFORM_WINDOWS
HWND _windowHandle;
IDXGISwapChain* _swapChain;
+ bool _allowTearing, _isFullscreen;
#else
IUnknown* _windowHandle;
IDXGISwapChain1* _swapChain;
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp
index 5aae0febf..3483b5e4e 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp
+++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp
@@ -264,17 +264,19 @@ bool GPUDeviceDX12::Init()
return true;
}
UpdateOutputs(adapter);
+
+ ComPtr factory5;
+ _factoryDXGI->QueryInterface(IID_PPV_ARGS(&factory5));
+ if (factory5)
{
- ComPtr factory5;
- _factoryDXGI->QueryInterface(IID_PPV_ARGS(&factory5));
- if (factory5)
- {
- BOOL allowTearing;
- if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing))) && allowTearing)
- {
- AllowTearing = true;
- }
- }
+ BOOL allowTearing;
+ if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing)))
+ && allowTearing
+#if PLATFORM_WINDOWS
+ && GetModuleHandleA("renderdoc.dll") == nullptr // Disable tearing with RenderDoc (prevents crashing)
+#endif
+ )
+ AllowTearing = true;
}
// Create DirectX device
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUSwapChainDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUSwapChainDX12.cpp
index f4784f479..e7e976987 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUSwapChainDX12.cpp
+++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUSwapChainDX12.cpp
@@ -51,6 +51,8 @@ GPUSwapChainDX12::GPUSwapChainDX12(GPUDeviceDX12* device, Window* window)
, _windowHandle(static_cast(window->GetNativePtr()))
, _swapChain(nullptr)
, _currentFrameIndex(0)
+ , _allowTearing(false)
+ , _isFullscreen(false)
{
ASSERT(_windowHandle);
_window = window;
@@ -135,6 +137,16 @@ void GPUSwapChainDX12::SetFullscreen(bool isFullscreen)
}
_isFullscreen = isFullscreen;
+
+ // Buffers must be resized in flip presentation model
+ if (swapChainDesc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL ||
+ swapChainDesc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD)
+ {
+ const int32 width = _width;
+ const int32 height = _height;
+ _width = _height = 0;
+ Resize(width, height);
+ }
}
#else
LOG(Info, "Cannot change fullscreen mode on this platform");
@@ -217,7 +229,7 @@ bool GPUSwapChainDX12::Resize(int32 width, int32 height)
_backBuffers.Resize(swapChainDesc.BufferCount);
// Disable DXGI changes to the window
- dxgiFactory->MakeWindowAssociation(_windowHandle, 0);
+ VALIDATE_DIRECTX_RESULT(dxgiFactory->MakeWindowAssociation(_windowHandle, DXGI_MWA_NO_ALT_ENTER));
}
else
{
diff --git a/Source/Engine/GraphicsDevice/DirectX/IncludeDirectXHeaders.h b/Source/Engine/GraphicsDevice/DirectX/IncludeDirectXHeaders.h
index ca4dae608..7cf4be599 100644
--- a/Source/Engine/GraphicsDevice/DirectX/IncludeDirectXHeaders.h
+++ b/Source/Engine/GraphicsDevice/DirectX/IncludeDirectXHeaders.h
@@ -39,6 +39,7 @@ typedef IGraphicsUnknown IDXGISwapChain3;
#include
#include
#include
+#include
#endif
#if GRAPHICS_API_DIRECTX12
#include
diff --git a/Source/Engine/Level/Actor.cpp b/Source/Engine/Level/Actor.cpp
index 72c35da56..a80c3ceed 100644
--- a/Source/Engine/Level/Actor.cpp
+++ b/Source/Engine/Level/Actor.cpp
@@ -1358,7 +1358,7 @@ bool Actor::HasActorInChildren(Actor* a) const
bool Actor::IntersectsItself(const Ray& ray, float& distance, Vector3& normal)
{
- return GetBox().Intersects(ray, distance, normal);
+ return _box.Intersects(ray, distance, normal);
}
Actor* Actor::Intersects(const Ray& ray, float& distance, Vector3& normal)
diff --git a/Source/Engine/Level/Actors/AnimatedModel.cpp b/Source/Engine/Level/Actors/AnimatedModel.cpp
index e2d5a5668..3ddfdd3a1 100644
--- a/Source/Engine/Level/Actors/AnimatedModel.cpp
+++ b/Source/Engine/Level/Actors/AnimatedModel.cpp
@@ -76,7 +76,8 @@ void AnimatedModel::SetupSkinningData()
void AnimatedModel::PreInitSkinningData()
{
- ASSERT(SkinnedModel && SkinnedModel->IsLoaded());
+ if (!SkinnedModel || !SkinnedModel->IsLoaded())
+ return;
ScopeLock lock(SkinnedModel->Locker);
diff --git a/Source/Engine/Physics/Actors/PhysicsActor.cpp b/Source/Engine/Physics/Actors/PhysicsActor.cpp
deleted file mode 100644
index 120d83bc4..000000000
--- a/Source/Engine/Physics/Actors/PhysicsActor.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
-
-#include "PhysicsActor.h"
-#include "../PhysicsBackend.h"
-
-PhysicsActor::PhysicsActor(const SpawnParams& params)
- : Actor(params)
- , _cachedScale(1.0f)
- , _isUpdatingTransform(false)
-{
-}
-
-void PhysicsActor::OnActiveTransformChanged()
-{
- // Change actor transform (but with locking)
- ASSERT(!_isUpdatingTransform);
- _isUpdatingTransform = true;
- Transform transform;
- PhysicsBackend::GetRigidActorPose(GetPhysicsActor(), transform.Translation, transform.Orientation);
- transform.Scale = _transform.Scale;
- if (_parent)
- {
- _parent->GetTransform().WorldToLocal(transform, _localTransform);
- }
- else
- {
- _localTransform = transform;
- }
- OnTransformChanged();
- _isUpdatingTransform = false;
-}
-
-void PhysicsActor::OnTransformChanged()
-{
- // Base
- Actor::OnTransformChanged();
-
- UpdateBounds();
-}
-
-void PhysicsActor::UpdateBounds()
-{
- void* actor = GetPhysicsActor();
- if (actor)
- PhysicsBackend::GetActorBounds(actor, _box);
- else
- _box = BoundingBox(_transform.Translation);
- BoundingSphere::FromBox(_box, _sphere);
-}
-
-bool PhysicsActor::IntersectsItself(const Ray& ray, float& distance, Vector3& normal)
-{
- return _box.Intersects(ray, distance, normal);
-}
diff --git a/Source/Engine/Physics/Actors/PhysicsActor.h b/Source/Engine/Physics/Actors/PhysicsActor.h
deleted file mode 100644
index 961c07eee..000000000
--- a/Source/Engine/Physics/Actors/PhysicsActor.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
-
-#pragma once
-
-#include "Engine/Level/Actor.h"
-#include "Engine/Physics/Types.h"
-#include "IPhysicsActor.h"
-
-///
-/// A base class for all physical actors.
-///
-///
-API_CLASS(Abstract) class FLAXENGINE_API PhysicsActor : public Actor, public IPhysicsActor
-{
-DECLARE_SCENE_OBJECT_ABSTRACT(PhysicsActor);
-protected:
-
- Vector3 _cachedScale;
- bool _isUpdatingTransform;
-
-public:
-
- ///
- /// Updates the bounding box.
- ///
- void UpdateBounds();
-
-public:
-
- // [Actor]
- bool IntersectsItself(const Ray& ray, float& distance, Vector3& normal) override;
-
- // [IPhysicsActor]
- void OnActiveTransformChanged() override;
-
-protected:
-
- // [Actor]
- void OnTransformChanged() override;
-};
diff --git a/Source/Engine/Physics/Actors/RigidBody.cpp b/Source/Engine/Physics/Actors/RigidBody.cpp
index 193422c0c..26512fb61 100644
--- a/Source/Engine/Physics/Actors/RigidBody.cpp
+++ b/Source/Engine/Physics/Actors/RigidBody.cpp
@@ -8,8 +8,9 @@
#include "Engine/Serialization/Serialization.h"
RigidBody::RigidBody(const SpawnParams& params)
- : PhysicsActor(params)
+ : Actor(params)
, _actor(nullptr)
+ , _cachedScale(1.0f)
, _mass(1.0f)
, _linearDamping(0.01f)
, _angularDamping(0.05f)
@@ -24,6 +25,7 @@ RigidBody::RigidBody(const SpawnParams& params)
, _startAwake(true)
, _updateMassWhenScaleChanges(false)
, _overrideMass(false)
+ , _isUpdatingTransform(false)
{
}
@@ -224,13 +226,13 @@ bool RigidBody::IsSleeping() const
void RigidBody::Sleep() const
{
if (_actor && GetEnableSimulation() && !GetIsKinematic() && IsActiveInHierarchy())
- PhysicsBackend::GetRigidActorSleep(_actor);
+ PhysicsBackend::RigidDynamicActorSleep(_actor);
}
void RigidBody::WakeUp() const
{
if (_actor && GetEnableSimulation() && !GetIsKinematic() && IsActiveInHierarchy())
- PhysicsBackend::GetRigidDynamicActorWakeUp(_actor);
+ PhysicsBackend::RigidDynamicActorWakeUp(_actor);
}
void RigidBody::UpdateMass()
@@ -323,6 +325,16 @@ void RigidBody::OnColliderChanged(Collider* c)
// WakeUp();
}
+void RigidBody::UpdateBounds()
+{
+ void* actor = GetPhysicsActor();
+ if (actor && PhysicsBackend::GetRigidActorShapesCount(actor) != 0)
+ PhysicsBackend::GetActorBounds(actor, _box);
+ else
+ _box = BoundingBox(_transform.Translation);
+ BoundingSphere::FromBox(_box, _sphere);
+}
+
void RigidBody::UpdateScale()
{
const Vector3 scale = GetScale();
@@ -339,7 +351,7 @@ void RigidBody::UpdateScale()
void RigidBody::Serialize(SerializeStream& stream, const void* otherObj)
{
// Base
- PhysicsActor::Serialize(stream, otherObj);
+ Actor::Serialize(stream, otherObj);
SERIALIZE_GET_OTHER_OBJ(RigidBody);
@@ -364,7 +376,7 @@ void RigidBody::Serialize(SerializeStream& stream, const void* otherObj)
void RigidBody::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
{
// Base
- PhysicsActor::Deserialize(stream, modifier);
+ Actor::Deserialize(stream, modifier);
DESERIALIZE_BIT_MEMBER(OverrideMass, _overrideMass);
DESERIALIZE_MEMBER(Mass, _mass);
@@ -389,6 +401,26 @@ void* RigidBody::GetPhysicsActor() const
return _actor;
}
+void RigidBody::OnActiveTransformChanged()
+{
+ // Change actor transform (but with locking)
+ ASSERT(!_isUpdatingTransform);
+ _isUpdatingTransform = true;
+ Transform transform;
+ PhysicsBackend::GetRigidActorPose(GetPhysicsActor(), transform.Translation, transform.Orientation);
+ transform.Scale = _transform.Scale;
+ if (_parent)
+ {
+ _parent->GetTransform().WorldToLocal(transform, _localTransform);
+ }
+ else
+ {
+ _localTransform = transform;
+ }
+ OnTransformChanged();
+ _isUpdatingTransform = false;
+}
+
void RigidBody::BeginPlay(SceneBeginData* data)
{
// Create rigid body
@@ -441,13 +473,13 @@ void RigidBody::BeginPlay(SceneBeginData* data)
UpdateBounds();
// Base
- PhysicsActor::BeginPlay(data);
+ Actor::BeginPlay(data);
}
void RigidBody::EndPlay()
{
// Base
- PhysicsActor::EndPlay();
+ Actor::EndPlay();
if (_actor)
{
@@ -462,7 +494,7 @@ void RigidBody::EndPlay()
void RigidBody::OnActiveInTreeChanged()
{
// Base
- PhysicsActor::OnActiveInTreeChanged();
+ Actor::OnActiveInTreeChanged();
if (_actor)
{
@@ -480,23 +512,18 @@ void RigidBody::OnActiveInTreeChanged()
void RigidBody::OnTransformChanged()
{
+ // Base
+ Actor::OnTransformChanged();
+
// Update physics is not during physics state synchronization
if (!_isUpdatingTransform && _actor)
{
- // Base (skip PhysicsActor call to optimize)
- Actor::OnTransformChanged();
-
const bool kinematic = GetIsKinematic() && GetEnableSimulation();
PhysicsBackend::SetRigidActorPose(_actor, _transform.Translation, _transform.Orientation, kinematic, true);
-
UpdateScale();
- UpdateBounds();
- }
- else
- {
- // Base
- PhysicsActor::OnTransformChanged();
}
+
+ UpdateBounds();
}
void RigidBody::OnPhysicsSceneChanged(PhysicsScene* previous)
diff --git a/Source/Engine/Physics/Actors/RigidBody.h b/Source/Engine/Physics/Actors/RigidBody.h
index 557ac55be..bbe30fe08 100644
--- a/Source/Engine/Physics/Actors/RigidBody.h
+++ b/Source/Engine/Physics/Actors/RigidBody.h
@@ -2,7 +2,9 @@
#pragma once
-#include "PhysicsActor.h"
+#include "Engine/Level/Actor.h"
+#include "Engine/Physics/Types.h"
+#include "Engine/Physics/Actors/IPhysicsActor.h"
#include "Engine/Physics/Collisions.h"
class PhysicsColliderActor;
@@ -11,8 +13,8 @@ class Collider;
///
/// Physics simulation driven object.
///
-///
-API_CLASS() class FLAXENGINE_API RigidBody : public PhysicsActor
+///
+API_CLASS() class FLAXENGINE_API RigidBody : public Actor, public IPhysicsActor
{
DECLARE_SCENE_OBJECT(RigidBody);
protected:
@@ -35,6 +37,7 @@ protected:
int32 _startAwake : 1;
int32 _updateMassWhenScaleChanges : 1;
int32 _overrideMass : 1;
+ int32 _isUpdatingTransform : 1;
public:
@@ -537,7 +540,10 @@ public:
// Called when collider gets detached from this rigidbody or activated/deactivated. Used to update rigidbody mass.
virtual void OnColliderChanged(Collider* c);
-protected:
+ ///
+ /// Updates the bounding box.
+ ///
+ void UpdateBounds();
///
/// Updates the rigidbody scale dependent properties like mass (may be modified when actor transformation changes).
@@ -546,14 +552,17 @@ protected:
public:
- // [PhysicsActor]
+ // [Actor]
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
+
+ // [IPhysicsActor]
void* GetPhysicsActor() const override;
+ void OnActiveTransformChanged() override;
protected:
- // [PhysicsActor]
+ // [Actor]
void BeginPlay(SceneBeginData* data) override;
void EndPlay() override;
void OnActiveInTreeChanged() override;
diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
index c1a08210d..256e48d5f 100644
--- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
+++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
@@ -1607,6 +1607,12 @@ void PhysicsBackend::GetActorBounds(void* actor, BoundingBox& bounds)
bounds = P2C(actorPhysX->getWorldBounds(boundsScale));
}
+int32 PhysicsBackend::GetRigidActorShapesCount(void* actor)
+{
+ auto actorPhysX = (PxRigidActor*)actor;
+ return actorPhysX->getNbShapes();
+}
+
void* PhysicsBackend::CreateRigidDynamicActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation)
{
const PxTransform trans(C2P(position), C2P(orientation));
@@ -1749,13 +1755,13 @@ bool PhysicsBackend::GetRigidDynamicActorIsSleeping(void* actor)
return actorPhysX->isSleeping();
}
-void PhysicsBackend::GetRigidActorSleep(void* actor)
+void PhysicsBackend::RigidDynamicActorSleep(void* actor)
{
auto actorPhysX = (PxRigidDynamic*)actor;
actorPhysX->putToSleep();
}
-void PhysicsBackend::GetRigidDynamicActorWakeUp(void* actor)
+void PhysicsBackend::RigidDynamicActorWakeUp(void* actor)
{
auto actorPhysX = (PxRigidDynamic*)actor;
actorPhysX->wakeUp();
diff --git a/Source/Engine/Physics/PhysicsBackend.h b/Source/Engine/Physics/PhysicsBackend.h
index 4c50e9ea0..980387bcb 100644
--- a/Source/Engine/Physics/PhysicsBackend.h
+++ b/Source/Engine/Physics/PhysicsBackend.h
@@ -131,6 +131,7 @@ public:
static ActorFlags GetActorFlags(void* actor);
static void SetActorFlags(void* actor, ActorFlags value);
static void GetActorBounds(void* actor, BoundingBox& bounds);
+ static int32 GetRigidActorShapesCount(void* actor);
static void* CreateRigidDynamicActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation);
static void* CreateRigidStaticActor(IPhysicsActor* actor, const Vector3& position, const Quaternion& orientation);
static RigidDynamicFlags GetRigidDynamicActorFlags(void* actor);
@@ -148,8 +149,8 @@ public:
static Vector3 GetRigidDynamicActorCenterOfMass(void* actor);
static void SetRigidDynamicActorCenterOfMassOffset(void* actor, const Vector3& value);
static bool GetRigidDynamicActorIsSleeping(void* actor);
- static void GetRigidActorSleep(void* actor);
- static void GetRigidDynamicActorWakeUp(void* actor);
+ static void RigidDynamicActorSleep(void* actor);
+ static void RigidDynamicActorWakeUp(void* actor);
static float GetRigidDynamicActorSleepThreshold(void* actor);
static void SetRigidDynamicActorSleepThreshold(void* actor, float value);
static float GetRigidDynamicActorMaxDepenetrationVelocity(void* actor);
diff --git a/Source/Engine/Platform/Windows/WindowsWindow.cpp b/Source/Engine/Platform/Windows/WindowsWindow.cpp
index 50f092407..cb1617219 100644
--- a/Source/Engine/Platform/Windows/WindowsWindow.cpp
+++ b/Source/Engine/Platform/Windows/WindowsWindow.cpp
@@ -1031,6 +1031,10 @@ LRESULT WindowsWindow::WndProc(UINT msg, WPARAM wParam, LPARAM lParam)
// In this case, we don't resize yet -- we wait until the user stops dragging, and a WM_EXITSIZEMOVE message comes.
UpdateRegion();
}
+ else if (_isSwitchingFullScreen)
+ {
+ // Ignored
+ }
else
{
// This WM_SIZE come from resizing the window via an API like SetWindowPos() so resize
@@ -1090,6 +1094,12 @@ LRESULT WindowsWindow::WndProc(UINT msg, WPARAM wParam, LPARAM lParam)
Close(ClosingReason::User);
return 0;
}
+ if (wParam == VK_RETURN)
+ {
+ LOG(Info, "Alt+Enter pressed");
+ SetIsFullscreen(!IsFullscreen());
+ return 0;
+ }
break;
case WM_POWERBROADCAST:
switch (wParam)
diff --git a/Source/Engine/Render2D/Render2D.cpp b/Source/Engine/Render2D/Render2D.cpp
index 779746d8d..8c6760ba8 100644
--- a/Source/Engine/Render2D/Render2D.cpp
+++ b/Source/Engine/Render2D/Render2D.cpp
@@ -1331,7 +1331,7 @@ void Render2D::DrawText(Font* font, const StringView& text, const Color& color,
{
// Calculate character size and atlas coordinates
const float x = pointer.X + entry.OffsetX * scale;
- const float y = pointer.Y + (font->GetHeight() + font->GetDescender() - entry.OffsetY) * scale;
+ const float y = pointer.Y - entry.OffsetY * scale + Math::Ceil((font->GetHeight() + font->GetDescender()) * scale);
Rectangle charRect(x, y, entry.UVSize.X * scale, entry.UVSize.Y * scale);
charRect.Offset(layout.Bounds.Location);
diff --git a/Source/Engine/Renderer/Renderer.cpp b/Source/Engine/Renderer/Renderer.cpp
index 3cb7d5f0a..7738fec45 100644
--- a/Source/Engine/Renderer/Renderer.cpp
+++ b/Source/Engine/Renderer/Renderer.cpp
@@ -541,7 +541,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext)
renderContext.List->RunMaterialPostFxPass(context, renderContext, MaterialPostFxLocation::AfterAntiAliasingPass, frameBuffer, tempBuffer);
// PostFx -> (up-scaling) -> Back Buffer
- if (Math::IsOne(task->RenderingPercentage))
+ if (task->RenderingPercentage >= 1.0f)
{
PROFILE_GPU("Copy frame");
context->SetRenderTarget(task->GetOutputView());
diff --git a/Source/Engine/Scripting/BinaryModule.h b/Source/Engine/Scripting/BinaryModule.h
index 5ea3713c5..73144c449 100644
--- a/Source/Engine/Scripting/BinaryModule.h
+++ b/Source/Engine/Scripting/BinaryModule.h
@@ -260,7 +260,7 @@ public:
private:
- int32 _firstManagedTypeIndex;
+ int32 _firstManagedTypeIndex = 0;
Array _managedMemoryBlocks;
public:
diff --git a/Source/Engine/Scripting/ManagedCLR/MAssembly.cpp b/Source/Engine/Scripting/ManagedCLR/MAssembly.cpp
index 8471f02cb..996bbb420 100644
--- a/Source/Engine/Scripting/ManagedCLR/MAssembly.cpp
+++ b/Source/Engine/Scripting/ManagedCLR/MAssembly.cpp
@@ -352,6 +352,7 @@ bool MAssembly::LoadWithImage(const String& assemblyPath)
}
}
+ // TODO: load pdbs for custom third-party libs referenced by game assemblies for debugging
#if 0
// Hack to load debug information for Newtonsoft.Json (enable it to debug C# code of json lib)
if (assemblyPath.EndsWith(TEXT("FlaxEngine.CSharp.dll")))
diff --git a/Source/Engine/Scripting/ManagedCLR/MCore.cpp b/Source/Engine/Scripting/ManagedCLR/MCore.cpp
index 91f12cfb0..f7b46e5cc 100644
--- a/Source/Engine/Scripting/ManagedCLR/MCore.cpp
+++ b/Source/Engine/Scripting/ManagedCLR/MCore.cpp
@@ -2,7 +2,6 @@
#include "MCore.h"
#include "MDomain.h"
-#include "MClass.h"
#include "Engine/Core/Log.h"
#include "Engine/Core/Types/String.h"
#include "Engine/Core/Types/DateTime.h"
@@ -353,6 +352,9 @@ bool MCore::LoadEngine()
PROFILE_CPU();
ASSERT(Globals::MonoPath.IsANSI());
+ // Debugging Mono GC
+ //Platform::SetEnvironmentVariable(TEXT("MONO_GC_DEBUG"), TEXT("6:gc-log.txt,check-remset-consistency,nursery-canaries"));
+
#if 0
// Override memory allocation callback
// TODO: use ENABLE_OVERRIDABLE_ALLOCATORS when building Mono to support memory callbacks or use counters for memory profiling
diff --git a/Source/Engine/Scripting/ManagedCLR/MUtils.cpp b/Source/Engine/Scripting/ManagedCLR/MUtils.cpp
index 3b46e4f36..aa5d1a6a1 100644
--- a/Source/Engine/Scripting/ManagedCLR/MUtils.cpp
+++ b/Source/Engine/Scripting/ManagedCLR/MUtils.cpp
@@ -114,7 +114,7 @@ MonoString* MUtils::ToString(const String& str)
MonoString* MUtils::ToString(const String& str, MonoDomain* domain)
{
if (str.IsEmpty())
- return mono_string_empty(mono_domain_get());
+ return mono_string_empty(domain);
return mono_string_new_utf16(domain, (const mono_unichar2*)*str, str.Length());
}
diff --git a/Source/Engine/Scripting/ManagedSerialization.cpp b/Source/Engine/Scripting/ManagedSerialization.cpp
index 97560701c..1fa799d56 100644
--- a/Source/Engine/Scripting/ManagedSerialization.cpp
+++ b/Source/Engine/Scripting/ManagedSerialization.cpp
@@ -10,7 +10,7 @@
#include "ManagedCLR/MMethod.h"
#include
-void ManagedSerialization::Serialize(ISerializable::SerializeStream& stream, MonoObject* object)
+void ManagedSerialization::Serialize(ISerializable::SerializeStream& stream, MObject* object)
{
if (!object)
{
@@ -47,7 +47,7 @@ void ManagedSerialization::Serialize(ISerializable::SerializeStream& stream, Mon
mono_free(invokeResultChars);
}
-void ManagedSerialization::SerializeDiff(ISerializable::SerializeStream& stream, MonoObject* object, MonoObject* other)
+void ManagedSerialization::SerializeDiff(ISerializable::SerializeStream& stream, MObject* object, MObject* other)
{
if (!object || !other)
{
@@ -85,7 +85,7 @@ void ManagedSerialization::SerializeDiff(ISerializable::SerializeStream& stream,
mono_free(invokeResultChars);
}
-void ManagedSerialization::Deserialize(ISerializable::DeserializeStream& stream, MonoObject* object)
+void ManagedSerialization::Deserialize(ISerializable::DeserializeStream& stream, MObject* object)
{
if (!object)
return;
@@ -98,7 +98,7 @@ void ManagedSerialization::Deserialize(ISerializable::DeserializeStream& stream,
Deserialize(StringAnsiView(buffer.GetString(), (int32)buffer.GetSize()), object);
}
-void ManagedSerialization::Deserialize(const StringAnsiView& data, MonoObject* object)
+void ManagedSerialization::Deserialize(const StringAnsiView& data, MObject* object)
{
const char* str = data.Get();
const int32 len = data.Length();
diff --git a/Source/Engine/Scripting/ManagedSerialization.h b/Source/Engine/Scripting/ManagedSerialization.h
index fdcccdcd1..10495dd36 100644
--- a/Source/Engine/Scripting/ManagedSerialization.h
+++ b/Source/Engine/Scripting/ManagedSerialization.h
@@ -18,7 +18,7 @@ public:
///
/// The output stream.
/// The object to serialize.
- static void Serialize(ISerializable::SerializeStream& stream, MonoObject* object);
+ static void Serialize(ISerializable::SerializeStream& stream, MObject* object);
///
/// Serializes managed object difference to JSON.
@@ -26,20 +26,20 @@ public:
/// The output stream.
/// The object to serialize.
/// The reference object to serialize diff compared to it.
- static void SerializeDiff(ISerializable::SerializeStream& stream, MonoObject* object, MonoObject* other);
+ static void SerializeDiff(ISerializable::SerializeStream& stream, MObject* object, MObject* other);
///
/// Deserializes managed object from the JSON.
///
/// The input stream.
/// The object to deserialize.
- static void Deserialize(ISerializable::DeserializeStream& stream, MonoObject* object);
+ static void Deserialize(ISerializable::DeserializeStream& stream, MObject* object);
///
/// Deserializes managed object from the JSON.
///
/// The input data.
/// The object to deserialize.
- static void Deserialize(const StringAnsiView& data, MonoObject* object);
+ static void Deserialize(const StringAnsiView& data, MObject* object);
#endif
};
diff --git a/Source/Engine/Scripting/Object.cs b/Source/Engine/Scripting/Object.cs
index 51001a86a..b86ed00d8 100644
--- a/Source/Engine/Scripting/Object.cs
+++ b/Source/Engine/Scripting/Object.cs
@@ -47,7 +47,7 @@ namespace FlaxEngine
{
Internal_ManagedInstanceCreated(this);
if (__unmanagedPtr == IntPtr.Zero)
- throw new FlaxException($"Failed to create native instance for object of type {GetType().FullName} (assembly: {GetType().Assembly.FullName}).");
+ throw new Exception($"Failed to create native instance for object of type {GetType().FullName} (assembly: {GetType().Assembly.FullName}).");
}
}
diff --git a/Source/Engine/Scripting/Scripting.cs b/Source/Engine/Scripting/Scripting.cs
index 5c7689fdb..6eff982d9 100644
--- a/Source/Engine/Scripting/Scripting.cs
+++ b/Source/Engine/Scripting/Scripting.cs
@@ -170,8 +170,12 @@ namespace FlaxEngine
private static void OnLocalizationChanged()
{
var currentThread = Thread.CurrentThread;
- currentThread.CurrentUICulture = Localization.CurrentLanguage;
- currentThread.CurrentCulture = Localization.CurrentCulture;
+ var language = Localization.CurrentLanguage;
+ if (language != null)
+ currentThread.CurrentUICulture = language;
+ var culture = Localization.CurrentCulture;
+ if (culture != null)
+ currentThread.CurrentCulture = culture;
}
///
diff --git a/Source/Engine/Serialization/JsonSerializer.cs b/Source/Engine/Serialization/JsonSerializer.cs
index 2099bc387..29a5951f9 100644
--- a/Source/Engine/Serialization/JsonSerializer.cs
+++ b/Source/Engine/Serialization/JsonSerializer.cs
@@ -188,7 +188,7 @@ namespace FlaxEngine.Json
while (reader.Read())
{
if (reader.TokenType != JsonToken.Comment)
- throw new FlaxException("Additional text found in JSON string after finishing deserializing object.");
+ throw new Exception("Additional text found in JSON string after finishing deserializing object.");
}
}
}
@@ -226,7 +226,7 @@ namespace FlaxEngine.Json
while (reader.Read())
{
if (reader.TokenType != JsonToken.Comment)
- throw new FlaxException("Additional text found in JSON string after finishing deserializing object.");
+ throw new Exception("Additional text found in JSON string after finishing deserializing object.");
}
}
@@ -254,7 +254,7 @@ namespace FlaxEngine.Json
while (reader.Read())
{
if (reader.TokenType != JsonToken.Comment)
- throw new FlaxException("Additional text found in JSON string after finishing deserializing object.");
+ throw new Exception("Additional text found in JSON string after finishing deserializing object.");
}
}
@@ -297,7 +297,7 @@ namespace FlaxEngine.Json
while (jsonReader.Read())
{
if (jsonReader.TokenType != JsonToken.Comment)
- throw new FlaxException("Additional text found in JSON string after finishing deserializing object.");
+ throw new Exception("Additional text found in JSON string after finishing deserializing object.");
}
}
diff --git a/Source/Engine/Utilities/Utils.cs b/Source/Engine/Utilities/Utils.cs
index 313fa276a..cc647a4fe 100644
--- a/Source/Engine/Utilities/Utils.cs
+++ b/Source/Engine/Utilities/Utils.cs
@@ -357,6 +357,14 @@ namespace FlaxEngine
return new Matrix(stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle());
}
+ internal static byte[] ReadJsonBytes(this BinaryReader stream)
+ {
+ // ReadStream::ReadJson
+ var engineBuild = stream.ReadInt32();
+ var size = stream.ReadInt32();
+ return stream.ReadBytes(size);
+ }
+
///
/// Deserializes object from Json by reading it as a raw data (ver+length+bytes).
///
@@ -569,6 +577,19 @@ namespace FlaxEngine
stream.Write(value.M44);
}
+ internal static void WriteJsonBytes(this BinaryWriter stream, byte[] bytes)
+ {
+ // WriteStream::WriteJson
+ stream.Write(Globals.EngineBuildNumber);
+ if (bytes != null)
+ {
+ stream.Write(bytes.Length);
+ stream.Write(bytes);
+ }
+ else
+ stream.Write(0);
+ }
+
///
/// Serializes object to Json and writes it as a raw data (ver+length+bytes).
///
diff --git a/Source/Engine/Visject/ShaderGraph.cpp b/Source/Engine/Visject/ShaderGraph.cpp
index 11adc31cd..e2f1472d3 100644
--- a/Source/Engine/Visject/ShaderGraph.cpp
+++ b/Source/Engine/Visject/ShaderGraph.cpp
@@ -156,6 +156,10 @@ void ShaderGenerator::ProcessGroupMath(Box* box, Node* node, Value& value)
Box* b2 = node->GetBox(1);
Value v1 = tryGetValue(b1, 0, Value::Zero);
Value v2 = tryGetValue(b2, 1, Value::Zero);
+ if (b1->HasConnection())
+ v2 = v2.Cast(v1.Type);
+ else
+ v1 = v1.Cast(v2.Type);
Char op = '?';
switch (node->TypeID)
{
diff --git a/Source/Engine/Visject/VisjectGraph.cpp b/Source/Engine/Visject/VisjectGraph.cpp
index 658121b20..9d706cca0 100644
--- a/Source/Engine/Visject/VisjectGraph.cpp
+++ b/Source/Engine/Visject/VisjectGraph.cpp
@@ -154,8 +154,13 @@ void VisjectExecutor::ProcessGroupMath(Box* box, Node* node, Value& value)
case 40:
case 41:
{
- Value v1 = tryGetValue(node->GetBox(0), 0, Value::Zero);
- Value v2 = tryGetValue(node->GetBox(1), 1, Value::Zero).Cast(v1.Type);
+ auto b1 = node->GetBox(0);
+ Value v1 = tryGetValue(b1, 0, Value::Zero);
+ Value v2 = tryGetValue(node->GetBox(1), 1, Value::Zero);
+ if (b1->HasConnection())
+ v2 = v2.Cast(v1.Type);
+ else
+ v1 = v1.Cast(v2.Type);
GraphUtilities::ApplySomeMathHere(node->TypeID, value, v1, v2);
break;
}
diff --git a/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs b/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs
index c549ae84b..1637524c2 100644
--- a/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs
+++ b/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs
@@ -160,7 +160,7 @@ namespace Flax.Build
// Prefer installed Roslyn C# compiler over Mono one
monoPath = null;
- cscPath = Path.Combine(Path.GetDirectoryName(Deploy.VCEnvironment.MSBuildPath), "Roslyn", "csc.exe");
+ cscPath = Path.Combine(Path.GetDirectoryName(VCEnvironment.MSBuildPath), "Roslyn", "csc.exe");
if (!File.Exists(cscPath))
{
diff --git a/Source/Tools/Flax.Build/Deploy/VCEnvironment.cs b/Source/Tools/Flax.Build/Deploy/VCEnvironment.cs
index 98c352829..0ca955324 100644
--- a/Source/Tools/Flax.Build/Deploy/VCEnvironment.cs
+++ b/Source/Tools/Flax.Build/Deploy/VCEnvironment.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2020 Flax Engine. All rights reserved.
using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
using Flax.Build;
@@ -219,7 +220,8 @@ namespace Flax.Deploy
/// Path to the solution file
/// Configuration to build.
/// Platform to build.
- public static void BuildSolution(string solutionFile, string buildConfig, string buildPlatform)
+ /// Custom build properties mapping (property=value).
+ public static void BuildSolution(string solutionFile, string buildConfig, string buildPlatform, Dictionary props = null)
{
var msBuild = MSBuildPath;
if (string.IsNullOrEmpty(msBuild))
@@ -233,6 +235,11 @@ namespace Flax.Deploy
}
string cmdLine = string.Format("\"{0}\" /m /t:Build /p:Configuration=\"{1}\" /p:Platform=\"{2}\" {3} /nologo", solutionFile, buildConfig, buildPlatform, Verbosity);
+ if (props != null)
+ {
+ foreach (var e in props)
+ cmdLine += string.Format(" /p:{0}={1}", e.Key, e.Value);
+ }
int result = Utilities.Run(msBuild, cmdLine);
if (result != 0)
{
diff --git a/Source/Tools/Flax.Build/Deps/Dependency.cs b/Source/Tools/Flax.Build/Deps/Dependency.cs
index 4a801b13c..ed4d4731a 100644
--- a/Source/Tools/Flax.Build/Deps/Dependency.cs
+++ b/Source/Tools/Flax.Build/Deps/Dependency.cs
@@ -99,6 +99,18 @@ namespace Flax.Deps
}
}
+ ///
+ /// Clones the directory.
+ ///
+ /// The source folder path.
+ /// The destination folder path.
+ public static void CloneDirectory(string src, string dst)
+ {
+ if (Directory.Exists(dst))
+ Utilities.DirectoryDelete(dst);
+ Utilities.DirectoryCopy(src, dst);
+ }
+
///
/// Clones the git repository from the remote url (full repository).
///
@@ -275,30 +287,76 @@ namespace Flax.Deps
///
/// The path.
/// The workspace folder.
- /// Custom environment variables to pass to the child process.
- public static void RunCygwin(string path, string workspace = null, Dictionary envVars = null)
+ public static void RunCygwin(string path, string workspace = null)
+ {
+ RunBash(path, string.Empty, workspace);
+ }
+
+ ///
+ /// Runs the bash script (executes natively on Unix platforms, uses Cygwin on Windows).
+ ///
+ /// The script or command path.
+ /// The arguments.
+ /// The workspace folder.
+ /// Custom environment variables to pass to the child process.
+ public static void RunBash(string path, string args = null, string workspace = null, Dictionary envVars = null)
{
- string app;
switch (BuildPlatform)
{
case TargetPlatform.Windows:
{
+ // Find Cygwin
var cygwinFolder = Environment.GetEnvironmentVariable("CYGWIN");
if (string.IsNullOrEmpty(cygwinFolder) || !Directory.Exists(cygwinFolder))
{
cygwinFolder = "C:\\cygwin";
if (!Directory.Exists(cygwinFolder))
- throw new Exception("Missing Cygwin. Install Cygwin64 to C:\\cygwin or set CYGWIN env variable to install location folder.");
+ {
+ cygwinFolder = "C:\\cygwin64";
+ if (!Directory.Exists(cygwinFolder))
+ throw new Exception("Missing Cygwin. Install Cygwin64 to C:\\cygwin or set CYGWIN env variable to install location folder.");
+ }
+ }
+ var cygwinBinFolder = Path.Combine(cygwinFolder, "bin");
+
+ // Ensure that Cygwin binaries folder is in a PATH
+ string envPath = null;
+ envVars?.TryGetValue("PATH", out envPath);
+ if (envPath == null || envPath.IndexOf(cygwinBinFolder, StringComparison.OrdinalIgnoreCase) == -1)
+ {
+ if (envVars == null)
+ envVars = new Dictionary();
+ envVars["PATH"] = cygwinBinFolder;
+ if (envPath != null)
+ envVars["PATH"] += ";" + envPath;
+ }
+
+ // Get the executable file path
+ if (path.EndsWith(".sh", StringComparison.OrdinalIgnoreCase))
+ {
+ // Bash script
+ if (args == null)
+ args = path.Replace('\\', '/');
+ else
+ args = path.Replace('\\', '/') + " " + args;
+ path = Path.Combine(cygwinBinFolder, "bash.exe");
+ }
+ else if (File.Exists(Path.Combine(cygwinBinFolder, path + ".exe")))
+ {
+ // Tool (eg. make)
+ path = Path.Combine(cygwinBinFolder, path + ".exe");
+ }
+ else
+ {
+ throw new Exception("Cannot execute command " + path + " with args " + args);
}
- app = Path.Combine(cygwinFolder, "bin\\bash.exe");
break;
}
case TargetPlatform.Linux:
- app = "bash";
- break;
+ case TargetPlatform.Mac: break;
default: throw new InvalidPlatformException(BuildPlatform);
}
- Utilities.Run(app, path, null, workspace, Utilities.RunOptions.None, envVars);
+ Utilities.Run(path, args, null, workspace, Utilities.RunOptions.ThrowExceptionOnError, envVars);
}
}
}
diff --git a/Source/Tools/Flax.Build/Utilities/Utilities.cs b/Source/Tools/Flax.Build/Utilities/Utilities.cs
index 72278c72e..a9a97bac0 100644
--- a/Source/Tools/Flax.Build/Utilities/Utilities.cs
+++ b/Source/Tools/Flax.Build/Utilities/Utilities.cs
@@ -244,6 +244,26 @@ namespace Flax.Build
}
}
+ ///
+ /// Deletes the directories inside a directory.
+ ///
+ /// The directory path.
+ /// The custom filter for the directories to delete. Can be used to select files to delete. Null if unused.
+ /// if set to true with sub-directories (recursive delete operation).
+ public static void DirectoriesDelete(string directoryPath, string searchPattern = null, bool withSubdirs = true)
+ {
+ if (!Directory.Exists(directoryPath))
+ return;
+ if (searchPattern == null)
+ searchPattern = "*";
+
+ var directories = Directory.GetDirectories(directoryPath, searchPattern, withSubdirs ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
+ for (int i = 0; i < directories.Length; i++)
+ {
+ DirectoryDelete(directories[i]);
+ }
+ }
+
///
/// The process run options.
///
@@ -355,14 +375,14 @@ namespace Flax.Build
Stopwatch stopwatch = Stopwatch.StartNew();
if (!options.HasFlag(RunOptions.NoLoggingOfRunCommand))
{
- Log.Verbose("Running: " + app + " " + (string.IsNullOrEmpty(commandLine) ? "" : commandLine));
+ Log.Verbose("Running: " + app + (string.IsNullOrEmpty(commandLine) ? "" : " " + commandLine));
}
bool redirectStdOut = (options & RunOptions.NoStdOutRedirect) != RunOptions.NoStdOutRedirect;
Process proc = new Process();
proc.StartInfo.FileName = app;
- proc.StartInfo.Arguments = string.IsNullOrEmpty(commandLine) ? "" : commandLine;
+ proc.StartInfo.Arguments = commandLine != null ? commandLine : "";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardInput = input != null;
proc.StartInfo.CreateNoWindow = true;
@@ -386,7 +406,7 @@ namespace Flax.Build
{
if (env.Key == "PATH")
{
- proc.StartInfo.EnvironmentVariables[env.Key] = proc.StartInfo.EnvironmentVariables[env.Key] + ';' + env.Value;
+ proc.StartInfo.EnvironmentVariables[env.Key] = env.Value + ';' + proc.StartInfo.EnvironmentVariables[env.Key];
}
else
{