Merge remote-tracking branch 'origin/master' into dotnet7
# Conflicts: # README.md
This commit is contained in:
@@ -269,24 +269,16 @@ float CalcLOD(float2 xy, float4 morph)
|
|||||||
if ((xy.x + xy.y) > 1)
|
if ((xy.x + xy.y) > 1)
|
||||||
{
|
{
|
||||||
if (xy.x < xy.y)
|
if (xy.x < xy.y)
|
||||||
{
|
|
||||||
lod = lodCalculated.w;
|
lod = lodCalculated.w;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
lod = lodCalculated.z;
|
lod = lodCalculated.z;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (xy.x < xy.y)
|
if (xy.x < xy.y)
|
||||||
{
|
|
||||||
lod = lodCalculated.y;
|
lod = lodCalculated.y;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
lod = lodCalculated.x;
|
lod = lodCalculated.x;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return lod;
|
return lod;
|
||||||
|
|||||||
19
README.md
19
README.md
@@ -36,6 +36,7 @@ Flax Visual Studio extension provides better programming workflow, C# scripts de
|
|||||||
* Install Windows 8.1 SDK or newer (via Visual Studio Installer)
|
* Install Windows 8.1 SDK or newer (via Visual Studio Installer)
|
||||||
* Install Microsoft Visual C++ 2015 v140 toolset or newer (via Visual Studio Installer)
|
* Install Microsoft Visual C++ 2015 v140 toolset or newer (via Visual Studio Installer)
|
||||||
* Install .Net 7 SDK (via Visual Studio Installer or [from web](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
* Install .Net 7 SDK (via Visual Studio Installer or [from web](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
||||||
|
* Install Git with LFS
|
||||||
* Clone repo (with LFS)
|
* Clone repo (with LFS)
|
||||||
* Run **GenerateProjectFiles.bat**
|
* Run **GenerateProjectFiles.bat**
|
||||||
* Open `Flax.sln` and set solution configuration to **Editor.Development** and solution platform to **Win64**
|
* Open `Flax.sln` and set solution configuration to **Editor.Development** and solution platform to **Win64**
|
||||||
@@ -49,11 +50,21 @@ Flax Visual Studio extension provides better programming workflow, C# scripts de
|
|||||||
|
|
||||||
* Install Visual Studio Code
|
* Install Visual Studio Code
|
||||||
* Install .Net 7 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/7.0](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
* Install .Net 7 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/7.0](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
||||||
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
|
* Ubuntu: `sudo snap install dotnet-sdk --classic channel=7.0/stable`
|
||||||
|
* Install Vulkan SDK
|
||||||
|
* Ubuntu: see the instructions here: ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
|
||||||
|
* Arch: `sudo pacman -S spirv-tools vulkan-headers vulkan-tools vulkan-validation-layers`
|
||||||
* Install Git with LFS
|
* Install Git with LFS
|
||||||
* Install requried packages: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev nuget autoconf libogg-dev automake build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev`
|
* Ubuntu: `sudo apt-get install git git-lfs`
|
||||||
* Install compiler `sudo apt-get install clang lldb lld` (Clang 6 or newer)
|
* Arch: `sudo pacman -S git git-lfs`
|
||||||
* Clone repo (with LFS)
|
* `git-lfs install`
|
||||||
|
* Install the required packages:
|
||||||
|
* Ubuntu: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev zlib1g-dev`
|
||||||
|
* Arch: `sudo pacman -S base-devel libx11 libxcursor libxinerama zlib`
|
||||||
|
* Install Clang compiler (version 6 or later):
|
||||||
|
* Ubuntu: `sudo apt-get install clang lldb lld`
|
||||||
|
* Arch: `sudo pacman -S clang lldb lld`
|
||||||
|
* Clone the repository (with LFS)
|
||||||
* Run `./GenerateProjectFiles.sh`
|
* Run `./GenerateProjectFiles.sh`
|
||||||
* Open workspace with Visual Code
|
* Open workspace with Visual Code
|
||||||
* Build and run (configuration and task named `Flax|Editor.Linux.Development|x64`)
|
* Build and run (configuration and task named `Flax|Editor.Linux.Development|x64`)
|
||||||
|
|||||||
@@ -289,13 +289,14 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
String androidSdk;
|
String androidSdk;
|
||||||
if (!envVars.TryGet(TEXT("ANDROID_SDK"), androidSdk) || !FileSystem::DirectoryExists(androidSdk))
|
if (!envVars.TryGet(TEXT("ANDROID_HOME"), androidSdk) || !FileSystem::DirectoryExists(androidSdk))
|
||||||
{
|
{
|
||||||
LOG(Error, "Missing or invalid ANDROID_SDK env variable. {0}", androidSdk);
|
if (!envVars.TryGet(TEXT("ANDROID_SDK"), androidSdk) || !FileSystem::DirectoryExists(androidSdk))
|
||||||
return true;
|
{
|
||||||
|
LOG(Error, "Missing or invalid ANDROID_HOME env variable. {0}", androidSdk);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!envVars.ContainsKey(TEXT("ANDROID_SDK_ROOT")))
|
|
||||||
envVars[TEXT("ANDROID_SDK_ROOT")] = androidSdk;
|
|
||||||
|
|
||||||
// Build Gradle project into package
|
// Build Gradle project into package
|
||||||
LOG(Info, "Building Gradle project into package...");
|
LOG(Info, "Building Gradle project into package...");
|
||||||
|
|||||||
@@ -96,7 +96,8 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
AnchorPreset = AnchorPresets.TopLeft,
|
AnchorPreset = AnchorPresets.TopLeft,
|
||||||
TooltipText = "Scale values are linked together.",
|
TooltipText = "Scale values are linked together.",
|
||||||
};
|
};
|
||||||
_linkImage.LocalX += 40;
|
var x = LinkedLabel.Text.Value.Length * 7 + 5;
|
||||||
|
_linkImage.LocalX += x;
|
||||||
_linkImage.LocalY += 1;
|
_linkImage.LocalY += 1;
|
||||||
|
|
||||||
LinkedLabel.SetupContextMenu += (label, menu, editor) =>
|
LinkedLabel.SetupContextMenu += (label, menu, editor) =>
|
||||||
|
|||||||
@@ -1538,7 +1538,7 @@ namespace FlaxEditor
|
|||||||
if (dockedTo != null && dockedTo.SelectedTab != gameWin && dockedTo.SelectedTab != null)
|
if (dockedTo != null && dockedTo.SelectedTab != gameWin && dockedTo.SelectedTab != null)
|
||||||
result = dockedTo.SelectedTab.Size * root.DpiScale;
|
result = dockedTo.SelectedTab.Size * root.DpiScale;
|
||||||
else
|
else
|
||||||
result = gameWin.Size * root.DpiScale;
|
result = gameWin.Viewport.Size * root.DpiScale;
|
||||||
|
|
||||||
result = Float2.Round(result);
|
result = Float2.Round(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -365,6 +365,7 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
float maxWidth = 0;
|
float maxWidth = 0;
|
||||||
float height = _itemsAreaMargin.Height;
|
float height = _itemsAreaMargin.Height;
|
||||||
int itemsLeft = MaximumItemsInViewCount;
|
int itemsLeft = MaximumItemsInViewCount;
|
||||||
|
int overflowItemCount = 0;
|
||||||
for (int i = 0; i < _panel.Children.Count; i++)
|
for (int i = 0; i < _panel.Children.Count; i++)
|
||||||
{
|
{
|
||||||
if (_panel.Children[i] is ContextMenuItem item && item.Visible)
|
if (_panel.Children[i] is ContextMenuItem item && item.Visible)
|
||||||
@@ -374,11 +375,27 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
height += item.Height + _itemsMargin.Height;
|
height += item.Height + _itemsMargin.Height;
|
||||||
itemsLeft--;
|
itemsLeft--;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
overflowItemCount++;
|
||||||
|
}
|
||||||
maxWidth = Mathf.Max(maxWidth, item.MinimumWidth);
|
maxWidth = Mathf.Max(maxWidth, item.MinimumWidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
maxWidth = Mathf.Max(maxWidth + 20, MinimumWidth);
|
maxWidth = Mathf.Max(maxWidth + 20, MinimumWidth);
|
||||||
|
|
||||||
|
// Move child arrows to accommodate scroll bar showing
|
||||||
|
if (overflowItemCount > 0)
|
||||||
|
{
|
||||||
|
foreach (var child in _panel.Children)
|
||||||
|
{
|
||||||
|
if (child is ContextMenuChildMenu item && item.Visible)
|
||||||
|
{
|
||||||
|
item.AdjustArrowAmount = -_panel.VScrollBar.Width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Resize container
|
// Resize container
|
||||||
Size = new Float2(Mathf.Ceil(maxWidth), Mathf.Ceil(height));
|
Size = new Float2(Mathf.Ceil(maxWidth), Mathf.Ceil(height));
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly ContextMenu ContextMenu = new ContextMenu();
|
public readonly ContextMenu ContextMenu = new ContextMenu();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The amount to adjust the arrow image by in x coordinates.
|
||||||
|
/// </summary>
|
||||||
|
public float AdjustArrowAmount = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ContextMenuChildMenu"/> class.
|
/// Initializes a new instance of the <see cref="ContextMenuChildMenu"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -44,7 +49,7 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
|
|
||||||
// Draw arrow
|
// Draw arrow
|
||||||
if (ContextMenu.HasChildren)
|
if (ContextMenu.HasChildren)
|
||||||
Render2D.DrawSprite(style.ArrowRight, new Rectangle(Width - 15, (Height - 12) / 2, 12, 12), Enabled ? isCMopened ? style.BackgroundSelected : style.Foreground : style.ForegroundDisabled);
|
Render2D.DrawSprite(style.ArrowRight, new Rectangle(Width - 15 + AdjustArrowAmount, (Height - 12) / 2, 12, 12), Enabled ? isCMopened ? style.BackgroundSelected : style.Foreground : style.ForegroundDisabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -274,6 +274,7 @@ namespace FlaxEditor.Modules.SourceCodeEditing
|
|||||||
{
|
{
|
||||||
ScriptsBuilder.ScriptsReload += OnScriptsReload;
|
ScriptsBuilder.ScriptsReload += OnScriptsReload;
|
||||||
ScriptsBuilder.ScriptsReloadEnd += OnScriptsReloadEnd;
|
ScriptsBuilder.ScriptsReloadEnd += OnScriptsReloadEnd;
|
||||||
|
ScriptsBuilder.ScriptsLoaded += OnScriptsLoaded;
|
||||||
Editor.Options.OptionsChanged += OnOptionsChanged;
|
Editor.Options.OptionsChanged += OnOptionsChanged;
|
||||||
|
|
||||||
// Add default code editors (in-build)
|
// Add default code editors (in-build)
|
||||||
@@ -344,6 +345,7 @@ namespace FlaxEditor.Modules.SourceCodeEditing
|
|||||||
|
|
||||||
ScriptsBuilder.ScriptsReload -= OnScriptsReload;
|
ScriptsBuilder.ScriptsReload -= OnScriptsReload;
|
||||||
ScriptsBuilder.ScriptsReloadEnd -= OnScriptsReloadEnd;
|
ScriptsBuilder.ScriptsReloadEnd -= OnScriptsReloadEnd;
|
||||||
|
ScriptsBuilder.ScriptsLoaded -= OnScriptsLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -379,6 +381,12 @@ namespace FlaxEditor.Modules.SourceCodeEditing
|
|||||||
OnTypesChanged();
|
OnTypesChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnScriptsLoaded()
|
||||||
|
{
|
||||||
|
// Clear any state with engine-only types
|
||||||
|
ClearTypes();
|
||||||
|
}
|
||||||
|
|
||||||
private static bool IsTypeValidScriptingType(ScriptType t)
|
private static bool IsTypeValidScriptingType(ScriptType t)
|
||||||
{
|
{
|
||||||
return !t.IsGenericType && !t.IsAbstract && !t.HasAttribute(typeof(HideInEditorAttribute), false);
|
return !t.IsGenericType && !t.IsAbstract && !t.HasAttribute(typeof(HideInEditorAttribute), false);
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ enum class EventType
|
|||||||
ReloadBegin = 5,
|
ReloadBegin = 5,
|
||||||
Reload = 6,
|
Reload = 6,
|
||||||
ReloadEnd = 7,
|
ReloadEnd = 7,
|
||||||
|
ScriptsLoaded = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EventData
|
struct EventData
|
||||||
@@ -74,6 +75,7 @@ namespace ScriptsBuilderImpl
|
|||||||
void onScriptsReloadStart();
|
void onScriptsReloadStart();
|
||||||
void onScriptsReload();
|
void onScriptsReload();
|
||||||
void onScriptsReloadEnd();
|
void onScriptsReloadEnd();
|
||||||
|
void onScriptsLoaded();
|
||||||
|
|
||||||
void GetClassName(const MString& fullname, MString& className);
|
void GetClassName(const MString& fullname, MString& className);
|
||||||
|
|
||||||
@@ -203,6 +205,11 @@ void ScriptsBuilderImpl::onScriptsReloadEnd()
|
|||||||
CallEvent(EventType::ReloadEnd);
|
CallEvent(EventType::ReloadEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScriptsBuilderImpl::onScriptsLoaded()
|
||||||
|
{
|
||||||
|
CallEvent(EventType::ScriptsLoaded);
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptsBuilder::Compile()
|
void ScriptsBuilder::Compile()
|
||||||
{
|
{
|
||||||
ScopeLock scopeLock(_locker);
|
ScopeLock scopeLock(_locker);
|
||||||
@@ -556,6 +563,7 @@ bool ScriptsBuilderService::Init()
|
|||||||
Level::ScriptsReloadStart.Bind(onScriptsReloadStart);
|
Level::ScriptsReloadStart.Bind(onScriptsReloadStart);
|
||||||
Level::ScriptsReload.Bind(onScriptsReload);
|
Level::ScriptsReload.Bind(onScriptsReload);
|
||||||
Level::ScriptsReloadEnd.Bind(onScriptsReloadEnd);
|
Level::ScriptsReloadEnd.Bind(onScriptsReloadEnd);
|
||||||
|
Scripting::ScriptsLoaded.Bind(onScriptsLoaded);
|
||||||
|
|
||||||
// Listen to code editors manager events
|
// Listen to code editors manager events
|
||||||
CodeEditingManager::AsyncOpenBegin.Bind(onCodeEditorAsyncOpenBegin);
|
CodeEditingManager::AsyncOpenBegin.Bind(onCodeEditorAsyncOpenBegin);
|
||||||
|
|||||||
@@ -66,6 +66,11 @@ namespace FlaxEditor
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static event Action ScriptsReloadEnd;
|
public static event Action ScriptsReloadEnd;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when engine loads game scripts.
|
||||||
|
/// </summary>
|
||||||
|
public static event Action ScriptsLoaded;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when code editor starts asynchronous open a file or a solution.
|
/// Occurs when code editor starts asynchronous open a file or a solution.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -86,6 +91,7 @@ namespace FlaxEditor
|
|||||||
ReloadBegin = 5,
|
ReloadBegin = 5,
|
||||||
Reload = 6,
|
Reload = 6,
|
||||||
ReloadEnd = 7,
|
ReloadEnd = 7,
|
||||||
|
ScriptsLoaded = 8,
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void Internal_OnEvent(EventType type)
|
internal static void Internal_OnEvent(EventType type)
|
||||||
@@ -118,6 +124,9 @@ namespace FlaxEditor
|
|||||||
case EventType.ReloadEnd:
|
case EventType.ReloadEnd:
|
||||||
ScriptsReloadEnd?.Invoke();
|
ScriptsReloadEnd?.Invoke();
|
||||||
break;
|
break;
|
||||||
|
case EventType.ScriptsLoaded:
|
||||||
|
ScriptsLoaded?.Invoke();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -973,6 +973,19 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
NodeElementArchetype.Factory.TextBox(30, Surface.Constants.LayoutOffsetY, 140, TextBox.DefaultHeight, 0, false),
|
NodeElementArchetype.Factory.TextBox(30, Surface.Constants.LayoutOffsetY, 140, TextBox.DefaultHeight, 0, false),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
new NodeArchetype
|
||||||
|
{
|
||||||
|
TypeID = 33,
|
||||||
|
Title = "Animation Instance Data",
|
||||||
|
Description = "Caches custom data per-instance and allow sampling it. Can be used to randomize animation play offset to offer randomization for crowds reusing the same graph.",
|
||||||
|
Flags = NodeFlags.AnimGraph,
|
||||||
|
Size = new Float2(240, 20),
|
||||||
|
Elements = new[]
|
||||||
|
{
|
||||||
|
NodeElementArchetype.Factory.Output(0, "Get", typeof(Float4), 0),
|
||||||
|
NodeElementArchetype.Factory.Input(0, "Init", true, typeof(Float4), 1),
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ namespace FlaxEditor.Tools.Terrain
|
|||||||
_31 = 31,
|
_31 = 31,
|
||||||
_63 = 63,
|
_63 = 63,
|
||||||
_127 = 127,
|
_127 = 127,
|
||||||
|
_254 = 254,
|
||||||
_255 = 255,
|
_255 = 255,
|
||||||
|
_511 = 511,
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Options
|
private class Options
|
||||||
@@ -34,7 +36,7 @@ namespace FlaxEditor.Tools.Terrain
|
|||||||
[EditorOrder(100), EditorDisplay("Layout", "Number Of Patches"), DefaultValue(typeof(Int2), "1,1"), Limit(0, 512), Tooltip("Amount of terrain patches in each direction (X and Z). Each terrain patch contains a grid of 16 chunks. Patches can be later added or removed from terrain using a terrain editor tool.")]
|
[EditorOrder(100), EditorDisplay("Layout", "Number Of Patches"), DefaultValue(typeof(Int2), "1,1"), Limit(0, 512), Tooltip("Amount of terrain patches in each direction (X and Z). Each terrain patch contains a grid of 16 chunks. Patches can be later added or removed from terrain using a terrain editor tool.")]
|
||||||
public Int2 NumberOfPatches = new Int2(1, 1);
|
public Int2 NumberOfPatches = new Int2(1, 1);
|
||||||
|
|
||||||
[EditorOrder(110), EditorDisplay("Layout"), DefaultValue(ChunkSizes._127), Tooltip("The size of the chunk (amount of quads per edge for the highest LOD). Must be power of two minus one (eg. 63).")]
|
[EditorOrder(110), EditorDisplay("Layout"), DefaultValue(ChunkSizes._127), Tooltip("The size of the chunk (amount of quads per edge for the highest LOD).")]
|
||||||
public ChunkSizes ChunkSize = ChunkSizes._127;
|
public ChunkSizes ChunkSize = ChunkSizes._127;
|
||||||
|
|
||||||
[EditorOrder(120), EditorDisplay("Layout", "LOD Count"), DefaultValue(6), Limit(1, FlaxEngine.Terrain.MaxLODs), Tooltip("The maximum Level Of Details count. The actual amount of LODs may be lower due to provided chunk size (each LOD has 4 times less quads).")]
|
[EditorOrder(120), EditorDisplay("Layout", "LOD Count"), DefaultValue(6), Limit(1, FlaxEngine.Terrain.MaxLODs), Tooltip("The maximum Level Of Details count. The actual amount of LODs may be lower due to provided chunk size (each LOD has 4 times less quads).")]
|
||||||
|
|||||||
@@ -235,14 +235,14 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
if (IsLayoutLocked)
|
if (IsLayoutLocked)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var root = Graph.Root;
|
_tree.LockChildrenRecursive();
|
||||||
root.TreeNode.LockChildrenRecursive();
|
|
||||||
|
|
||||||
// Update tree
|
// Update tree
|
||||||
var query = _searchBox.Text;
|
var query = _searchBox.Text;
|
||||||
|
var root = Graph.Root;
|
||||||
root.TreeNode.UpdateFilter(query);
|
root.TreeNode.UpdateFilter(query);
|
||||||
|
|
||||||
root.TreeNode.UnlockChildrenRecursive();
|
_tree.UnlockChildrenRecursive();
|
||||||
PerformLayout();
|
PerformLayout();
|
||||||
PerformLayout();
|
PerformLayout();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,14 +123,14 @@ namespace FlaxEditor.Windows
|
|||||||
if (IsLayoutLocked)
|
if (IsLayoutLocked)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var root = Editor.Scene.Root;
|
_tree.LockChildrenRecursive();
|
||||||
root.TreeNode.LockChildrenRecursive();
|
|
||||||
|
|
||||||
// Update tree
|
// Update tree
|
||||||
var query = _searchBox.Text;
|
var query = _searchBox.Text;
|
||||||
|
var root = Editor.Scene.Root;
|
||||||
root.TreeNode.UpdateFilter(query);
|
root.TreeNode.UpdateFilter(query);
|
||||||
|
|
||||||
root.TreeNode.UnlockChildrenRecursive();
|
_tree.UnlockChildrenRecursive();
|
||||||
PerformLayout();
|
PerformLayout();
|
||||||
PerformLayout();
|
PerformLayout();
|
||||||
}
|
}
|
||||||
@@ -251,7 +251,7 @@ namespace FlaxEditor.Windows
|
|||||||
if (nodes.Count == 1)
|
if (nodes.Count == 1)
|
||||||
{
|
{
|
||||||
nodes[0].ExpandAllParents(true);
|
nodes[0].ExpandAllParents(true);
|
||||||
ScrollViewTo(nodes[0]);
|
_sceneTreePanel.ScrollViewTo(nodes[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,6 +115,11 @@ void SlotBucketInit(AnimGraphInstanceData::Bucket& bucket)
|
|||||||
bucket.Slot.LoopsLeft = 0;
|
bucket.Slot.LoopsLeft = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InstanceDataBucketInit(AnimGraphInstanceData::Bucket& bucket)
|
||||||
|
{
|
||||||
|
bucket.InstanceData.Init = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool SortMultiBlend1D(const byte& a, const byte& b, AnimGraphNode* n)
|
bool SortMultiBlend1D(const byte& a, const byte& b, AnimGraphNode* n)
|
||||||
{
|
{
|
||||||
// Sort items by X location from the lowest to the highest
|
// Sort items by X location from the lowest to the highest
|
||||||
@@ -432,10 +437,12 @@ bool AnimGraphBase::onNodeLoaded(Node* n)
|
|||||||
}
|
}
|
||||||
// Animation Slot
|
// Animation Slot
|
||||||
case 32:
|
case 32:
|
||||||
{
|
|
||||||
ADD_BUCKET(SlotBucketInit);
|
ADD_BUCKET(SlotBucketInit);
|
||||||
break;
|
break;
|
||||||
}
|
// Animation Instance Data
|
||||||
|
case 33:
|
||||||
|
ADD_BUCKET(InstanceDataBucketInit);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// Custom
|
// Custom
|
||||||
|
|||||||
@@ -315,6 +315,12 @@ public:
|
|||||||
int32 LoopsLeft;
|
int32 LoopsLeft;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct InstanceDataBucket
|
||||||
|
{
|
||||||
|
bool Init;
|
||||||
|
float Data[4];
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The single data storage bucket for the instanced animation graph node. Used to store the node state (playback position, state, transition data).
|
/// The single data storage bucket for the instanced animation graph node. Used to store the node state (playback position, state, transition data).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -327,6 +333,7 @@ public:
|
|||||||
BlendPoseBucket BlendPose;
|
BlendPoseBucket BlendPose;
|
||||||
StateMachineBucket StateMachine;
|
StateMachineBucket StateMachine;
|
||||||
SlotBucket Slot;
|
SlotBucket Slot;
|
||||||
|
InstanceDataBucket InstanceData;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2035,10 +2035,22 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Animation Instance Data
|
||||||
|
case 33:
|
||||||
|
{
|
||||||
|
auto& bucket = context.Data->State[node->BucketIndex].InstanceData;
|
||||||
|
if (bucket.Init)
|
||||||
|
{
|
||||||
|
bucket.Init = false;
|
||||||
|
*(Float4*)bucket.Data = (Float4)tryGetValue(node->GetBox(1), Value::Zero);
|
||||||
|
}
|
||||||
|
value = *(Float4*)bucket.Data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
context.ValueCache.Add(boxBase, value);
|
context.ValueCache[boxBase] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimGraphExecutor::ProcessGroupFunction(Box* boxBase, Node* node, Value& value)
|
void AnimGraphExecutor::ProcessGroupFunction(Box* boxBase, Node* node, Value& value)
|
||||||
|
|||||||
@@ -55,8 +55,7 @@ LoadingThread::~LoadingThread()
|
|||||||
// Check if has thread attached
|
// Check if has thread attached
|
||||||
if (_thread != nullptr)
|
if (_thread != nullptr)
|
||||||
{
|
{
|
||||||
if (_thread->IsRunning())
|
_thread->Kill(true);
|
||||||
_thread->Kill(true);
|
|
||||||
Delete(_thread);
|
Delete(_thread);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "Engine/Core/Types/Guid.h"
|
#include "Engine/Core/Types/Guid.h"
|
||||||
#include "Engine/Core/ISerializable.h"
|
#include "Engine/Core/ISerializable.h"
|
||||||
|
#include "Engine/Scripting/ScriptingType.h"
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the reference to the scene asset. Stores the unique ID of the scene to reference. Can be used to load the selected scene.
|
/// Represents the reference to the scene asset. Stores the unique ID of the scene to reference. Can be used to load the selected scene.
|
||||||
|
|||||||
@@ -21,7 +21,11 @@ namespace THelpers
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct TIsTriviallyDestructibleImpl<T, false>
|
struct TIsTriviallyDestructibleImpl<T, false>
|
||||||
{
|
{
|
||||||
enum { Value = __has_trivial_destructor(T) };
|
#if defined(__clang__) && __clang_major__ >= 15
|
||||||
|
enum { Value = __is_trivially_destructible(T) };
|
||||||
|
#else
|
||||||
|
enum { Value = __has_trivial_destructor(T) };
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,7 +265,11 @@ struct TIsCopyConstructible
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct TIsTriviallyCopyConstructible
|
struct TIsTriviallyCopyConstructible
|
||||||
{
|
{
|
||||||
enum { Value = TOrValue<__has_trivial_copy(T), TIsPODType<T>>::Value };
|
#if defined(__clang__) && __clang_major__ >= 15
|
||||||
|
enum { Value = TOrValue<__is_trivially_copyable(T), TIsPODType<T>>::Value };
|
||||||
|
#else
|
||||||
|
enum { Value = TOrValue<__has_trivial_copy(T), TIsPODType<T>>::Value };
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -289,7 +297,11 @@ struct TIsTriviallyDestructible
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct TIsTriviallyCopyAssignable
|
struct TIsTriviallyCopyAssignable
|
||||||
{
|
{
|
||||||
enum { Value = TOrValue<__has_trivial_assign(T), TIsPODType<T>>::Value };
|
#if defined(__clang__) && __clang_major__ >= 15
|
||||||
|
enum { Value = TOrValue<__is_trivially_assignable(T, const T), TIsPODType<T>>::Value };
|
||||||
|
#else
|
||||||
|
enum { Value = TOrValue<__has_trivial_assign(T), TIsPODType<T>>::Value };
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ void ScreenSpaceReflectionsSettings::BlendWith(ScreenSpaceReflectionsSettings& o
|
|||||||
const bool isHalf = weight >= 0.5f;
|
const bool isHalf = weight >= 0.5f;
|
||||||
|
|
||||||
BLEND_FLOAT(Intensity);
|
BLEND_FLOAT(Intensity);
|
||||||
|
BLEND_ENUM(TraceMode);
|
||||||
BLEND_ENUM(DepthResolution);
|
BLEND_ENUM(DepthResolution);
|
||||||
BLEND_ENUM(RayTracePassResolution);
|
BLEND_ENUM(RayTracePassResolution);
|
||||||
BLEND_FLOAT(BRDFBias);
|
BLEND_FLOAT(BRDFBias);
|
||||||
|
|||||||
@@ -134,9 +134,15 @@ bool RenderTask::Resize(int32 width, int32 height)
|
|||||||
SceneRenderTask::SceneRenderTask(const SpawnParams& params)
|
SceneRenderTask::SceneRenderTask(const SpawnParams& params)
|
||||||
: RenderTask(params)
|
: RenderTask(params)
|
||||||
{
|
{
|
||||||
|
Buffers = New<RenderBuffers>();
|
||||||
|
|
||||||
|
// Initialize view
|
||||||
View.Position = Float3::Zero;
|
View.Position = Float3::Zero;
|
||||||
View.Direction = Float3::Forward;
|
View.Direction = Float3::Forward;
|
||||||
Buffers = New<RenderBuffers>();
|
Matrix::PerspectiveFov(PI_OVER_2, 1.0f, View.Near, View.Far, View.Projection);
|
||||||
|
View.NonJitteredProjection = View.Projection;
|
||||||
|
Matrix::Invert(View.Projection, View.IP);
|
||||||
|
View.SetFace(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneRenderTask::~SceneRenderTask()
|
SceneRenderTask::~SceneRenderTask()
|
||||||
|
|||||||
@@ -100,10 +100,8 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the order in which multiple volumes are blended together.
|
/// Gets the order in which multiple volumes are blended together. The volume with the highest priority takes precedence over all other overlapping volumes.
|
||||||
/// The volume with the highest priority takes precedence over all other overlapping volumes.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The result.</returns>
|
|
||||||
API_PROPERTY(Attributes="EditorDisplay(\"PostFx Volume\"), EditorOrder(60)")
|
API_PROPERTY(Attributes="EditorDisplay(\"PostFx Volume\"), EditorOrder(60)")
|
||||||
FORCE_INLINE int32 GetPriority() const
|
FORCE_INLINE int32 GetPriority() const
|
||||||
{
|
{
|
||||||
@@ -111,10 +109,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the order in which multiple volumes are blended together.
|
/// Sets the order in which multiple volumes are blended together. The volume with the highest priority takes precedence over all other overlapping volumes.
|
||||||
/// The volume with the highest priority takes precedence over all other overlapping volumes.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The value.</param>
|
|
||||||
API_PROPERTY() FORCE_INLINE void SetPriority(int32 value)
|
API_PROPERTY() FORCE_INLINE void SetPriority(int32 value)
|
||||||
{
|
{
|
||||||
_priority = value;
|
_priority = value;
|
||||||
@@ -123,7 +119,6 @@ public:
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the distance inside the volume at which blending with the volume's settings occurs.
|
/// Gets the distance inside the volume at which blending with the volume's settings occurs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The result.</returns>
|
|
||||||
API_PROPERTY(Attributes="EditorDisplay(\"PostFx Volume\"), EditorOrder(70)")
|
API_PROPERTY(Attributes="EditorDisplay(\"PostFx Volume\"), EditorOrder(70)")
|
||||||
FORCE_INLINE float GetBlendRadius() const
|
FORCE_INLINE float GetBlendRadius() const
|
||||||
{
|
{
|
||||||
@@ -133,7 +128,6 @@ public:
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the distance inside the volume at which blending with the volume's settings occurs.
|
/// Sets the distance inside the volume at which blending with the volume's settings occurs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The value.</param>
|
|
||||||
API_PROPERTY() void SetBlendRadius(float value)
|
API_PROPERTY() void SetBlendRadius(float value)
|
||||||
{
|
{
|
||||||
_blendRadius = Math::Clamp(value, 0.0f, 1000.0f);
|
_blendRadius = Math::Clamp(value, 0.0f, 1000.0f);
|
||||||
@@ -142,7 +136,6 @@ public:
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the amount of influence the volume's properties have. 0 is no effect; 1 is full effect.
|
/// Gets the amount of influence the volume's properties have. 0 is no effect; 1 is full effect.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The result.</returns>
|
|
||||||
API_PROPERTY(Attributes="EditorDisplay(\"PostFx Volume\"), EditorOrder(80)")
|
API_PROPERTY(Attributes="EditorDisplay(\"PostFx Volume\"), EditorOrder(80)")
|
||||||
FORCE_INLINE float GetBlendWeight() const
|
FORCE_INLINE float GetBlendWeight() const
|
||||||
{
|
{
|
||||||
@@ -152,18 +145,14 @@ public:
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the amount of influence the volume's properties have. 0 is no effect; 1 is full effect.
|
/// Sets the amount of influence the volume's properties have. 0 is no effect; 1 is full effect.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The value.</param>
|
|
||||||
API_PROPERTY() void SetBlendWeight(float value)
|
API_PROPERTY() void SetBlendWeight(float value)
|
||||||
{
|
{
|
||||||
_blendWeight = Math::Saturate(value);
|
_blendWeight = Math::Saturate(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the value indicating whether the bounds of the volume are taken into account.
|
/// Gets the value indicating whether the bounds of the volume are taken into account. If false, the volume affects the entire world, regardless of its bounds. If true, the volume only has an effect within its bounds.
|
||||||
/// If false, the volume affects the entire world, regardless of its bounds.
|
|
||||||
/// If true, the volume only has an effect within its bounds.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The result.</returns>
|
|
||||||
API_PROPERTY(Attributes="EditorDisplay(\"PostFx Volume\"), EditorOrder(90)")
|
API_PROPERTY(Attributes="EditorDisplay(\"PostFx Volume\"), EditorOrder(90)")
|
||||||
FORCE_INLINE bool GetIsBounded() const
|
FORCE_INLINE bool GetIsBounded() const
|
||||||
{
|
{
|
||||||
@@ -171,11 +160,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the value indicating whether the bounds of the volume are taken into account.
|
/// Sets the value indicating whether the bounds of the volume are taken into account. If false, the volume affects the entire world, regardless of its bounds. If true, the volume only has an effect within its bounds.
|
||||||
/// If false, the volume affects the entire world, regardless of its bounds.
|
|
||||||
/// If true, the volume only has an effect within its bounds.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">The value.</param>
|
|
||||||
API_PROPERTY() FORCE_INLINE void SetIsBounded(bool value)
|
API_PROPERTY() FORCE_INLINE void SetIsBounded(bool value)
|
||||||
{
|
{
|
||||||
_isBounded = value;
|
_isBounded = value;
|
||||||
|
|||||||
@@ -352,7 +352,7 @@ void NavMeshRuntime::EnsureCapacity(int32 tilesToAddCount)
|
|||||||
// Navmesh tiles capacity growing rule
|
// Navmesh tiles capacity growing rule
|
||||||
int32 newCapacity = capacity ? capacity : 32;
|
int32 newCapacity = capacity ? capacity : 32;
|
||||||
while (newCapacity < newTilesCount)
|
while (newCapacity < newTilesCount)
|
||||||
newCapacity = Math::RoundUpToPowerOf2(newCapacity);
|
newCapacity = Math::RoundUpToPowerOf2(newCapacity + 1);
|
||||||
|
|
||||||
LOG(Info, "Resizing navmesh {2} from {0} to {1} tiles capacity", capacity, newCapacity, Properties.Name);
|
LOG(Info, "Resizing navmesh {2} from {0} to {1} tiles capacity", capacity, newCapacity, Properties.Name);
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public:
|
|||||||
/// Gets the size of the box, measured in the object's local space.
|
/// Gets the size of the box, measured in the object's local space.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>The box size will be scaled by the actor's world scale. </remarks>
|
/// <remarks>The box size will be scaled by the actor's world scale. </remarks>
|
||||||
API_PROPERTY(Attributes="EditorOrder(100), DefaultValue(typeof(Vector3), \"100,100,100\"), EditorDisplay(\"Collider\")")
|
API_PROPERTY(Attributes="EditorOrder(100), DefaultValue(typeof(Float3), \"100,100,100\"), EditorDisplay(\"Collider\")")
|
||||||
FORCE_INLINE Float3 GetSize() const
|
FORCE_INLINE Float3 GetSize() const
|
||||||
{
|
{
|
||||||
return _size;
|
return _size;
|
||||||
|
|||||||
@@ -50,11 +50,16 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(FileSystemBase);
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="parentWindow">The parent window or null.</param>
|
/// <param name="parentWindow">The parent window or null.</param>
|
||||||
/// <param name="initialDirectory">The initial directory.</param>
|
/// <param name="initialDirectory">The initial directory.</param>
|
||||||
/// <param name="filter">The custom filter.</param>
|
/// <param name="filter">The file filter string as null-terminated pairs of name and list of extensions. Multiple file extensions must be separated with semicolon.</param>
|
||||||
/// <param name="multiSelect">True if allow multiple files to be selected, otherwise use single-file mode.</param>
|
/// <param name="multiSelect">True if allow multiple files to be selected, otherwise use single-file mode.</param>
|
||||||
/// <param name="title">The dialog title.</param>
|
/// <param name="title">The dialog title.</param>
|
||||||
/// <param name="filenames">The output names of the files picked by the user.</param>
|
/// <param name="filenames">The output names of the files picked by the user.</param>
|
||||||
/// <returns>True if failed, otherwise false.</returns>
|
/// <returns>True if failed, otherwise false.</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// Example file filters:
|
||||||
|
/// "All Files\0*.*"
|
||||||
|
/// "All Files\0*.*\0Image Files\0*.png;*.jpg"
|
||||||
|
/// </remarks>
|
||||||
API_FUNCTION() static bool ShowOpenFileDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& filter, bool multiSelect, const StringView& title, API_PARAM(Out) Array<String, HeapAllocation>& filenames);
|
API_FUNCTION() static bool ShowOpenFileDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& filter, bool multiSelect, const StringView& title, API_PARAM(Out) Array<String, HeapAllocation>& filenames);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -62,11 +67,16 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(FileSystemBase);
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="parentWindow">The parent window.</param>
|
/// <param name="parentWindow">The parent window.</param>
|
||||||
/// <param name="initialDirectory">The initial directory.</param>
|
/// <param name="initialDirectory">The initial directory.</param>
|
||||||
/// <param name="filter">The filter.</param>
|
/// <param name="filter">The file filter string as null-terminated pairs of name and list of extensions. Multiple file extensions must be separated with semicolon.</param>
|
||||||
/// <param name="multiSelect">True if allow multiple files to be selected, otherwise use single-file mode.</param>
|
/// <param name="multiSelect">True if allow multiple files to be selected, otherwise use single-file mode.</param>
|
||||||
/// <param name="title">The title.</param>
|
/// <param name="title">The title.</param>
|
||||||
/// <param name="filenames">The output names of the files picked by the user.</param>
|
/// <param name="filenames">The output names of the files picked by the user.</param>
|
||||||
/// <returns>True if failed, otherwise false.</returns>
|
/// <returns>True if failed, otherwise false.</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// Example file filters:
|
||||||
|
/// "All Files\0*.*"
|
||||||
|
/// "All Files\0*.*\0Image Files\0*.png;*.jpg"
|
||||||
|
/// </remarks>
|
||||||
API_FUNCTION() static bool ShowSaveFileDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& filter, bool multiSelect, const StringView& title, API_PARAM(Out) Array<String, HeapAllocation>& filenames);
|
API_FUNCTION() static bool ShowSaveFileDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& filter, bool multiSelect, const StringView& title, API_PARAM(Out) Array<String, HeapAllocation>& filenames);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -528,4 +528,17 @@ String StringUtils::ToString(double value)
|
|||||||
return String::Format(TEXT("{}"), value);
|
return String::Format(TEXT("{}"), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String StringUtils::GetZZString(const Char* str)
|
||||||
|
{
|
||||||
|
const Char* end = str;
|
||||||
|
while (*end != '\0')
|
||||||
|
{
|
||||||
|
end++;
|
||||||
|
if (*end == '\0')
|
||||||
|
end++;
|
||||||
|
}
|
||||||
|
const int len = end - str;
|
||||||
|
return String(str, len);
|
||||||
|
}
|
||||||
|
|
||||||
#undef STRING_UTILS_ITOSTR_BUFFER_SIZE
|
#undef STRING_UTILS_ITOSTR_BUFFER_SIZE
|
||||||
|
|||||||
@@ -43,7 +43,10 @@ void ThreadBase::SetPriority(ThreadPriority priority)
|
|||||||
void ThreadBase::Kill(bool waitForJoin)
|
void ThreadBase::Kill(bool waitForJoin)
|
||||||
{
|
{
|
||||||
if (!_isRunning)
|
if (!_isRunning)
|
||||||
|
{
|
||||||
|
ClearHandleInternal();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
ASSERT(GetID());
|
ASSERT(GetID());
|
||||||
const auto thread = static_cast<Thread*>(this);
|
const auto thread = static_cast<Thread*>(this);
|
||||||
|
|
||||||
@@ -105,7 +108,6 @@ int32 ThreadBase::Run()
|
|||||||
_callAfterWork = false;
|
_callAfterWork = false;
|
||||||
_runnable->AfterWork(false);
|
_runnable->AfterWork(false);
|
||||||
}
|
}
|
||||||
ClearHandleInternal();
|
|
||||||
_isRunning = false;
|
_isRunning = false;
|
||||||
ThreadExiting(thread, exitCode);
|
ThreadExiting(thread, exitCode);
|
||||||
ThreadRegistry::Remove(thread);
|
ThreadRegistry::Remove(thread);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ class IRunnable;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Base class for thread objects.
|
/// Base class for thread objects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>Ensure to call Kill or Join before deleting thread object.</remarks>
|
||||||
class FLAXENGINE_API ThreadBase : public Object, public NonCopyable
|
class FLAXENGINE_API ThreadBase : public Object, public NonCopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
|
|
||||||
#include "LinuxFileSystem.h"
|
#include "LinuxFileSystem.h"
|
||||||
#include "Engine/Platform/File.h"
|
#include "Engine/Platform/File.h"
|
||||||
|
#include "Engine/Platform/StringUtils.h"
|
||||||
#include "Engine/Core/Types/String.h"
|
#include "Engine/Core/Types/String.h"
|
||||||
|
#include "Engine/Core/Types/StringBuilder.h"
|
||||||
#include "Engine/Core/Types/StringView.h"
|
#include "Engine/Core/Types/StringView.h"
|
||||||
#include "Engine/Core/Types/TimeSpan.h"
|
#include "Engine/Core/Types/TimeSpan.h"
|
||||||
#include "Engine/Core/Math/Math.h"
|
#include "Engine/Core/Math/Math.h"
|
||||||
@@ -27,20 +29,38 @@ bool LinuxFileSystem::ShowOpenFileDialog(Window* parentWindow, const StringView&
|
|||||||
{
|
{
|
||||||
const StringAsANSI<> initialDirectoryAnsi(*initialDirectory, initialDirectory.Length());
|
const StringAsANSI<> initialDirectoryAnsi(*initialDirectory, initialDirectory.Length());
|
||||||
const StringAsANSI<> titleAnsi(*title, title.Length());
|
const StringAsANSI<> titleAnsi(*title, title.Length());
|
||||||
|
const char* initDir = initialDirectory.HasChars() ? initialDirectoryAnsi.Get() : ".";
|
||||||
char cmd[2048];
|
char cmd[2048];
|
||||||
if (FileSystem::FileExists(TEXT("/usr/bin/zenity")))
|
String xdgCurrentDesktop;
|
||||||
|
StringBuilder fileFilter;
|
||||||
|
Array<String> fileFilterEntries;
|
||||||
|
Platform::GetEnvironmentVariable(TEXT("XDG_CURRENT_DESKTOP"), xdgCurrentDesktop);
|
||||||
|
StringUtils::GetZZString(filter.Get()).Split('\0', fileFilterEntries);
|
||||||
|
|
||||||
|
const bool zenitySupported = FileSystem::FileExists(TEXT("/usr/bin/zenity"));
|
||||||
|
const bool kdialogSupported = FileSystem::FileExists(TEXT("/usr/bin/kdialog"));
|
||||||
|
if (zenitySupported && (xdgCurrentDesktop != TEXT("KDE") || !kdialogSupported)) // Prefer kdialog when running on KDE
|
||||||
{
|
{
|
||||||
// TODO: initialDirectory support
|
for (int32 i = 1; i < fileFilterEntries.Count(); i += 2)
|
||||||
// TODO: multiSelect support
|
{
|
||||||
// TODO: filter support
|
String extensions(fileFilterEntries[i]);
|
||||||
sprintf(cmd, "/usr/bin/zenity --modal --file-selection --title=\"%s\" ", titleAnsi.Get());
|
fileFilterEntries[i].Replace(TEXT(";"), TEXT(" "));
|
||||||
|
fileFilter.Append(String::Format(TEXT("{0}--file-filter=\"{1}|{2}\""), i > 1 ? TEXT(" ") : TEXT(""), fileFilterEntries[i-1].Get(), extensions.Get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(cmd, "/usr/bin/zenity --modal --file-selection %s--filename=\"%s\" --title=\"%s\" %s ", multiSelect ? "--multiple --separator=$'\n' " : " ", initDir, titleAnsi.Get(), fileFilter.ToStringView().ToStringAnsi().GetText());
|
||||||
}
|
}
|
||||||
else if (FileSystem::FileExists(TEXT("/usr/bin/kdialog")))
|
else if (kdialogSupported)
|
||||||
{
|
{
|
||||||
// TODO: multiSelect support
|
for (int32 i = 1; i < fileFilterEntries.Count(); i += 2)
|
||||||
// TODO: filter support
|
{
|
||||||
const char* initDir = initialDirectory.HasChars() ? initialDirectoryAnsi.Get() : ".";
|
String extensions(fileFilterEntries[i]);
|
||||||
sprintf(cmd, "/usr/bin/kdialog --getopenfilename \"%s\" --title \"%s\" ", initDir, titleAnsi.Get());
|
fileFilterEntries[i].Replace(TEXT(";"), TEXT(" "));
|
||||||
|
fileFilter.Append(String::Format(TEXT("{0}\"{1}({2})\""), i > 1 ? TEXT(" ") : TEXT(""), fileFilterEntries[i-1].Get(), extensions.Get()));
|
||||||
|
}
|
||||||
|
fileFilter.Append(String::Format(TEXT("{0}\"{1}({2})\""), TEXT(" "), TEXT("many things"), TEXT("*.png *.jpg")));
|
||||||
|
|
||||||
|
sprintf(cmd, "/usr/bin/kdialog --getopenfilename %s--title \"%s\" \"%s\" %s ", multiSelect ? "--multiple --separate-output " : " ", titleAnsi.Get(), initDir, fileFilter.ToStringView().ToStringAnsi().GetText());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ namespace FileSystemWatchers
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GetRootWatcher(event->wd)->OnEvent(name, FileSystemAction::Modify);
|
GetRootWatcher(event->wd)->OnEvent(name, FileSystemAction::Modify);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,7 +140,7 @@ namespace FileSystemWatchers
|
|||||||
|
|
||||||
void AddDirWatcher(const int rootFileDesc, const String& path)
|
void AddDirWatcher(const int rootFileDesc, const String& path)
|
||||||
{
|
{
|
||||||
auto watcher = New<FileSystemWatcher>(path, false, rootFileDesc);
|
auto watcher = New<FileSystemWatcher>(path, true, rootFileDesc);
|
||||||
Pair<String, LinuxFileSystemWatcher*> subDir = Pair<String, LinuxFileSystemWatcher*>(path, watcher);
|
Pair<String, LinuxFileSystemWatcher*> subDir = Pair<String, LinuxFileSystemWatcher*>(path, watcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,8 +183,16 @@ LinuxFileSystemWatcher::LinuxFileSystemWatcher(const String& directory, bool wit
|
|||||||
FileSystemWatchers::Watchers[WachedDirectory] = Pair<int, Pair<String, LinuxFileSystemWatcher*>>(rootWatcher, Pair<String, LinuxFileSystemWatcher*>(directory, this));
|
FileSystemWatchers::Watchers[WachedDirectory] = Pair<int, Pair<String, LinuxFileSystemWatcher*>>(rootWatcher, Pair<String, LinuxFileSystemWatcher*>(directory, this));
|
||||||
if (withSubDirs)
|
if (withSubDirs)
|
||||||
{
|
{
|
||||||
FileSystemWatchers::RootWatchers[WachedDirectory] = this;
|
if (rootWatcher == -1)
|
||||||
FileSystemWatchers::AddSubDirWatcher(WachedDirectory, directory);
|
{
|
||||||
|
FileSystemWatchers::RootWatchers[WachedDirectory] = this;
|
||||||
|
FileSystemWatchers::AddSubDirWatcher(WachedDirectory, directory);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FileSystemWatchers::RootWatchers[WachedDirectory] = FileSystemWatchers::RootWatchers[rootWatcher];
|
||||||
|
FileSystemWatchers::AddSubDirWatcher(rootWatcher, directory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FileSystemWatchers::Locker.Unlock();
|
FileSystemWatchers::Locker.Unlock();
|
||||||
|
|||||||
@@ -431,8 +431,11 @@ static int X11_MessageBoxCreateWindow(MessageBoxData* data)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
x = (X11_DisplayWidth(display, data->screen) - data->dialog_width) / 2;
|
int screenCount;
|
||||||
y = (X11_DisplayHeight(display, data->screen) - data->dialog_height) / 3;
|
X11::XineramaScreenInfo* xsi = X11::XineramaQueryScreens(xDisplay, &screenCount);
|
||||||
|
ASSERT(data->screen < screenCount);
|
||||||
|
x = (float)xsi[data->screen].x_org + ((float)xsi[data->screen].width - data->dialog_width) / 2;
|
||||||
|
y = (float)xsi[data->screen].y_org + ((float)xsi[data->screen].height - data->dialog_height) / 2;
|
||||||
}
|
}
|
||||||
X11::XMoveWindow(display, data->window, x, y);
|
X11::XMoveWindow(display, data->window, x, y);
|
||||||
|
|
||||||
@@ -840,17 +843,17 @@ int X11ErrorHandler(X11::Display* display, X11::XErrorEvent* event)
|
|||||||
|
|
||||||
int32 CalculateDpi()
|
int32 CalculateDpi()
|
||||||
{
|
{
|
||||||
// in X11 a screen is not necessarily identical to a desktop
|
int dpi = 96;
|
||||||
// so we need to stick to one type for pixel and physical size query
|
char* resourceString = X11::XResourceManagerString(xDisplay);
|
||||||
|
if (resourceString == NULL)
|
||||||
|
return dpi;
|
||||||
|
|
||||||
int screenIdx = 0;
|
char* type = NULL;
|
||||||
int widthMM = X11_DisplayWidthMM(xDisplay, screenIdx);
|
X11::XrmValue value;
|
||||||
int heightMM = X11_DisplayHeightMM(xDisplay, screenIdx);
|
X11::XrmDatabase database = X11::XrmGetStringDatabase(resourceString);
|
||||||
double xdpi = (widthMM ? X11_DisplayWidth(xDisplay, screenIdx) / (double)widthMM * 25.4 : 0);
|
if (X11::XrmGetResource(database, "Xft.dpi", "String", &type, &value) == 1 && value.addr != NULL)
|
||||||
double ydpi = (heightMM ? X11_DisplayHeight(xDisplay, screenIdx) / (double)heightMM * 25.4 : 0);
|
dpi = (int)atof(value.addr);
|
||||||
if (xdpi || ydpi)
|
return dpi;
|
||||||
return (int32)Math::Ceil((xdpi + ydpi) / (xdpi && ydpi ? 2 : 1));
|
|
||||||
return 96;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maps Flax key codes to X11 names for physical key locations.
|
// Maps Flax key codes to X11 names for physical key locations.
|
||||||
@@ -2101,6 +2104,7 @@ bool LinuxPlatform::Init()
|
|||||||
xAtomWmName = X11::XInternAtom(xDisplay, "_NET_WM_NAME", 0);
|
xAtomWmName = X11::XInternAtom(xDisplay, "_NET_WM_NAME", 0);
|
||||||
xAtomClipboard = X11::XInternAtom(xDisplay, "CLIPBOARD", 0);
|
xAtomClipboard = X11::XInternAtom(xDisplay, "CLIPBOARD", 0);
|
||||||
|
|
||||||
|
X11::XrmInitialize();
|
||||||
SystemDpi = CalculateDpi();
|
SystemDpi = CalculateDpi();
|
||||||
|
|
||||||
int cursorSize = X11::XcursorGetDefaultSize(xDisplay);
|
int cursorSize = X11::XcursorGetDefaultSize(xDisplay);
|
||||||
@@ -2806,6 +2810,7 @@ int32 LinuxProcess(const StringView& cmdLine, const StringView& workingDir, cons
|
|||||||
{
|
{
|
||||||
close(fildes[0]); // close the reading end of the pipe
|
close(fildes[0]); // close the reading end of the pipe
|
||||||
dup2(fildes[1], STDOUT_FILENO); // redirect stdout to pipe
|
dup2(fildes[1], STDOUT_FILENO); // redirect stdout to pipe
|
||||||
|
close(fildes[1]);
|
||||||
dup2(STDOUT_FILENO, STDERR_FILENO); // redirect stderr to stdout
|
dup2(STDOUT_FILENO, STDERR_FILENO); // redirect stderr to stdout
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2814,6 +2819,8 @@ int32 LinuxProcess(const StringView& cmdLine, const StringView& workingDir, cons
|
|||||||
{
|
{
|
||||||
LOG(Warning, " failed, errno={}", errno);
|
LOG(Warning, " failed, errno={}", errno);
|
||||||
}
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
_exit(1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2826,7 +2833,7 @@ int32 LinuxProcess(const StringView& cmdLine, const StringView& workingDir, cons
|
|||||||
{
|
{
|
||||||
char lineBuffer[1024];
|
char lineBuffer[1024];
|
||||||
close(fildes[1]); // close the writing end of the pipe
|
close(fildes[1]); // close the writing end of the pipe
|
||||||
FILE *stdPipe = fdopen(fildes[0], "r");
|
FILE* stdPipe = fdopen(fildes[0], "r");
|
||||||
while (fgets(lineBuffer, sizeof(lineBuffer), stdPipe) != NULL)
|
while (fgets(lineBuffer, sizeof(lineBuffer), stdPipe) != NULL)
|
||||||
{
|
{
|
||||||
char *p = lineBuffer + strlen(lineBuffer)-1;
|
char *p = lineBuffer + strlen(lineBuffer)-1;
|
||||||
@@ -2861,6 +2868,7 @@ int32 LinuxProcess(const StringView& cmdLine, const StringView& workingDir, cons
|
|||||||
returnCode = EPIPE;
|
returnCode = EPIPE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
close(fildes[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,11 @@ static X11::Time MouseLastButtonPressTime = 0;
|
|||||||
LinuxWindow::LinuxWindow(const CreateWindowSettings& settings)
|
LinuxWindow::LinuxWindow(const CreateWindowSettings& settings)
|
||||||
: WindowBase(settings)
|
: WindowBase(settings)
|
||||||
{
|
{
|
||||||
|
auto display = (X11::Display*)LinuxPlatform::GetXDisplay();
|
||||||
|
if (!display)
|
||||||
|
return;
|
||||||
|
auto screen = XDefaultScreen(display);
|
||||||
|
|
||||||
// Cache data
|
// Cache data
|
||||||
int32 width = Math::TruncToInt(settings.Size.X);
|
int32 width = Math::TruncToInt(settings.Size.X);
|
||||||
int32 height = Math::TruncToInt(settings.Size.Y);
|
int32 height = Math::TruncToInt(settings.Size.Y);
|
||||||
@@ -64,9 +69,21 @@ LinuxWindow::LinuxWindow(const CreateWindowSettings& settings)
|
|||||||
break;
|
break;
|
||||||
case WindowStartPosition::CenterScreen:
|
case WindowStartPosition::CenterScreen:
|
||||||
{
|
{
|
||||||
Float2 desktopSize = Platform::GetDesktopSize();
|
Rectangle desktopBounds;
|
||||||
x = Math::TruncToInt((desktopSize.X - _clientSize.X) * 0.5f);
|
int event, err;
|
||||||
y = Math::TruncToInt((desktopSize.Y - _clientSize.Y) * 0.5f);
|
const bool ok = X11::XineramaQueryExtension(display, &event, &err);
|
||||||
|
if (X11::XineramaQueryExtension(display, &event, &err))
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
X11::XineramaScreenInfo* xsi = X11::XineramaQueryScreens(display, &count);
|
||||||
|
ASSERT(screen < count);
|
||||||
|
desktopBounds = Rectangle(Float2((float)xsi[screen].x_org, (float)xsi[screen].y_org), Float2((float)xsi[screen].width, (float)xsi[screen].height));
|
||||||
|
X11::XFree(xsi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
desktopBounds = Rectangle(Float2::Zero, Platform::GetDesktopSize());
|
||||||
|
x = Math::TruncToInt(desktopBounds.Location.X + (desktopBounds.Size.X - _clientSize.X) * 0.5f);
|
||||||
|
y = Math::TruncToInt(desktopBounds.Location.Y + (desktopBounds.Size.Y - _clientSize.Y) * 0.5f);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WindowStartPosition::Manual:
|
case WindowStartPosition::Manual:
|
||||||
@@ -76,11 +93,6 @@ LinuxWindow::LinuxWindow(const CreateWindowSettings& settings)
|
|||||||
}
|
}
|
||||||
_resizeDisabled = !settings.HasSizingFrame;
|
_resizeDisabled = !settings.HasSizingFrame;
|
||||||
|
|
||||||
auto display = (X11::Display*)LinuxPlatform::GetXDisplay();
|
|
||||||
if (!display)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto screen = XDefaultScreen(display);
|
|
||||||
auto rootWindow = XRootWindow(display, screen);
|
auto rootWindow = XRootWindow(display, screen);
|
||||||
|
|
||||||
long visualMask = VisualScreenMask;
|
long visualMask = VisualScreenMask;
|
||||||
|
|||||||
@@ -438,6 +438,13 @@ public:
|
|||||||
static String ToString(uint64 value);
|
static String ToString(uint64 value);
|
||||||
static String ToString(float value);
|
static String ToString(float value);
|
||||||
static String ToString(double value);
|
static String ToString(double value);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Returns the String to double null-terminated string
|
||||||
|
// @param str Double null-terminated string
|
||||||
|
// @return Double null-terminated String
|
||||||
|
static String GetZZString(const Char* str);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline uint32 GetHash(const char* key)
|
inline uint32 GetHash(const char* key)
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ UnixThread* UnixThread::Setup(UnixThread* thread, uint32 stackSize)
|
|||||||
void UnixThread::Join()
|
void UnixThread::Join()
|
||||||
{
|
{
|
||||||
pthread_join(_thread, nullptr);
|
pthread_join(_thread, nullptr);
|
||||||
|
ClearHandleInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnixThread::ClearHandleInternal()
|
void UnixThread::ClearHandleInternal()
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ unsigned long Win32Thread::ThreadProc(void* pThis)
|
|||||||
void Win32Thread::Join()
|
void Win32Thread::Join()
|
||||||
{
|
{
|
||||||
WaitForSingleObject((HANDLE)_thread, INFINITE);
|
WaitForSingleObject((HANDLE)_thread, INFINITE);
|
||||||
|
ClearHandleInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Win32Thread::ClearHandleInternal()
|
void Win32Thread::ClearHandleInternal()
|
||||||
|
|||||||
@@ -98,10 +98,12 @@ bool TerrainManager::GetChunkGeometry(DrawCall& drawCall, int32 chunkSize, int32
|
|||||||
// Prepare
|
// Prepare
|
||||||
const int32 vertexCount = (chunkSize + 1) >> lodIndex;
|
const int32 vertexCount = (chunkSize + 1) >> lodIndex;
|
||||||
chunkSize = vertexCount - 1;
|
chunkSize = vertexCount - 1;
|
||||||
|
const bool indexUse16bits = chunkSize * chunkSize * vertexCount < MAX_uint16;
|
||||||
|
const int32 indexSize = indexUse16bits ? sizeof(uint16) : sizeof(uint32);
|
||||||
const int32 indexCount = chunkSize * chunkSize * 2 * 3;
|
const int32 indexCount = chunkSize * chunkSize * 2 * 3;
|
||||||
const int32 vertexCount2 = vertexCount * vertexCount;
|
const int32 vertexCount2 = vertexCount * vertexCount;
|
||||||
const int32 vbSize = sizeof(TerrainVertex) * vertexCount2;
|
const int32 vbSize = sizeof(TerrainVertex) * vertexCount2;
|
||||||
const int32 ibSize = sizeof(uint16) * indexCount;
|
const int32 ibSize = indexSize * indexCount;
|
||||||
TempData.Clear();
|
TempData.Clear();
|
||||||
TempData.EnsureCapacity(Math::Max(vbSize, ibSize));
|
TempData.EnsureCapacity(Math::Max(vbSize, ibSize));
|
||||||
|
|
||||||
@@ -140,26 +142,51 @@ bool TerrainManager::GetChunkGeometry(DrawCall& drawCall, int32 chunkSize, int32
|
|||||||
|
|
||||||
// Create index buffer
|
// Create index buffer
|
||||||
auto ib = GPUDevice::Instance->CreateBuffer(TEXT("TerrainChunk.IB"));
|
auto ib = GPUDevice::Instance->CreateBuffer(TEXT("TerrainChunk.IB"));
|
||||||
auto index = (uint16*)TempData.Get();
|
if (indexUse16bits)
|
||||||
for (int32 z = 0; z < chunkSize; z++)
|
|
||||||
{
|
{
|
||||||
for (int32 x = 0; x < chunkSize; x++)
|
auto index = (uint16*)TempData.Get();
|
||||||
|
for (int32 z = 0; z < chunkSize; z++)
|
||||||
{
|
{
|
||||||
const uint16 i00 = (x + 0) + (z + 0) * vertexCount;
|
for (int32 x = 0; x < chunkSize; x++)
|
||||||
const uint16 i10 = (x + 1) + (z + 0) * vertexCount;
|
{
|
||||||
const uint16 i11 = (x + 1) + (z + 1) * vertexCount;
|
const uint16 i00 = (x + 0) + (z + 0) * vertexCount;
|
||||||
const uint16 i01 = (x + 0) + (z + 1) * vertexCount;
|
const uint16 i10 = (x + 1) + (z + 0) * vertexCount;
|
||||||
|
const uint16 i11 = (x + 1) + (z + 1) * vertexCount;
|
||||||
|
const uint16 i01 = (x + 0) + (z + 1) * vertexCount;
|
||||||
|
|
||||||
*index++ = i00;
|
*index++ = i00;
|
||||||
*index++ = i11;
|
*index++ = i11;
|
||||||
*index++ = i10;
|
*index++ = i10;
|
||||||
|
|
||||||
*index++ = i00;
|
*index++ = i00;
|
||||||
*index++ = i01;
|
*index++ = i01;
|
||||||
*index++ = i11;
|
*index++ = i11;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
desc = GPUBufferDescription::Index(sizeof(uint16), indexCount, TempData.Get());
|
else
|
||||||
|
{
|
||||||
|
auto index = (uint32*)TempData.Get();
|
||||||
|
for (int32 z = 0; z < chunkSize; z++)
|
||||||
|
{
|
||||||
|
for (int32 x = 0; x < chunkSize; x++)
|
||||||
|
{
|
||||||
|
const uint32 i00 = (x + 0) + (z + 0) * vertexCount;
|
||||||
|
const uint32 i10 = (x + 1) + (z + 0) * vertexCount;
|
||||||
|
const uint32 i11 = (x + 1) + (z + 1) * vertexCount;
|
||||||
|
const uint32 i01 = (x + 0) + (z + 1) * vertexCount;
|
||||||
|
|
||||||
|
*index++ = i00;
|
||||||
|
*index++ = i11;
|
||||||
|
*index++ = i10;
|
||||||
|
|
||||||
|
*index++ = i00;
|
||||||
|
*index++ = i01;
|
||||||
|
*index++ = i11;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
desc = GPUBufferDescription::Index(indexSize, indexCount, TempData.Get());
|
||||||
if (ib->Init(desc))
|
if (ib->Init(desc))
|
||||||
{
|
{
|
||||||
vb->ReleaseGPU();
|
vb->ReleaseGPU();
|
||||||
|
|||||||
@@ -149,8 +149,7 @@ void JobSystemService::Dispose()
|
|||||||
{
|
{
|
||||||
if (Threads[i])
|
if (Threads[i])
|
||||||
{
|
{
|
||||||
if (Threads[i]->IsRunning())
|
Threads[i]->Kill(true);
|
||||||
Threads[i]->Kill(true);
|
|
||||||
Delete(Threads[i]);
|
Delete(Threads[i]);
|
||||||
Threads[i] = nullptr;
|
Threads[i] = nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,10 +98,7 @@ void ThreadPoolService::Dispose()
|
|||||||
// Delete threads
|
// Delete threads
|
||||||
for (int32 i = 0; i < ThreadPoolImpl::Threads.Count(); i++)
|
for (int32 i = 0; i < ThreadPoolImpl::Threads.Count(); i++)
|
||||||
{
|
{
|
||||||
if (ThreadPoolImpl::Threads[i]->IsRunning())
|
ThreadPoolImpl::Threads[i]->Kill(true);
|
||||||
{
|
|
||||||
ThreadPoolImpl::Threads[i]->Kill(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ThreadPoolImpl::Threads.ClearDelete();
|
ThreadPoolImpl::Threads.ClearDelete();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1155,6 +1155,8 @@ namespace Flax.Build.Bindings
|
|||||||
contents.Append("out ");
|
contents.Append("out ");
|
||||||
else if (parameterInfo.IsRef)
|
else if (parameterInfo.IsRef)
|
||||||
contents.Append("ref ");
|
contents.Append("ref ");
|
||||||
|
else if (parameterInfo.IsThis)
|
||||||
|
contents.Append("this ");
|
||||||
contents.Append(managedType);
|
contents.Append(managedType);
|
||||||
contents.Append(' ');
|
contents.Append(' ');
|
||||||
contents.Append(parameterInfo.Name);
|
contents.Append(parameterInfo.Name);
|
||||||
@@ -1214,6 +1216,8 @@ namespace Flax.Build.Bindings
|
|||||||
contents.Append("out ");
|
contents.Append("out ");
|
||||||
else if (parameterInfo.IsRef)
|
else if (parameterInfo.IsRef)
|
||||||
contents.Append("ref ");
|
contents.Append("ref ");
|
||||||
|
else if (parameterInfo.IsThis)
|
||||||
|
contents.Append("this ");
|
||||||
contents.Append(managedType);
|
contents.Append(managedType);
|
||||||
contents.Append(' ');
|
contents.Append(' ');
|
||||||
contents.Append(parameterInfo.Name);
|
contents.Append(parameterInfo.Name);
|
||||||
@@ -1913,6 +1917,8 @@ namespace Flax.Build.Bindings
|
|||||||
contents.Append("out ");
|
contents.Append("out ");
|
||||||
else if (parameterInfo.IsRef)
|
else if (parameterInfo.IsRef)
|
||||||
contents.Append("ref ");
|
contents.Append("ref ");
|
||||||
|
else if (parameterInfo.IsThis)
|
||||||
|
contents.Append("this ");
|
||||||
contents.Append(managedType);
|
contents.Append(managedType);
|
||||||
contents.Append(' ');
|
contents.Append(' ');
|
||||||
contents.Append(parameterInfo.Name);
|
contents.Append(parameterInfo.Name);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace Flax.Build.Bindings
|
|||||||
partial class BindingsGenerator
|
partial class BindingsGenerator
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<string, Type> TypeCache = new Dictionary<string, Type>();
|
private static readonly Dictionary<string, Type> TypeCache = new Dictionary<string, Type>();
|
||||||
private const int CacheVersion = 17;
|
private const int CacheVersion = 18;
|
||||||
|
|
||||||
internal static void Write(BinaryWriter writer, string e)
|
internal static void Write(BinaryWriter writer, string e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2487,7 +2487,10 @@ namespace Flax.Build.Bindings
|
|||||||
separator = true;
|
separator = true;
|
||||||
contents.Append(parameterInfo.Type).Append(' ').Append(parameterInfo.Name);
|
contents.Append(parameterInfo.Type).Append(' ').Append(parameterInfo.Name);
|
||||||
}
|
}
|
||||||
contents.Append(") override").AppendLine();
|
contents.Append(')');
|
||||||
|
if (functionInfo.IsConst)
|
||||||
|
contents.Append(" const");
|
||||||
|
contents.Append(" override").AppendLine();
|
||||||
contents.AppendLine(" {");
|
contents.AppendLine(" {");
|
||||||
// TODO: try to use ScriptVTable for interfaces implementation in scripting to call proper function instead of manually check at runtime
|
// TODO: try to use ScriptVTable for interfaces implementation in scripting to call proper function instead of manually check at runtime
|
||||||
if (functionInfo.Parameters.Count != 0)
|
if (functionInfo.Parameters.Count != 0)
|
||||||
|
|||||||
@@ -334,6 +334,9 @@ namespace Flax.Build.Bindings
|
|||||||
case "out":
|
case "out":
|
||||||
currentParam.IsOut = true;
|
currentParam.IsOut = true;
|
||||||
break;
|
break;
|
||||||
|
case "this":
|
||||||
|
currentParam.IsThis = true;
|
||||||
|
break;
|
||||||
case "attributes":
|
case "attributes":
|
||||||
currentParam.Attributes = tag.Value;
|
currentParam.Attributes = tag.Value;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace Flax.Build.Bindings
|
|||||||
public string Attributes;
|
public string Attributes;
|
||||||
public bool IsRef;
|
public bool IsRef;
|
||||||
public bool IsOut;
|
public bool IsOut;
|
||||||
|
public bool IsThis;
|
||||||
|
|
||||||
public bool HasDefaultValue => !string.IsNullOrEmpty(DefaultValue);
|
public bool HasDefaultValue => !string.IsNullOrEmpty(DefaultValue);
|
||||||
|
|
||||||
@@ -35,6 +36,7 @@ namespace Flax.Build.Bindings
|
|||||||
// TODO: convert into flags
|
// TODO: convert into flags
|
||||||
writer.Write(IsRef);
|
writer.Write(IsRef);
|
||||||
writer.Write(IsOut);
|
writer.Write(IsOut);
|
||||||
|
writer.Write(IsThis);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Read(BinaryReader reader)
|
public void Read(BinaryReader reader)
|
||||||
@@ -46,6 +48,7 @@ namespace Flax.Build.Bindings
|
|||||||
// TODO: convert into flags
|
// TODO: convert into flags
|
||||||
IsRef = reader.ReadBoolean();
|
IsRef = reader.ReadBoolean();
|
||||||
IsOut = reader.ReadBoolean();
|
IsOut = reader.ReadBoolean();
|
||||||
|
IsThis = reader.ReadBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
|||||||
@@ -33,7 +33,9 @@ namespace Flax.Build.Platforms
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Find Android SDK folder path
|
// Find Android SDK folder path
|
||||||
var sdkPath = Environment.GetEnvironmentVariable("ANDROID_SDK");
|
var sdkPath = Environment.GetEnvironmentVariable("ANDROID_HOME");
|
||||||
|
if (string.IsNullOrEmpty(sdkPath))
|
||||||
|
sdkPath = Environment.GetEnvironmentVariable("ANDROID_SDK");
|
||||||
if (string.IsNullOrEmpty(sdkPath))
|
if (string.IsNullOrEmpty(sdkPath))
|
||||||
{
|
{
|
||||||
// Look for adb in Android folders of some common locations
|
// Look for adb in Android folders of some common locations
|
||||||
@@ -53,6 +55,8 @@ namespace Flax.Build.Platforms
|
|||||||
foreach (string searchDir in searchDirs)
|
foreach (string searchDir in searchDirs)
|
||||||
{
|
{
|
||||||
string androidDir = Path.Combine(searchDir, "Android");
|
string androidDir = Path.Combine(searchDir, "Android");
|
||||||
|
if (!Directory.Exists(androidDir))
|
||||||
|
androidDir = Path.Combine(searchDir, "sdk");
|
||||||
if (Directory.Exists(androidDir))
|
if (Directory.Exists(androidDir))
|
||||||
{
|
{
|
||||||
string[] subDirs = Directory.GetDirectories(androidDir, "*sdk*", SearchOption.TopDirectoryOnly);
|
string[] subDirs = Directory.GetDirectories(androidDir, "*sdk*", SearchOption.TopDirectoryOnly);
|
||||||
@@ -72,7 +76,7 @@ namespace Flax.Build.Platforms
|
|||||||
}
|
}
|
||||||
else if (!Directory.Exists(sdkPath))
|
else if (!Directory.Exists(sdkPath))
|
||||||
{
|
{
|
||||||
Log.Warning(string.Format("Specified Android SDK folder in ANDROID_SDK env variable doesn't exist ({0})", sdkPath));
|
Log.Warning(string.Format("Specified Android SDK folder in ANDROID_HOME env variable doesn't exist ({0})", sdkPath));
|
||||||
}
|
}
|
||||||
if (string.IsNullOrEmpty(sdkPath))
|
if (string.IsNullOrEmpty(sdkPath))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,14 +24,24 @@ namespace Flax.Build.Platforms
|
|||||||
{
|
{
|
||||||
// Setup system paths
|
// Setup system paths
|
||||||
var includePath = Path.Combine(ToolsetRoot, "usr", "include");
|
var includePath = Path.Combine(ToolsetRoot, "usr", "include");
|
||||||
SystemIncludePaths.Add(includePath);
|
if (Directory.Exists(includePath))
|
||||||
|
SystemIncludePaths.Add(includePath);
|
||||||
|
else
|
||||||
|
Log.Error($"Missing toolset header files location {includePath}");
|
||||||
var cppIncludePath = Path.Combine(includePath, "c++", ClangVersion.ToString());
|
var cppIncludePath = Path.Combine(includePath, "c++", ClangVersion.ToString());
|
||||||
if (Directory.Exists(cppIncludePath))
|
if (Directory.Exists(cppIncludePath))
|
||||||
SystemIncludePaths.Add(cppIncludePath);
|
SystemIncludePaths.Add(cppIncludePath);
|
||||||
|
else
|
||||||
|
Log.Verbose($"Missing Clang {ClangVersion} C++ header files location {cppIncludePath}");
|
||||||
var clangLibPath = Path.Combine(ToolsetRoot, "usr", "lib", "clang");
|
var clangLibPath = Path.Combine(ToolsetRoot, "usr", "lib", "clang");
|
||||||
var clangIncludePath = Path.Combine(clangLibPath, ClangVersion.Major.ToString(), "include");
|
var clangIncludePath = Path.Combine(clangLibPath, ClangVersion.Major.ToString(), "include");
|
||||||
if (!Directory.Exists(clangIncludePath))
|
if (!Directory.Exists(clangIncludePath))
|
||||||
|
{
|
||||||
|
var error = $"Missing Clang {ClangVersion} header files location {clangIncludePath}";
|
||||||
clangIncludePath = Path.Combine(clangLibPath, ClangVersion.ToString(), "include");
|
clangIncludePath = Path.Combine(clangLibPath, ClangVersion.ToString(), "include");
|
||||||
|
if (!Directory.Exists(clangIncludePath))
|
||||||
|
Log.Error(error);
|
||||||
|
}
|
||||||
SystemIncludePaths.Add(clangIncludePath);
|
SystemIncludePaths.Add(clangIncludePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +85,8 @@ namespace Flax.Build.Platforms
|
|||||||
|
|
||||||
args.Add("-Wl,-rpath,\"\\$ORIGIN\"");
|
args.Add("-Wl,-rpath,\"\\$ORIGIN\"");
|
||||||
//args.Add("-Wl,--as-needed");
|
//args.Add("-Wl,--as-needed");
|
||||||
args.Add("-Wl,--copy-dt-needed-entries");
|
if (LdKind == "bfd")
|
||||||
|
args.Add("-Wl,--copy-dt-needed-entries");
|
||||||
args.Add("-Wl,--hash-style=gnu");
|
args.Add("-Wl,--hash-style=gnu");
|
||||||
//args.Add("-Wl,--build-id");
|
//args.Add("-Wl,--build-id");
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Flax.Build.Graph;
|
using Flax.Build.Graph;
|
||||||
using Flax.Build.NativeCpp;
|
using Flax.Build.NativeCpp;
|
||||||
@@ -61,6 +62,11 @@ namespace Flax.Build.Platforms
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected string LdPath;
|
protected string LdPath;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of the linker.
|
||||||
|
/// </summary>
|
||||||
|
protected string LdKind;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The clang tool version.
|
/// The clang tool version.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -91,7 +97,19 @@ namespace Flax.Build.Platforms
|
|||||||
RanlibPath = UnixPlatform.Which("ranlib");
|
RanlibPath = UnixPlatform.Which("ranlib");
|
||||||
StripPath = UnixPlatform.Which("strip");
|
StripPath = UnixPlatform.Which("strip");
|
||||||
ObjcopyPath = UnixPlatform.Which("objcopy");
|
ObjcopyPath = UnixPlatform.Which("objcopy");
|
||||||
LdPath = UnixPlatform.Which("ld");
|
|
||||||
|
LdPath = UnixPlatform.Which("ld.lld");
|
||||||
|
LdKind = "lld";
|
||||||
|
if (LdPath == null)
|
||||||
|
{
|
||||||
|
LdPath = UnixPlatform.Which("ld.gold");
|
||||||
|
LdKind = "gold";
|
||||||
|
}
|
||||||
|
if (LdPath == null)
|
||||||
|
{
|
||||||
|
LdPath = UnixPlatform.Which("ld"); // ld.bfd
|
||||||
|
LdKind = "bfd";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -478,6 +496,9 @@ namespace Flax.Build.Platforms
|
|||||||
// TODO: linkEnvironment.LinkTimeCodeGeneration
|
// TODO: linkEnvironment.LinkTimeCodeGeneration
|
||||||
// TODO: linkEnvironment.Optimization
|
// TODO: linkEnvironment.Optimization
|
||||||
// TODO: linkEnvironment.UseIncrementalLinking
|
// TODO: linkEnvironment.UseIncrementalLinking
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(LdKind))
|
||||||
|
args.Add(string.Format("-fuse-ld={0}", LdKind));
|
||||||
}
|
}
|
||||||
SetupLinkFilesArgs(graph, options, args, outputFilePath);
|
SetupLinkFilesArgs(graph, options, args, outputFilePath);
|
||||||
|
|
||||||
@@ -536,9 +557,10 @@ namespace Flax.Build.Platforms
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Input files
|
// Input files (link static libraries last)
|
||||||
task.PrerequisiteFiles.AddRange(linkEnvironment.InputFiles);
|
task.PrerequisiteFiles.AddRange(linkEnvironment.InputFiles);
|
||||||
foreach (var file in linkEnvironment.InputFiles)
|
foreach (var file in linkEnvironment.InputFiles.Where(x => !x.EndsWith(".a"))
|
||||||
|
.Concat(linkEnvironment.InputFiles.Where(x => x.EndsWith(".a"))))
|
||||||
{
|
{
|
||||||
args.Add(string.Format("\"{0}\"", file.Replace('\\', '/')));
|
args.Add(string.Format("\"{0}\"", file.Replace('\\', '/')));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user