Compare commits
91 Commits
d4d3933187
...
a38cc4d5cb
| Author | SHA1 | Date | |
|---|---|---|---|
| a38cc4d5cb | |||
| 1528d458d9 | |||
| 9e937776ac | |||
| a8aebdd01f | |||
| 998ed87029 | |||
| 279b3f8d9a | |||
| 738a506b6d | |||
| 0ddecdda1f | |||
| 94a22907e2 | |||
| d22a0aad0c | |||
| 9e035f3818 | |||
| 99a810458a | |||
| 2806578126 | |||
| 882e9a6623 | |||
| 14c156e351 | |||
| cd2151332e | |||
| 53bbca3779 | |||
| 51f4ac467e | |||
| 81427a7f9e | |||
| faadfb28b3 | |||
| 6bfe0bed35 | |||
| 6e4d5b853f | |||
| 0ebe23b482 | |||
| abbde5861a | |||
| b78d4349a7 | |||
| 3c1d3234b8 | |||
|
|
79baaae8e7 | ||
| 79289662ed | |||
| 89a2985ad8 | |||
| 1f0a521a87 | |||
| 8a0e43c38c | |||
| ac9022f585 | |||
| 314dbbbeaf | |||
| f13e09910d | |||
| 67b9511afe | |||
| 510c477468 | |||
| 697fcc18ab | |||
| 89ff08b3f2 | |||
| 9417585cd9 | |||
| f794bb5455 | |||
| bb7a5326cd | |||
| a998b2a44e | |||
| a69eb4296f | |||
| 727af5a5b9 | |||
| d545dd8219 | |||
| 29e385ab4b | |||
| 5c63e30b84 | |||
| 5187c677f1 | |||
| 1d43314efd | |||
| 91ef8c69db | |||
| f24251af82 | |||
| ed6e0138e6 | |||
| 4362cdb396 | |||
| 8146680b53 | |||
| 27aa2cfa1f | |||
|
|
1475075b00 | ||
|
|
702564366d | ||
|
|
e2fd3891d1 | ||
| f54e961f11 | |||
|
|
aabd70fbe7 | ||
| 428ebf7fd7 | |||
|
|
72f16d738f | ||
|
|
475818554d | ||
|
|
8ebb3a3215 | ||
|
|
2085a0bf25 | ||
|
|
d829461def | ||
|
|
2d169fdcd8 | ||
|
|
53ba5968fd | ||
|
|
cc735a1b6a | ||
|
|
970af7bdc8 | ||
|
|
2ff6a6dd9a | ||
|
|
ae3149c9c0 | ||
|
|
1a1bd56802 | ||
|
|
25b566b348 | ||
|
|
4fb95a704a | ||
|
|
5f09ef4c1f | ||
|
|
7bc099c32c | ||
|
|
9a59d0c5ed | ||
|
|
275ca296fa | ||
|
|
57af076c8d | ||
|
|
f905c49f0b | ||
|
|
c72fac335f | ||
|
|
030befdcaa | ||
|
|
3a591577ad | ||
|
|
8f9eaddbe5 | ||
|
|
ec11a79f55 | ||
|
|
55fd198102 | ||
|
|
425699c4b0 | ||
| af3badaeef | |||
|
|
873491eca2 | ||
|
|
3ba1ebb847 |
13
.github/workflows/cd.yml
vendored
13
.github/workflows/cd.yml
vendored
@@ -7,6 +7,7 @@ on:
|
||||
env:
|
||||
DOTNET_NOLOGO: true
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: false
|
||||
GIT_LFS_PULL_OPTIONS: '-c lfs.concurrenttransfers=10 -c lfs.transfer.maxretries=2'
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -20,7 +21,7 @@ jobs:
|
||||
- name: Checkout LFS
|
||||
run: |
|
||||
git lfs version
|
||||
git lfs pull
|
||||
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
|
||||
- name: Setup Vulkan
|
||||
uses: ./.github/actions/vulkan
|
||||
- name: Setup .NET
|
||||
@@ -53,7 +54,7 @@ jobs:
|
||||
- name: Checkout LFS
|
||||
run: |
|
||||
git lfs version
|
||||
git lfs pull
|
||||
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
|
||||
- name: Setup Vulkan
|
||||
uses: ./.github/actions/vulkan
|
||||
- name: Setup .NET
|
||||
@@ -83,7 +84,7 @@ jobs:
|
||||
- name: Checkout LFS
|
||||
run: |
|
||||
git lfs version
|
||||
git lfs pull
|
||||
GIT_TRACE=1 GIT_TRANSFER_TRACE=1 git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
||||
@@ -114,7 +115,7 @@ jobs:
|
||||
- name: Checkout LFS
|
||||
run: |
|
||||
git lfs version
|
||||
git lfs pull
|
||||
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
||||
@@ -147,7 +148,7 @@ jobs:
|
||||
- name: Checkout LFS
|
||||
run: |
|
||||
git lfs version
|
||||
git lfs pull
|
||||
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
|
||||
- name: Setup Vulkan
|
||||
uses: ./.github/actions/vulkan
|
||||
- name: Setup .NET
|
||||
@@ -175,7 +176,7 @@ jobs:
|
||||
- name: Checkout LFS
|
||||
run: |
|
||||
git lfs version
|
||||
git lfs pull
|
||||
git ${{ env.GIT_LFS_PULL_OPTIONS }} lfs pull
|
||||
- name: Setup Vulkan
|
||||
uses: ./.github/actions/vulkan
|
||||
- name: Setup .NET
|
||||
|
||||
@@ -31,7 +31,7 @@ Follow the instructions below to compile and run the engine from source.
|
||||
* Install Visual Studio 2022 or newer
|
||||
* 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 .NET 8 SDK for **Windows x64** (via Visual Studio Installer or [from web](https://dotnet.microsoft.com/en-us/download/dotnet/8.0))
|
||||
* Install .NET 8 or 9 SDK for **Windows x64** (via Visual Studio Installer or [from web](https://dotnet.microsoft.com/en-us/download/dotnet/8.0))
|
||||
* Install Git with LFS
|
||||
* Clone repo (with LFS)
|
||||
* Run **GenerateProjectFiles.bat**
|
||||
@@ -44,8 +44,9 @@ Follow the instructions below to compile and run the engine from source.
|
||||
## Linux
|
||||
|
||||
* Install Visual Studio Code
|
||||
* Install .NET 8 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0))
|
||||
* Install .NET 8 or 9 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0))
|
||||
* Ubuntu: `sudo apt install dotnet-sdk-8.0`
|
||||
* Arch: `sudo pacman -S dotnet-sdk-8.0 dotnet-runtime-8.0 dotnet-targeting-pack-8.0 dotnet-host`
|
||||
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
|
||||
* Ubuntu: `sudo apt install vulkan-sdk`
|
||||
* Arch: `sudo pacman -S spirv-tools vulkan-headers vulkan-tools vulkan-validation-layers`
|
||||
@@ -67,12 +68,12 @@ Follow the instructions below to compile and run the engine from source.
|
||||
## Mac
|
||||
|
||||
* Install XCode
|
||||
* Install .NET 8 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0))
|
||||
* Install .NET 8 or 9 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0))
|
||||
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
|
||||
* Clone repo (with LFS)
|
||||
* Run `GenerateProjectFiles.command`
|
||||
* Open workspace with XCode or Visual Studio Code
|
||||
* Build and run (configuration `Editor.Mac.Development`)
|
||||
* Build and run (configuration `Editor.Mac.Development`)
|
||||
|
||||
#### Troubleshooting
|
||||
|
||||
|
||||
@@ -750,7 +750,8 @@ namespace FlaxEditor.Content
|
||||
|
||||
// Draw short name
|
||||
Render2D.PushClip(ref textRect);
|
||||
Render2D.DrawText(style.FontMedium, ShowFileExtension || view.ShowFileExtensions ? FileName : ShortName, textRect, style.Foreground, nameAlignment, TextAlignment.Center, TextWrapping.WrapWords, 1f, 0.95f);
|
||||
var scale = 0.95f * view.ViewScale;
|
||||
Render2D.DrawText(style.FontMedium, ShowFileExtension || view.ShowFileExtensions ? FileName : ShortName, textRect, style.Foreground, nameAlignment, TextAlignment.Center, TextWrapping.WrapWords, 1f, scale);
|
||||
Render2D.PopClip();
|
||||
|
||||
if (IsBeingCut)
|
||||
|
||||
@@ -883,7 +883,7 @@ namespace FlaxEditor.CustomEditors
|
||||
/// </summary>
|
||||
protected virtual void ClearToken()
|
||||
{
|
||||
ParentEditor.ClearToken();
|
||||
ParentEditor?.ClearToken();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using System;
|
||||
using System.Linq;
|
||||
using FlaxEditor.Content;
|
||||
using FlaxEditor.GUI;
|
||||
using FlaxEditor.GUI.Drag;
|
||||
using FlaxEditor.Scripting;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
@@ -156,6 +157,17 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
private Rectangle DropdownRect => new Rectangle(Width - DropdownIconSize - DropdownIconMargin, DropdownIconMargin, DropdownIconSize, DropdownIconSize);
|
||||
|
||||
public Action ShowPicker;
|
||||
public Action<ContentItem> OnAssetDropped;
|
||||
|
||||
private DragItems _dragItems;
|
||||
private DragHandlers _dragHandlers;
|
||||
private bool _hasValidDragOver;
|
||||
private Func<ContentItem, bool> _validate;
|
||||
|
||||
public void SetValidationMethod(Func<ContentItem, bool> validate)
|
||||
{
|
||||
_validate = validate;
|
||||
}
|
||||
|
||||
public override void Draw()
|
||||
{
|
||||
@@ -164,6 +176,14 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
var style = FlaxEngine.GUI.Style.Current;
|
||||
var dropdownRect = DropdownRect;
|
||||
Render2D.DrawSprite(style.ArrowDown, dropdownRect, Enabled ? (DropdownRect.Contains(PointFromWindow(RootWindow.MousePosition)) ? style.BorderSelected : style.Foreground) : style.ForegroundDisabled);
|
||||
|
||||
// Check if drag is over
|
||||
if (IsDragOver && _hasValidDragOver)
|
||||
{
|
||||
var bounds = new Rectangle(Float2.Zero, Size);
|
||||
Render2D.FillRectangle(bounds, style.Selection);
|
||||
Render2D.DrawRectangle(bounds, style.SelectionBorder);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OnMouseDown(Float2 location, MouseButton button)
|
||||
@@ -207,6 +227,68 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private DragDropEffect DragEffect => _hasValidDragOver ? DragDropEffect.Move : DragDropEffect.None;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DragDropEffect OnDragEnter(ref Float2 location, DragData data)
|
||||
{
|
||||
base.OnDragEnter(ref location, data);
|
||||
|
||||
// Ensure to have valid drag helpers (uses lazy init)
|
||||
if (_dragItems == null)
|
||||
_dragItems = new DragItems(ValidateDragAsset);
|
||||
if (_dragHandlers == null)
|
||||
{
|
||||
_dragHandlers = new DragHandlers
|
||||
{
|
||||
_dragItems,
|
||||
};
|
||||
}
|
||||
|
||||
_hasValidDragOver = _dragHandlers.OnDragEnter(data) != DragDropEffect.None;
|
||||
|
||||
|
||||
return DragEffect;
|
||||
}
|
||||
|
||||
private bool ValidateDragAsset(ContentItem contentItem)
|
||||
{
|
||||
// Load or get asset
|
||||
return _validate?.Invoke(contentItem) ?? false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DragDropEffect OnDragMove(ref Float2 location, DragData data)
|
||||
{
|
||||
base.OnDragMove(ref location, data);
|
||||
|
||||
return DragEffect;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDragLeave()
|
||||
{
|
||||
_hasValidDragOver = false;
|
||||
_dragHandlers.OnDragLeave();
|
||||
|
||||
base.OnDragLeave();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DragDropEffect OnDragDrop(ref Float2 location, DragData data)
|
||||
{
|
||||
var result = DragEffect;
|
||||
|
||||
base.OnDragDrop(ref location, data);
|
||||
|
||||
if (_dragItems.HasValidDrag)
|
||||
{
|
||||
OnAssetDropped(_dragItems.Objects[0]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private TextBoxWithPicker _textBox;
|
||||
@@ -221,13 +303,21 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
{
|
||||
if (HasDifferentTypes)
|
||||
return;
|
||||
|
||||
_validator = new AssetPickerValidator(ScriptType.Null);
|
||||
_textBox = layout.Custom<TextBoxWithPicker>().CustomControl;
|
||||
_textBox.ShowPicker = OnShowPicker;
|
||||
_textBox.OnAssetDropped = OnItemDropped;
|
||||
_textBox.EditEnd += OnEditEnd;
|
||||
_validator = new AssetPickerValidator(ScriptType.Null);
|
||||
_textBox.SetValidationMethod(_validator.IsValid);
|
||||
AssetRefEditor.ApplyAssetReferenceAttribute(Values, out _, _validator);
|
||||
}
|
||||
|
||||
private void OnItemDropped(ContentItem item)
|
||||
{
|
||||
SetPickerPath(item);
|
||||
}
|
||||
|
||||
private void OnShowPicker()
|
||||
{
|
||||
if (_validator.AssetType != ScriptType.Null)
|
||||
|
||||
@@ -641,7 +641,68 @@ namespace FlaxEditor
|
||||
DrawControlWidget(uiControl, ref eu, ref mousePos, ref widgetHandleSize, viewScale, new Float2(0, -1), CursorType.SizeNS);
|
||||
DrawControlWidget(uiControl, ref eb, ref mousePos, ref widgetHandleSize, viewScale, new Float2(0, 1), CursorType.SizeNS);
|
||||
|
||||
// TODO: draw anchors
|
||||
// Draw pivot
|
||||
var pivotSize = 8.0f;
|
||||
if (viewScale < 0.7f)
|
||||
pivotSize *= viewScale;
|
||||
var pivotX = Mathf.Remap(control.Pivot.X, 0, 1, bounds.Location.X, bounds.Location.X + bounds.Width);
|
||||
var pivotY = Mathf.Remap(control.Pivot.Y, 0, 1, bounds.Location.Y, bounds.Location.Y + bounds.Height);
|
||||
var pivotLoc = control.PointToParent(this, new Float2(pivotX, pivotY));
|
||||
var pivotRect = new Rectangle(pivotLoc - pivotSize * 0.5f, new Float2(pivotSize));
|
||||
var pivotColor = options.UIPivotColor;
|
||||
Render2D.FillRectangle(pivotRect, pivotColor);
|
||||
|
||||
// Draw anchors
|
||||
var controlParent = control.Parent;
|
||||
if (controlParent != null)
|
||||
{
|
||||
var parentBounds = controlParent.EditorBounds;
|
||||
var anchorMin = control.AnchorMin;
|
||||
var anchorMax = control.AnchorMax;
|
||||
var newMinX = Mathf.Remap(anchorMin.X, 0, 1, parentBounds.UpperLeft.X, parentBounds.UpperRight.X);
|
||||
var newMinY = Mathf.Remap(anchorMin.Y, 0, 1, parentBounds.UpperLeft.Y, parentBounds.LowerLeft.Y);
|
||||
var newMaxX = Mathf.Remap(anchorMax.X, 0, 1, parentBounds.UpperLeft.X, parentBounds.UpperRight.X);
|
||||
var newMaxY = Mathf.Remap(anchorMax.Y, 0, 1, parentBounds.UpperLeft.Y, parentBounds.LowerLeft.Y);
|
||||
|
||||
var anchorUpperLeft = controlParent.PointToParent(this, new Float2(newMinX, newMinY));
|
||||
var anchorUpperRight = controlParent.PointToParent(this, new Float2(newMaxX, newMinY));
|
||||
var anchorLowerLeft = controlParent.PointToParent(this, new Float2(newMinX, newMaxY));
|
||||
var anchorLowerRight = controlParent.PointToParent(this, new Float2(newMaxX, newMaxY));
|
||||
|
||||
var anchorRectSize = 8.0f;
|
||||
if (viewScale < 0.7f)
|
||||
anchorRectSize *= viewScale;
|
||||
|
||||
// Make anchor rects and rotate if parent is rotated.
|
||||
var parentRotation = controlParent.Rotation * Mathf.DegreesToRadians;
|
||||
|
||||
var rect1Axis = new Float2(-1, -1);
|
||||
var rect1 = new Rectangle(anchorUpperLeft +
|
||||
new Float2(anchorRectSize * rect1Axis.X * Mathf.Cos(parentRotation) - anchorRectSize * rect1Axis.Y * Mathf.Sin(parentRotation),
|
||||
anchorRectSize * rect1Axis.Y * Mathf.Cos(parentRotation) + anchorRectSize * rect1Axis.X * Mathf.Sin(parentRotation)) - anchorRectSize * 0.5f, new Float2(anchorRectSize));
|
||||
var rect2Axis = new Float2(1, -1);
|
||||
var rect2 = new Rectangle(anchorUpperRight +
|
||||
new Float2(anchorRectSize * rect2Axis.X * Mathf.Cos(parentRotation) - anchorRectSize * rect2Axis.Y * Mathf.Sin(parentRotation),
|
||||
anchorRectSize * rect2Axis.Y * Mathf.Cos(parentRotation) + anchorRectSize * rect2Axis.X * Mathf.Sin(parentRotation)) - anchorRectSize * 0.5f, new Float2(anchorRectSize));
|
||||
var rect3Axis = new Float2(-1, 1);
|
||||
var rect3 = new Rectangle(anchorLowerLeft +
|
||||
new Float2(anchorRectSize * rect3Axis.X * Mathf.Cos(parentRotation) - anchorRectSize * rect3Axis.Y * Mathf.Sin(parentRotation),
|
||||
anchorRectSize * rect3Axis.Y * Mathf.Cos(parentRotation) + anchorRectSize * rect3Axis.X * Mathf.Sin(parentRotation)) - anchorRectSize * 0.5f, new Float2(anchorRectSize));
|
||||
var rect4Axis = new Float2(1, 1);
|
||||
var rect4 = new Rectangle(anchorLowerRight +
|
||||
new Float2(anchorRectSize * rect4Axis.X * Mathf.Cos(parentRotation) - anchorRectSize * rect4Axis.Y * Mathf.Sin(parentRotation),
|
||||
anchorRectSize * rect4Axis.Y * Mathf.Cos(parentRotation) + anchorRectSize * rect4Axis.X * Mathf.Sin(parentRotation)) - anchorRectSize * 0.5f, new Float2(anchorRectSize));
|
||||
|
||||
var rectColor = options.UIAnchorColor;
|
||||
Render2D.DrawLine(anchorUpperLeft, anchorUpperRight, rectColor);
|
||||
Render2D.DrawLine(anchorUpperRight, anchorLowerRight, rectColor);
|
||||
Render2D.DrawLine(anchorLowerRight, anchorLowerLeft, rectColor);
|
||||
Render2D.DrawLine(anchorLowerLeft, anchorUpperLeft, rectColor);
|
||||
Render2D.FillRectangle(rect1, rectColor);
|
||||
Render2D.FillRectangle(rect2, rectColor);
|
||||
Render2D.FillRectangle(rect3, rectColor);
|
||||
Render2D.FillRectangle(rect4, rectColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -651,8 +712,7 @@ namespace FlaxEditor
|
||||
var control = uiControl.Control;
|
||||
var rotation = control.Rotation;
|
||||
var rotationInRadians = rotation * Mathf.DegreesToRadians;
|
||||
var rect = new Rectangle(
|
||||
(pos +
|
||||
var rect = new Rectangle((pos +
|
||||
new Float2(resizeAxis.X * Mathf.Cos(rotationInRadians) - resizeAxis.Y * Mathf.Sin(rotationInRadians),
|
||||
resizeAxis.Y * Mathf.Cos(rotationInRadians) + resizeAxis.X * Mathf.Sin(rotationInRadians)) * 10 * scale) - size * 0.5f,
|
||||
size);
|
||||
@@ -714,16 +774,15 @@ namespace FlaxEditor
|
||||
|
||||
private bool RayCastControl(ref Float2 location, out Control hit)
|
||||
{
|
||||
#if false
|
||||
// Raycast only controls with content (eg. skips transparent panels)
|
||||
return RayCastChildren(ref location, out hit);
|
||||
#else
|
||||
// Find any control under mouse (hierarchical)
|
||||
hit = GetChildAtRecursive(location);
|
||||
// First, raycast only controls with content (eg. skips transparent panels)
|
||||
RayCastChildren(ref location, out hit);
|
||||
|
||||
// If raycast failed, then find any control under mouse (hierarchical)
|
||||
hit = hit ?? GetChildAtRecursive(location);
|
||||
if (hit is View || hit is CanvasContainer)
|
||||
hit = null;
|
||||
|
||||
return hit != null;
|
||||
#endif
|
||||
}
|
||||
|
||||
private UIControlNode FindUIControlNode(Control control)
|
||||
|
||||
@@ -39,6 +39,20 @@ namespace FlaxEditor.Options
|
||||
[EditorDisplay("UI Gizmo", "UI Control Outline Size"), EditorOrder(103), Tooltip("The size of the selection outline for UI controls.")]
|
||||
public float UISelectionOutlineSize { get; set; } = 2.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pivot color for the UI Gizmo.
|
||||
/// </summary>
|
||||
[DefaultValue(typeof(Color), "0.0,0.5725,0.8,0.5")]
|
||||
[EditorDisplay("UI Gizmo", "Pivot Color"), EditorOrder(103), Tooltip("The color of the pivot for the UI Gizmo.")]
|
||||
public Color UIPivotColor { get; set; } = new Color(0.0f, 0.5725f, 0.8f, 0.5f);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the anchor color for the UI Gizmo.
|
||||
/// </summary>
|
||||
[DefaultValue(typeof(Color), "0.8392,0.8471,0.8706,0.5")]
|
||||
[EditorDisplay("UI Gizmo", "Anchor Color"), EditorOrder(103), Tooltip("The color of the anchors for the UI Gizmo.")]
|
||||
public Color UIAnchorColor { get; set; } = new Color(0.8392f, 0.8471f, 0.8706f, 0.5f);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the transform gizmo size.
|
||||
/// </summary>
|
||||
|
||||
@@ -215,10 +215,10 @@ namespace FlaxEditor.SceneGraph
|
||||
public override bool CanDuplicate => (_actor.HideFlags & HideFlags.HideInHierarchy) == 0;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsActive => _actor.IsActive;
|
||||
public override bool IsActive => _actor?.IsActive ?? false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsActiveInHierarchy => _actor.IsActiveInHierarchy;
|
||||
public override bool IsActiveInHierarchy => _actor?.IsActiveInHierarchy ?? false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int OrderInParent
|
||||
|
||||
@@ -924,6 +924,25 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
(int)ModuleType.Initialize,
|
||||
},
|
||||
},
|
||||
new NodeArchetype
|
||||
{
|
||||
TypeID = 216,
|
||||
Create = CreateParticleModuleNode,
|
||||
Title = "Rotate Position Shape",
|
||||
Description = "Rotate the shape.",
|
||||
Flags = DefaultModuleFlags,
|
||||
Size = new Float2(200, 1 * Surface.Constants.LayoutOffsetY),
|
||||
DefaultValues = new object[]
|
||||
{
|
||||
true,
|
||||
(int)ModuleType.Initialize,
|
||||
Quaternion.Identity,
|
||||
},
|
||||
Elements = new []
|
||||
{
|
||||
NodeElementArchetype.Factory.Input(-0.5f, "Rotation", true, typeof(Quaternion), 0, 2),
|
||||
}
|
||||
},
|
||||
GetParticleAttribute(ModuleType.Initialize, 250, "Set Position", "Sets the particle position", typeof(Float3), Float3.Zero),
|
||||
GetParticleAttribute(ModuleType.Initialize, 251, "Set Lifetime", "Sets the particle lifetime (in seconds)", typeof(float), 10.0f),
|
||||
GetParticleAttribute(ModuleType.Initialize, 252, "Set Age", "Sets the particle age (in seconds)", typeof(float), 0.0f),
|
||||
|
||||
@@ -135,6 +135,8 @@ namespace FlaxEditor.Viewport.Cameras
|
||||
float a = Mathf.Saturate(progress);
|
||||
a = a * a * a;
|
||||
var targetTransform = Transform.Lerp(_startMove, _endMove, a);
|
||||
if (progress >= 1.0f)
|
||||
targetTransform = _endMove; // Be precise
|
||||
targetTransform.Scale = Vector3.Zero;
|
||||
Viewport.ViewPosition = targetTransform.Translation;
|
||||
Viewport.ViewOrientation = targetTransform.Orientation;
|
||||
|
||||
@@ -233,13 +233,11 @@ namespace FlaxEditor.Viewport
|
||||
{
|
||||
if (Mathf.Abs(_movementSpeed - _maxMovementSpeed) < Mathf.Epsilon || Mathf.Abs(_movementSpeed - _minMovementSpeed) < Mathf.Epsilon)
|
||||
return "{0:0.##}";
|
||||
|
||||
if (_movementSpeed < 10.0f)
|
||||
return "{0:0.00}";
|
||||
else if (_movementSpeed < 100.0f)
|
||||
if (_movementSpeed < 100.0f)
|
||||
return "{0:0.0}";
|
||||
else
|
||||
return "{0:#}";
|
||||
return "{0:#}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,11 +288,6 @@ namespace FlaxEditor.Viewport
|
||||
/// </summary>
|
||||
public Float2 MousePositionDelta => _mouseDelta;
|
||||
|
||||
/// <summary>
|
||||
/// Camera's pitch angle clamp range (in degrees).
|
||||
/// </summary>
|
||||
public Float2 CamPitchAngles = new Float2(-88, 88);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the view transform.
|
||||
/// </summary>
|
||||
@@ -330,7 +323,7 @@ namespace FlaxEditor.Viewport
|
||||
get => Float3.Forward * ViewOrientation;
|
||||
set
|
||||
{
|
||||
var right = Float3.Cross(value, Float3.Up);
|
||||
var right = Mathf.Abs(Float3.Dot(value, Float3.Up)) < 1.0f - Mathf.Epsilon ? Float3.Cross(value, Float3.Up) : Float3.Forward;
|
||||
var up = Float3.Cross(right, value);
|
||||
ViewOrientation = Quaternion.LookRotation(value, up);
|
||||
}
|
||||
@@ -380,7 +373,11 @@ namespace FlaxEditor.Viewport
|
||||
public float Pitch
|
||||
{
|
||||
get => _pitch;
|
||||
set => _pitch = Mathf.Clamp(value, CamPitchAngles.X, CamPitchAngles.Y);
|
||||
set
|
||||
{
|
||||
var pitchLimit = _isOrtho ? new Float2(-90, 90) : new Float2(-88, 88);
|
||||
_pitch = Mathf.Clamp(value, pitchLimit.X, pitchLimit.Y);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1160,8 +1157,7 @@ namespace FlaxEditor.Viewport
|
||||
/// <param name="orientation">The orientation.</param>
|
||||
protected void OrientViewport(Quaternion orientation)
|
||||
{
|
||||
var quat = orientation;
|
||||
OrientViewport(ref quat);
|
||||
OrientViewport(ref orientation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1372,7 +1368,7 @@ namespace FlaxEditor.Viewport
|
||||
{
|
||||
var direction = ViewDirection;
|
||||
var target = position + direction;
|
||||
var right = Float3.Normalize(Float3.Cross(Float3.Up, direction));
|
||||
var right = Mathf.Abs(Float3.Dot(direction, Float3.Up)) < 1.0f - Mathf.Epsilon ? Float3.Normalize(Float3.Cross(Float3.Up, direction)) : Float3.Forward;
|
||||
var up = Float3.Normalize(Float3.Cross(direction, right));
|
||||
Matrix.LookAt(ref position, ref target, ref up, out result);
|
||||
}
|
||||
|
||||
@@ -476,9 +476,9 @@ void Spline::GetKeyframes(MArray* data)
|
||||
Platform::MemoryCopy(MCore::Array::GetAddress(data), Curve.GetKeyframes().Get(), sizeof(Keyframe) * Curve.GetKeyframes().Count());
|
||||
}
|
||||
|
||||
void Spline::SetKeyframes(MArray* data)
|
||||
void Spline::SetKeyframes(MArray* data, int32 keySize)
|
||||
{
|
||||
Curve = Span<byte>((const byte*)MCore::Array::GetAddress(data), MCore::Array::GetLength(data));
|
||||
Curve = Span<byte>(MCore::Array::GetAddress<byte>(data), keySize * MCore::Array::GetLength(data));
|
||||
UpdateSpline();
|
||||
}
|
||||
|
||||
|
||||
@@ -372,7 +372,7 @@ private:
|
||||
// Internal bindings
|
||||
#if !COMPILE_WITHOUT_CSHARP
|
||||
API_FUNCTION(NoProxy) void GetKeyframes(MArray* data);
|
||||
API_FUNCTION(NoProxy) void SetKeyframes(MArray* data);
|
||||
API_FUNCTION(NoProxy) void SetKeyframes(MArray* data, int32 keySize);
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace FlaxEngine
|
||||
if (value == null)
|
||||
value = Utils.GetEmptyArray<BezierCurve<Transform>.Keyframe>();
|
||||
_keyframes = null;
|
||||
Internal_SetKeyframes(__unmanagedPtr, value);
|
||||
Internal_SetKeyframes(__unmanagedPtr, value, System.Runtime.CompilerServices.Unsafe.SizeOf<BezierCurve<Transform>.Keyframe>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1150,6 +1150,47 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode*
|
||||
// Not supported
|
||||
break;
|
||||
}
|
||||
// Rotate Position Shape
|
||||
case 216:
|
||||
{
|
||||
PARTICLE_EMITTER_MODULE("Rotate Position Shape");
|
||||
auto& positionAttr = context.Data->Buffer->Layout->Attributes[node->Attributes[0]];
|
||||
|
||||
byte* positionPtr = start + positionAttr.Offset;
|
||||
|
||||
auto quatBox = node->GetBox(0);
|
||||
|
||||
#define INPUTS_FETCH() \
|
||||
const Quaternion quat = (Quaternion)GetValue(quatBox, 2);
|
||||
#define LOGIC() \
|
||||
Quaternion nq = Quaternion::Invert(quat); \
|
||||
Float3 v3 = *((Float3*)positionPtr); \
|
||||
Quaternion q = Quaternion(v3.X, v3.Y, v3.Z, 0.0f); \
|
||||
Quaternion rq = quat * (q * nq); \
|
||||
*(Float3*)positionPtr = Float3(rq.X, rq.Y, rq.Z); \
|
||||
positionPtr += stride;
|
||||
|
||||
if (node->UsePerParticleDataResolve())
|
||||
{
|
||||
for (int32 particleIndex = particlesStart; particleIndex < particlesEnd; particleIndex++)
|
||||
{
|
||||
context.ParticleIndex = particleIndex;
|
||||
INPUTS_FETCH();
|
||||
LOGIC();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
INPUTS_FETCH();
|
||||
for (int32 particleIndex = particlesStart; particleIndex < particlesEnd; particleIndex++)
|
||||
{
|
||||
LOGIC();
|
||||
}
|
||||
}
|
||||
#undef INPUTS_FETCH
|
||||
#undef LOGIC
|
||||
break;
|
||||
}
|
||||
|
||||
// Helper macros for collision modules to share the code
|
||||
#define COLLISION_BEGIN() \
|
||||
|
||||
@@ -632,6 +632,20 @@ void ParticleEmitterGPUGenerator::ProcessModule(Node* node)
|
||||
), position.Value, param.ShaderName, wsPos);
|
||||
break;
|
||||
}
|
||||
// Rotate position shape
|
||||
case 216:
|
||||
{
|
||||
auto positionAttr = AccessParticleAttribute(node, nodeGpu->Attributes[0], AccessMode::Write);
|
||||
const Value quaternion = GetValue(node->GetBox(0), 2).Cast(VariantType::Quaternion);
|
||||
_writer.Write(
|
||||
TEXT(
|
||||
" {{\n"
|
||||
" // Rotate position shape\n"
|
||||
" {0} = QuatRotateVector({1}, {0});\n"
|
||||
" }}\n"
|
||||
), positionAttr.Value, quaternion.Value);
|
||||
break;
|
||||
}
|
||||
|
||||
// Helper macros for collision modules to share the code
|
||||
#define COLLISION_BEGIN() \
|
||||
|
||||
@@ -858,6 +858,14 @@ namespace FlaxEngine.GUI
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool ContainsPoint(ref Float2 location, bool precise = false)
|
||||
{
|
||||
if (precise && this.GetType() == typeof(ContainerControl) && BackgroundColor.A <= 0.0f) // Go through transparency
|
||||
return false;
|
||||
return base.ContainsPoint(ref location, precise);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void PerformLayout(bool force = false)
|
||||
{
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace FlaxEngine.GUI
|
||||
/// <summary>
|
||||
/// Gets or sets the normalized position in the parent control that the upper left corner is anchored to (range 0-1).
|
||||
/// </summary>
|
||||
[Serialize, HideInEditor]
|
||||
[Serialize, HideInEditor, Limit(0, 1, 0.01f)]
|
||||
public Float2 AnchorMin
|
||||
{
|
||||
get => _anchorMin;
|
||||
@@ -69,7 +69,7 @@ namespace FlaxEngine.GUI
|
||||
/// <summary>
|
||||
/// Gets or sets the normalized position in the parent control that the bottom right corner is anchored to (range 0-1).
|
||||
/// </summary>
|
||||
[Serialize, HideInEditor]
|
||||
[Serialize, HideInEditor, Limit(0, 1, 0.01f)]
|
||||
public Float2 AnchorMax
|
||||
{
|
||||
get => _anchorMax;
|
||||
|
||||
@@ -301,7 +301,7 @@ namespace Flax.Build
|
||||
else
|
||||
project.Path = targets[0].CustomExternalProjectFilePath;
|
||||
if (project.WorkspaceRootPath.StartsWith(rootProject.ProjectFolderPath))
|
||||
project.GroupName = Utilities.MakePathRelativeTo(project.WorkspaceRootPath, rootProject.ProjectFolderPath);
|
||||
project.GroupName = Utilities.NormalizePath(Utilities.MakePathRelativeTo(project.WorkspaceRootPath, rootProject.ProjectFolderPath));
|
||||
else if (projectInfo != Globals.Project)
|
||||
project.GroupName = projectInfo.Name;
|
||||
project.SourceDirectories = new List<string>
|
||||
@@ -349,7 +349,10 @@ namespace Flax.Build
|
||||
var referenceBinaryModules = referenceModules.Keys.GroupBy(x => x.BinaryModuleName).ToArray();
|
||||
foreach (var binaryModule in referenceBinaryModules)
|
||||
{
|
||||
project.Defines.Add(binaryModule.Key.ToUpperInvariant() + "_API=");
|
||||
var binaryModuleName = binaryModule.Key;
|
||||
if (string.IsNullOrEmpty(binaryModuleName))
|
||||
continue;
|
||||
project.Defines.Add(binaryModuleName.ToUpperInvariant() + "_API=");
|
||||
}
|
||||
}
|
||||
catch
|
||||
|
||||
@@ -409,7 +409,7 @@ namespace Flax.Build
|
||||
var referencedBuild = buildData.FinReferenceBuildModule(dependencyModule.BinaryModuleName);
|
||||
if (referencedBuild != null && !string.IsNullOrEmpty(referencedBuild.ManagedPath))
|
||||
{
|
||||
// Reference binary module build build for referenced target
|
||||
// Reference binary module build for referenced target
|
||||
fileReferences.Add(referencedBuild.ManagedPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace Flax.Deps.Dependencies
|
||||
Path.Combine(root, "include", "SDL3"),
|
||||
};
|
||||
|
||||
CloneGitRepoFast(root, "https://github.com/libsdl-org/SDL");
|
||||
CloneGitRepo(root, "https://github.com/libsdl-org/SDL");
|
||||
GitFetch(root);
|
||||
GitResetToCommit(root, "535d80badefc83c5c527ec5748f2a20d6a9310fe"); // 3.2.0
|
||||
|
||||
|
||||
@@ -356,13 +356,13 @@ namespace Flax.Build.Projects.VisualStudio
|
||||
|
||||
if (project.SourceDirectories != null && project.SourceDirectories.Count == 1)
|
||||
{
|
||||
var subFolder = Utilities.MakePathRelativeTo(Path.GetDirectoryName(project.SourceDirectories[0]), project.WorkspaceRootPath);
|
||||
if (subFolder.StartsWith("Source\\"))
|
||||
subFolder = subFolder.Substring(7);
|
||||
var subFolder = Utilities.NormalizePath(Utilities.MakePathRelativeTo(Path.GetDirectoryName(project.SourceDirectories[0]), project.WorkspaceRootPath));
|
||||
if (subFolder.StartsWith("Source/"))
|
||||
subFolder = subFolder.Substring("Source/".Length);
|
||||
if (subFolder.Length != 0)
|
||||
{
|
||||
if (folder.Length != 0)
|
||||
folder += '\\';
|
||||
folder += '/';
|
||||
folder += subFolder;
|
||||
}
|
||||
}
|
||||
@@ -370,12 +370,12 @@ namespace Flax.Build.Projects.VisualStudio
|
||||
if (string.IsNullOrEmpty(folder))
|
||||
continue;
|
||||
|
||||
var folderParents = folder.Split('\\');
|
||||
var folderParents = folder.Split('/');
|
||||
for (int i = 0; i < folderParents.Length; i++)
|
||||
{
|
||||
var folderPath = folderParents[0];
|
||||
for (int j = 1; j <= i; j++)
|
||||
folderPath += '\\' + folderParents[j];
|
||||
folderPath += '/' + folderParents[j];
|
||||
|
||||
if (folderNames.Contains(folderPath))
|
||||
{
|
||||
@@ -397,7 +397,7 @@ namespace Flax.Build.Projects.VisualStudio
|
||||
{
|
||||
var folderGuid = folderIds[folder].ToString("B").ToUpperInvariant();
|
||||
var typeGuid = ProjectTypeGuids.ToOption(ProjectTypeGuids.SolutionFolder);
|
||||
var lastSplit = folder.LastIndexOf('\\');
|
||||
var lastSplit = folder.LastIndexOf('/');
|
||||
var name = lastSplit != -1 ? folder.Substring(lastSplit + 1) : folder;
|
||||
|
||||
vcSolutionFileContent.AppendLine(string.Format("Project(\"{0}\") = \"{1}\", \"{2}\", \"{3}\"", typeGuid, name, folder, folderGuid));
|
||||
@@ -573,7 +573,7 @@ namespace Flax.Build.Projects.VisualStudio
|
||||
// Write nested folders hierarchy
|
||||
foreach (var folder in folderNames)
|
||||
{
|
||||
var lastSplit = folder.LastIndexOf('\\');
|
||||
var lastSplit = folder.LastIndexOf('/');
|
||||
if (lastSplit != -1)
|
||||
{
|
||||
var folderGuid = folderIds[folder].ToString("B").ToUpperInvariant();
|
||||
@@ -615,8 +615,9 @@ namespace Flax.Build.Projects.VisualStudio
|
||||
{
|
||||
var profiles = new Dictionary<string, string>();
|
||||
var profile = new StringBuilder();
|
||||
var editorPath = Utilities.NormalizePath(Path.Combine(Globals.EngineRoot, Platform.GetEditorBinaryDirectory(), $"Development/FlaxEditor{Utilities.GetPlatformExecutableExt()}")).Replace('\\', '/');
|
||||
var workspacePath = Utilities.NormalizePath(solutionDirectory).Replace('\\', '/');
|
||||
var configuration = "Development";
|
||||
var editorPath = Utilities.NormalizePath(Path.Combine(Globals.EngineRoot, Platform.GetEditorBinaryDirectory(), configuration, $"FlaxEditor{Utilities.GetPlatformExecutableExt()}"));
|
||||
var workspacePath = Utilities.NormalizePath(solutionDirectory);
|
||||
foreach (var project in projects)
|
||||
{
|
||||
if (project.Type == TargetType.DotNetCore)
|
||||
|
||||
Reference in New Issue
Block a user