Merge branch 'FlaxEngine:master' into Nodes

This commit is contained in:
NoriteSC
2023-10-06 22:15:35 +02:00
committed by GitHub
30 changed files with 404 additions and 60 deletions

View File

@@ -125,6 +125,8 @@ namespace FlaxEditor.GUI.Timeline.Tracks
fov = cam.FieldOfView; fov = cam.FieldOfView;
customAspectRatio = cam.CustomAspectRatio; customAspectRatio = cam.CustomAspectRatio;
view.RenderLayersMask = cam.RenderLayersMask; view.RenderLayersMask = cam.RenderLayersMask;
view.Flags = cam.RenderFlags;
view.Mode = cam.RenderMode;
} }
// Try to evaluate camera properties based on the animated tracks // Try to evaluate camera properties based on the animated tracks

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Linq; using System.Linq;
using FlaxEditor.GUI.ContextMenu; using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.Windows;
using FlaxEngine; using FlaxEngine;
namespace FlaxEditor.SceneGraph.Actors namespace FlaxEditor.SceneGraph.Actors
@@ -22,9 +23,9 @@ namespace FlaxEditor.SceneGraph.Actors
} }
/// <inheritdoc /> /// <inheritdoc />
public override void OnContextMenu(ContextMenu contextMenu) public override void OnContextMenu(ContextMenu contextMenu, EditorWindow window)
{ {
base.OnContextMenu(contextMenu); base.OnContextMenu(contextMenu, window);
var actor = (AnimatedModel)Actor; var actor = (AnimatedModel)Actor;
if (actor && actor.SkinnedModel) if (actor && actor.SkinnedModel)

View File

@@ -6,6 +6,8 @@ using Real = System.Double;
using Real = System.Single; using Real = System.Single;
#endif #endif
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.Windows;
using FlaxEngine; using FlaxEngine;
namespace FlaxEditor.SceneGraph.Actors namespace FlaxEditor.SceneGraph.Actors
@@ -23,6 +25,25 @@ namespace FlaxEditor.SceneGraph.Actors
{ {
} }
/// <inheritdoc />
public override void OnContextMenu(ContextMenu contextMenu, EditorWindow window)
{
base.OnContextMenu(contextMenu, window);
if (window is not SceneTreeWindow win)
return;
var button = new ContextMenuButton(contextMenu, "Move Camera to View");
button.Parent = contextMenu.ItemsContainer;
contextMenu.ItemsContainer.Children.Remove(button);
contextMenu.ItemsContainer.Children.Insert(4, button);
button.Clicked += () =>
{
var c = Actor as Camera;
var viewport = Editor.Instance.Windows.EditWin.Viewport;
c.Position = viewport.ViewPosition;
c.Orientation = viewport.ViewOrientation;
};
}
/// <inheritdoc /> /// <inheritdoc />
public override bool RayCastSelf(ref RayCastData ray, out Real distance, out Vector3 normal) public override bool RayCastSelf(ref RayCastData ray, out Real distance, out Vector3 normal)
{ {

View File

@@ -3,6 +3,7 @@
using System.IO; using System.IO;
using FlaxEditor.GUI.ContextMenu; using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.SceneGraph.GUI; using FlaxEditor.SceneGraph.GUI;
using FlaxEditor.Windows;
using FlaxEngine; using FlaxEngine;
namespace FlaxEditor.SceneGraph.Actors namespace FlaxEditor.SceneGraph.Actors
@@ -65,7 +66,7 @@ namespace FlaxEditor.SceneGraph.Actors
public override SceneNode ParentScene => this; public override SceneNode ParentScene => this;
/// <inheritdoc /> /// <inheritdoc />
public override void OnContextMenu(ContextMenu contextMenu) public override void OnContextMenu(ContextMenu contextMenu, EditorWindow window)
{ {
contextMenu.AddSeparator(); contextMenu.AddSeparator();
var path = Scene.Path; var path = Scene.Path;
@@ -80,7 +81,7 @@ namespace FlaxEditor.SceneGraph.Actors
if (Level.ScenesCount > 1) if (Level.ScenesCount > 1)
contextMenu.AddButton("Unload all but this scene", OnUnloadAllButSelectedScene).LinkTooltip("Unloads all of the active scenes except for the selected scene.").Enabled = Editor.Instance.StateMachine.CurrentState.CanChangeScene; contextMenu.AddButton("Unload all but this scene", OnUnloadAllButSelectedScene).LinkTooltip("Unloads all of the active scenes except for the selected scene.").Enabled = Editor.Instance.StateMachine.CurrentState.CanChangeScene;
base.OnContextMenu(contextMenu); base.OnContextMenu(contextMenu, window);
} }
private void OnSelect() private void OnSelect()

View File

@@ -9,6 +9,7 @@ using Real = System.Single;
using System; using System;
using FlaxEditor.GUI.ContextMenu; using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.Modules; using FlaxEditor.Modules;
using FlaxEditor.Windows;
using FlaxEngine; using FlaxEngine;
using FlaxEngine.Json; using FlaxEngine.Json;
using Object = FlaxEngine.Object; using Object = FlaxEngine.Object;
@@ -203,9 +204,9 @@ namespace FlaxEditor.SceneGraph.Actors
} }
} }
public override void OnContextMenu(ContextMenu contextMenu) public override void OnContextMenu(ContextMenu contextMenu, EditorWindow window)
{ {
ParentNode.OnContextMenu(contextMenu); ParentNode.OnContextMenu(contextMenu, window);
} }
public static SceneGraphNode Create(StateData state) public static SceneGraphNode Create(StateData state)
@@ -272,9 +273,9 @@ namespace FlaxEditor.SceneGraph.Actors
DebugDraw.DrawSphere(new BoundingSphere(pos, tangentSize), Color.YellowGreen, 0, false); DebugDraw.DrawSphere(new BoundingSphere(pos, tangentSize), Color.YellowGreen, 0, false);
} }
public override void OnContextMenu(ContextMenu contextMenu) public override void OnContextMenu(ContextMenu contextMenu, EditorWindow window)
{ {
ParentNode.OnContextMenu(contextMenu); ParentNode.OnContextMenu(contextMenu, window);
} }
public override void OnDispose() public override void OnDispose()
@@ -354,9 +355,9 @@ namespace FlaxEditor.SceneGraph.Actors
} }
/// <inheritdoc /> /// <inheritdoc />
public override void OnContextMenu(ContextMenu contextMenu) public override void OnContextMenu(ContextMenu contextMenu, EditorWindow window)
{ {
base.OnContextMenu(contextMenu); base.OnContextMenu(contextMenu, window);
contextMenu.AddButton("Add spline model", OnAddSplineModel); contextMenu.AddButton("Add spline model", OnAddSplineModel);
contextMenu.AddButton("Add spline collider", OnAddSplineCollider); contextMenu.AddButton("Add spline collider", OnAddSplineCollider);

View File

@@ -3,6 +3,7 @@
using System; using System;
using FlaxEditor.Content; using FlaxEditor.Content;
using FlaxEditor.GUI.ContextMenu; using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.Windows;
using FlaxEngine; using FlaxEngine;
namespace FlaxEditor.SceneGraph.Actors namespace FlaxEditor.SceneGraph.Actors
@@ -21,9 +22,9 @@ namespace FlaxEditor.SceneGraph.Actors
} }
/// <inheritdoc /> /// <inheritdoc />
public override void OnContextMenu(ContextMenu contextMenu) public override void OnContextMenu(ContextMenu contextMenu, EditorWindow window)
{ {
base.OnContextMenu(contextMenu); base.OnContextMenu(contextMenu, window);
contextMenu.AddButton("Add collider", OnAddMeshCollider).Enabled = ((StaticModel)Actor).Model != null; contextMenu.AddButton("Add collider", OnAddMeshCollider).Enabled = ((StaticModel)Actor).Model != null;
} }

View File

@@ -599,7 +599,7 @@ namespace FlaxEditor.SceneGraph.GUI
// Drag scripts // Drag scripts
else if (_dragScripts != null && _dragScripts.HasValidDrag) else if (_dragScripts != null && _dragScripts.HasValidDrag)
{ {
foreach(var script in _dragScripts.Objects) foreach (var script in _dragScripts.Objects)
{ {
var customAction = script.HasPrefabLink ? new ReparentAction(script) : null; var customAction = script.HasPrefabLink ? new ReparentAction(script) : null;
using (new UndoBlock(ActorNode.Root.Undo, script, "Change script parent", customAction)) using (new UndoBlock(ActorNode.Root.Undo, script, "Change script parent", customAction))
@@ -616,7 +616,7 @@ namespace FlaxEditor.SceneGraph.GUI
var spawnParent = myActor; var spawnParent = myActor;
if (DragOverMode == DragItemPositioning.Above || DragOverMode == DragItemPositioning.Below) if (DragOverMode == DragItemPositioning.Above || DragOverMode == DragItemPositioning.Below)
spawnParent = newParent; spawnParent = newParent;
for (int i = 0; i < _dragAssets.Objects.Count; i++) for (int i = 0; i < _dragAssets.Objects.Count; i++)
{ {
var item = _dragAssets.Objects[i]; var item = _dragAssets.Objects[i];
@@ -720,7 +720,7 @@ namespace FlaxEditor.SceneGraph.GUI
for (var i = 0; i < tree.Selection.Count; i++) for (var i = 0; i < tree.Selection.Count; i++)
{ {
var e = tree.Selection[i]; var e = tree.Selection[i];
// Skip if parent is already selected to keep correct parenting // Skip if parent is already selected to keep correct parenting
if (tree.Selection.Contains(e.Parent)) if (tree.Selection.Contains(e.Parent))
continue; continue;

View File

@@ -11,6 +11,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using FlaxEditor.Modules; using FlaxEditor.Modules;
using FlaxEditor.SceneGraph.Actors; using FlaxEditor.SceneGraph.Actors;
using FlaxEditor.Windows;
using FlaxEngine; using FlaxEngine;
namespace FlaxEditor.SceneGraph namespace FlaxEditor.SceneGraph
@@ -339,7 +340,7 @@ namespace FlaxEditor.SceneGraph
/// <summary> /// <summary>
/// Called when scene tree window wants to show the context menu. Allows to add custom options. /// Called when scene tree window wants to show the context menu. Allows to add custom options.
/// </summary> /// </summary>
public virtual void OnContextMenu(FlaxEditor.GUI.ContextMenu.ContextMenu contextMenu) public virtual void OnContextMenu(FlaxEditor.GUI.ContextMenu.ContextMenu contextMenu, EditorWindow window)
{ {
} }

View File

@@ -787,7 +787,7 @@ namespace FlaxEditor.Surface.Archetypes
} }
} }
private class AsNode : SurfaceNode internal class AsNode : SurfaceNode
{ {
private TypePickerControl _picker; private TypePickerControl _picker;
@@ -838,6 +838,15 @@ namespace FlaxEditor.Surface.Archetypes
box.CurrentType = type ? type : ScriptType.FlaxObject; box.CurrentType = type ? type : ScriptType.FlaxObject;
} }
/// <summary>
/// Sets the type of the picker and the type of the output box
/// </summary>
/// <param name="type">Target Type</param>
public void SetPickerValue(ScriptType type)
{
_picker.Value = type;
}
/// <inheritdoc /> /// <inheritdoc />
public override void OnDestroy() public override void OnDestroy()
{ {
@@ -999,6 +1008,15 @@ namespace FlaxEditor.Surface.Archetypes
GetBox(4).CurrentType = type ? type : _picker.Type; GetBox(4).CurrentType = type ? type : _picker.Type;
} }
/// <summary>
/// Sets the type of the picker and the type of the output box
/// </summary>
/// <param name="type">Target Type</param>
public void SetPickerValue(ScriptType type)
{
_picker.Value = type;
}
/// <inheritdoc /> /// <inheritdoc />
public override void OnDestroy() public override void OnDestroy()
{ {

View File

@@ -721,9 +721,7 @@ namespace FlaxEditor.Surface.ContextMenu
SelectedItem = previousSelectedItem; SelectedItem = previousSelectedItem;
// Scroll into view (without smoothing) // Scroll into view (without smoothing)
_panel1.VScrollBar.SmoothingScale = 0; _panel1.ScrollViewTo(SelectedItem, true);
_panel1.ScrollViewTo(SelectedItem);
_panel1.VScrollBar.SmoothingScale = 1;
} }
return true; return true;
} }

View File

@@ -820,8 +820,62 @@ namespace FlaxEditor.Surface.Elements
if (useCaster) if (useCaster)
{ {
// Connect via Caster // Connect via Caster
//AddCaster(oB, iB); const float casterXOffset = 250;
throw new NotImplementedException("AddCaster(..) function"); if (Surface.Undo != null && Surface.Undo.Enabled)
{
bool undoEnabled = Surface.Undo.Enabled;
Surface.Undo.Enabled = false;
SurfaceNode node = Surface.Context.SpawnNode(7, 22, Float2.Zero); // 22 AsNode, 25 CastNode
Surface.Undo.Enabled = undoEnabled;
if (node is not Archetypes.Tools.AsNode castNode)
throw new Exception("Node is not a casting node!");
// Set the type of the casting node
undoEnabled = castNode.Surface.Undo.Enabled;
castNode.Surface.Undo.Enabled = false;
castNode.SetPickerValue(iB.CurrentType);
castNode.Surface.Undo.Enabled = undoEnabled;
if (node.GetBox(0) is not OutputBox castOutputBox || node.GetBox(1) is not InputBox castInputBox)
throw new NullReferenceException("Casting failed. Cast node is invalid!");
// We set the position of the cast node here to set it relative to the target nodes input box
undoEnabled = castNode.Surface.Undo.Enabled;
castNode.Surface.Undo.Enabled = false;
var wantedOffset = iB.ParentNode.Location - new Float2(casterXOffset, -(iB.LocalY - castOutputBox.LocalY));
castNode.Location = Surface.Root.PointFromParent(ref wantedOffset);
castNode.Surface.Undo.Enabled = undoEnabled;
var spawnNodeAction = new AddRemoveNodeAction(castNode, true);
var connectToCastNodeAction = new ConnectBoxesAction(castInputBox, oB, true);
castInputBox.CreateConnection(oB);
connectToCastNodeAction.End();
var connectCastToTargetNodeAction = new ConnectBoxesAction(iB, castOutputBox, true);
iB.CreateConnection(castOutputBox);
connectCastToTargetNodeAction.End();
Surface.AddBatchedUndoAction(new MultiUndoAction(spawnNodeAction, connectToCastNodeAction, connectCastToTargetNodeAction));
}
else
{
SurfaceNode node = Surface.Context.SpawnNode(7, 22, Float2.Zero); // 22 AsNode, 25 CastNode
if (node is not Archetypes.Tools.AsNode castNode)
throw new Exception("Node is not a casting node!");
// Set the type of the casting node
castNode.SetPickerValue(iB.CurrentType);
if (node.GetBox(0) is not OutputBox castOutputBox || node.GetBox(1) is not InputBox castInputBox)
throw new NullReferenceException("Casting failed. Cast node is invalid!");
// We set the position of the cast node here to set it relative to the target nodes input box
var wantedOffset = iB.ParentNode.Location - new Float2(casterXOffset, -(iB.LocalY - castOutputBox.LocalY));
castNode.Location = Surface.Root.PointFromParent(ref wantedOffset);
castInputBox.CreateConnection(oB);
iB.CreateConnection(castOutputBox);
}
Surface.MarkAsEdited();
} }
else else
{ {

View File

@@ -2,6 +2,7 @@
using System; using System;
using System.Linq; using System.Linq;
using FlaxEditor.Content.Settings;
using FlaxEditor.GUI.ContextMenu; using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.GUI.Input; using FlaxEditor.GUI.Input;
using FlaxEditor.Options; using FlaxEditor.Options;
@@ -9,6 +10,8 @@ using FlaxEditor.Viewport.Cameras;
using FlaxEditor.Viewport.Widgets; using FlaxEditor.Viewport.Widgets;
using FlaxEngine; using FlaxEngine;
using FlaxEngine.GUI; using FlaxEngine.GUI;
using Newtonsoft.Json;
using JsonSerializer = FlaxEngine.Json.JsonSerializer;
namespace FlaxEditor.Viewport namespace FlaxEditor.Viewport
{ {
@@ -486,10 +489,63 @@ namespace FlaxEditor.Viewport
} }
} }
// View Layers
{
var viewLayers = ViewWidgetButtonMenu.AddChildMenu("View Layers").ContextMenu;
viewLayers.AddButton("Copy layers", () => Clipboard.Text = JsonSerializer.Serialize(Task.View.RenderLayersMask));
viewLayers.AddButton("Paste layers", () =>
{
try
{
Task.ViewLayersMask = JsonSerializer.Deserialize<LayersMask>(Clipboard.Text);
}
catch
{
}
});
viewLayers.AddButton("Reset layers", () => Task.ViewLayersMask = LayersMask.Default).Icon = Editor.Instance.Icons.Rotate32;
viewLayers.AddButton("Disable layers", () => Task.ViewLayersMask = new LayersMask(0)).Icon = Editor.Instance.Icons.Rotate32;
viewLayers.AddSeparator();
var layers = LayersAndTagsSettings.GetCurrentLayers();
if (layers != null && layers.Length > 0)
{
for (int i = 0; i < layers.Length; i++)
{
var layer = layers[i];
var button = viewLayers.AddButton(layer);
button.CloseMenuOnClick = false;
button.Tag = 1 << i;
}
}
viewLayers.ButtonClicked += button =>
{
if (button.Tag != null)
{
int layerIndex = (int)button.Tag;
LayersMask mask = new LayersMask(layerIndex);
Task.ViewLayersMask ^= mask;
button.Icon = (Task.ViewLayersMask & mask) != 0 ? Style.Current.CheckBoxTick : SpriteHandle.Invalid;
}
};
viewLayers.VisibleChanged += WidgetViewLayersShowHide;
}
// View Flags // View Flags
{ {
var viewFlags = ViewWidgetButtonMenu.AddChildMenu("View Flags").ContextMenu; var viewFlags = ViewWidgetButtonMenu.AddChildMenu("View Flags").ContextMenu;
viewFlags.AddButton("Copy flags", () => Clipboard.Text = JsonSerializer.Serialize(Task.ViewFlags));
viewFlags.AddButton("Paste flags", () =>
{
try
{
Task.ViewFlags = JsonSerializer.Deserialize<ViewFlags>(Clipboard.Text);
}
catch
{
}
});
viewFlags.AddButton("Reset flags", () => Task.ViewFlags = ViewFlags.DefaultEditor).Icon = Editor.Instance.Icons.Rotate32; viewFlags.AddButton("Reset flags", () => Task.ViewFlags = ViewFlags.DefaultEditor).Icon = Editor.Instance.Icons.Rotate32;
viewFlags.AddButton("Disable flags", () => Task.ViewFlags = ViewFlags.None).Icon = Editor.Instance.Icons.Rotate32;
viewFlags.AddSeparator(); viewFlags.AddSeparator();
for (int i = 0; i < EditorViewportViewFlagsValues.Length; i++) for (int i = 0; i < EditorViewportViewFlagsValues.Length; i++)
{ {
@@ -504,7 +560,7 @@ namespace FlaxEditor.Viewport
{ {
var v = (ViewFlags)button.Tag; var v = (ViewFlags)button.Tag;
Task.ViewFlags ^= v; Task.ViewFlags ^= v;
button.Icon = (Task.View.Flags & v) != 0 ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; button.Icon = (Task.ViewFlags & v) != 0 ? Style.Current.CheckBoxTick : SpriteHandle.Invalid;
} }
}; };
viewFlags.VisibleChanged += WidgetViewFlagsShowHide; viewFlags.VisibleChanged += WidgetViewFlagsShowHide;
@@ -513,6 +569,18 @@ namespace FlaxEditor.Viewport
// Debug View // Debug View
{ {
var debugView = ViewWidgetButtonMenu.AddChildMenu("Debug View").ContextMenu; var debugView = ViewWidgetButtonMenu.AddChildMenu("Debug View").ContextMenu;
debugView.AddButton("Copy view", () => Clipboard.Text = JsonSerializer.Serialize(Task.ViewMode));
debugView.AddButton("Paste view", () =>
{
try
{
Task.ViewMode = JsonSerializer.Deserialize<ViewMode>(Clipboard.Text);
}
catch
{
}
});
debugView.AddSeparator();
for (int i = 0; i < EditorViewportViewModeValues.Length; i++) for (int i = 0; i < EditorViewportViewModeValues.Length; i++)
{ {
ref var v = ref EditorViewportViewModeValues[i]; ref var v = ref EditorViewportViewModeValues[i];
@@ -1084,9 +1152,9 @@ namespace FlaxEditor.Viewport
_isVirtualMouseRightDown = false; // Cancel when mouse right or escape is pressed _isVirtualMouseRightDown = false; // Cancel when mouse right or escape is pressed
if (_wasVirtualMouseRightDown) if (_wasVirtualMouseRightDown)
wasControllingMouse = true; wasControllingMouse = true;
if (_isVirtualMouseRightDown) if (_isVirtualMouseRightDown)
_isControllingMouse = _isVirtualMouseRightDown; _isControllingMouse = _isVirtualMouseRightDown;
if (wasControllingMouse != _isControllingMouse) if (wasControllingMouse != _isControllingMouse)
{ {
if (_isControllingMouse) if (_isControllingMouse)
@@ -1591,6 +1659,24 @@ namespace FlaxEditor.Viewport
} }
} }
private void WidgetViewLayersShowHide(Control cm)
{
if (cm.Visible == false)
return;
var ccm = (ContextMenu)cm;
var layersMask = Task.ViewLayersMask;
foreach (var e in ccm.Items)
{
if (e is ContextMenuButton b && b != null && b.Tag != null)
{
int layerIndex = (int)b.Tag;
LayersMask mask = new LayersMask(layerIndex);
b.Icon = (layersMask & mask) != 0 ? Style.Current.CheckBoxTick : SpriteHandle.Invalid;
}
}
}
private float GetGamepadAxis(GamepadAxis axis) private float GetGamepadAxis(GamepadAxis axis)
{ {
var value = FlaxEngine.Input.GetGamepadAxis(InputGamepadIndex.All, axis); var value = FlaxEngine.Input.GetGamepadAxis(InputGamepadIndex.All, axis);

View File

@@ -313,7 +313,7 @@ namespace FlaxEditor.Windows.Assets
} }
if (showCustomNodeOptions) if (showCustomNodeOptions)
{ {
Selection[0].OnContextMenu(contextMenu); Selection[0].OnContextMenu(contextMenu, this);
} }
ContextMenuShow?.Invoke(contextMenu); ContextMenuShow?.Invoke(contextMenu);

View File

@@ -151,7 +151,7 @@ namespace FlaxEditor.Windows.Assets
Graph = new LocalSceneGraph(new CustomRootNode(this)); Graph = new LocalSceneGraph(new CustomRootNode(this));
_tree = new PrefabTree _tree = new PrefabTree
{ {
Margin = new Margin(0.0f, 0.0f, -16.0f, 0.0f), // Hide root node Margin = new Margin(0.0f, 0.0f, -16.0f, _treePanel.ScrollBarsSize), // Hide root node
IsScrollable = true, IsScrollable = true,
}; };
_tree.AddChild(Graph.Root.TreeNode); _tree.AddChild(Graph.Root.TreeNode);

View File

@@ -215,7 +215,7 @@ namespace FlaxEditor.Windows
} }
if (showCustomNodeOptions) if (showCustomNodeOptions)
{ {
Editor.SceneEditing.Selection[0].OnContextMenu(contextMenu); Editor.SceneEditing.Selection[0].OnContextMenu(contextMenu, this);
} }
ContextMenuShow?.Invoke(contextMenu); ContextMenuShow?.Invoke(contextMenu);

View File

@@ -74,7 +74,7 @@ namespace FlaxEditor.Windows
root.TreeNode.Expand(); root.TreeNode.Expand();
_tree = new Tree(true) _tree = new Tree(true)
{ {
Margin = new Margin(0.0f, 0.0f, -16.0f, 0.0f), // Hide root node Margin = new Margin(0.0f, 0.0f, -16.0f, _sceneTreePanel.ScrollBarsSize), // Hide root node
IsScrollable = true, IsScrollable = true,
}; };
_tree.AddChild(root.TreeNode); _tree.AddChild(root.TreeNode);

View File

@@ -54,9 +54,7 @@ namespace FlaxEditor.Windows.Search
_selectedItem.BackgroundColor = Style.Current.BackgroundSelected; _selectedItem.BackgroundColor = Style.Current.BackgroundSelected;
if (_matchedItems.Count > VisibleItemCount) if (_matchedItems.Count > VisibleItemCount)
{ {
_resultPanel.VScrollBar.SmoothingScale = 0; _resultPanel.ScrollViewTo(_selectedItem, true);
_resultPanel.ScrollViewTo(_selectedItem);
_resultPanel.VScrollBar.SmoothingScale = 1;
} }
} }
} }

View File

@@ -171,6 +171,8 @@ int32 FindVertex(const MeshData& mesh, int32 vertexIndex, int32 startIndex, int3
const Float3 vNormal = mesh.Normals.HasItems() ? mesh.Normals[vertexIndex] : Float3::Zero; const Float3 vNormal = mesh.Normals.HasItems() ? mesh.Normals[vertexIndex] : Float3::Zero;
const Float3 vTangent = mesh.Tangents.HasItems() ? mesh.Tangents[vertexIndex] : Float3::Zero; const Float3 vTangent = mesh.Tangents.HasItems() ? mesh.Tangents[vertexIndex] : Float3::Zero;
const Float2 vLightmapUV = mesh.LightmapUVs.HasItems() ? mesh.LightmapUVs[vertexIndex] : Float2::Zero; const Float2 vLightmapUV = mesh.LightmapUVs.HasItems() ? mesh.LightmapUVs[vertexIndex] : Float2::Zero;
const Color vColor = mesh.Colors.HasItems() ? mesh.Colors[vertexIndex] : Color::Black; // Assuming Color::Black as a default color
const int32 end = startIndex + searchRange; const int32 end = startIndex + searchRange;
for (size_t i = 0; i < sparialSortCache.size(); i++) for (size_t i = 0; i < sparialSortCache.size(); i++)
@@ -184,6 +186,8 @@ int32 FindVertex(const MeshData& mesh, int32 vertexIndex, int32 startIndex, int3
const Float3 vNormal = mesh.Normals.HasItems() ? mesh.Normals[vertexIndex] : Float3::Zero; const Float3 vNormal = mesh.Normals.HasItems() ? mesh.Normals[vertexIndex] : Float3::Zero;
const Float3 vTangent = mesh.Tangents.HasItems() ? mesh.Tangents[vertexIndex] : Float3::Zero; const Float3 vTangent = mesh.Tangents.HasItems() ? mesh.Tangents[vertexIndex] : Float3::Zero;
const Float2 vLightmapUV = mesh.LightmapUVs.HasItems() ? mesh.LightmapUVs[vertexIndex] : Float2::Zero; const Float2 vLightmapUV = mesh.LightmapUVs.HasItems() ? mesh.LightmapUVs[vertexIndex] : Float2::Zero;
const Color vColor = mesh.Colors.HasItems() ? mesh.Colors[vertexIndex] : Color::Black; // Assuming Color::Black as a default color
const int32 end = startIndex + searchRange; const int32 end = startIndex + searchRange;
for (int32 v = startIndex; v < end; v++) for (int32 v = startIndex; v < end; v++)
@@ -201,6 +205,8 @@ int32 FindVertex(const MeshData& mesh, int32 vertexIndex, int32 startIndex, int3
continue; continue;
if (mesh.LightmapUVs.HasItems() && (vLightmapUV - mesh.LightmapUVs[v]).LengthSquared() > uvEpsSqr) if (mesh.LightmapUVs.HasItems() && (vLightmapUV - mesh.LightmapUVs[v]).LengthSquared() > uvEpsSqr)
continue; continue;
if (mesh.Colors.HasItems() && vColor != mesh.Colors[v])
continue;
// TODO: check more components? // TODO: check more components?
return v; return v;

View File

@@ -39,5 +39,19 @@ namespace FlaxEngine
View = view; View = view;
} }
} }
/// <summary>
/// The rendering mask for layers. Used to exclude objects from rendering (via <see cref="View"/> property).
/// </summary>
public LayersMask ViewLayersMask
{
get => View.RenderLayersMask;
set
{
var view = View;
view.RenderLayersMask = value;
View = view;
}
}
} }
} }

View File

@@ -176,7 +176,7 @@ void RenderView::SetProjector(float nearPlane, float farPlane, const Float3& pos
CullingFrustum = Frustum; CullingFrustum = Frustum;
} }
void RenderView::CopyFrom(Camera* camera, Viewport* viewport) void RenderView::CopyFrom(const Camera* camera, const Viewport* viewport)
{ {
const Vector3 cameraPos = camera->GetPosition(); const Vector3 cameraPos = camera->GetPosition();
LargeWorlds::UpdateOrigin(Origin, cameraPos); LargeWorlds::UpdateOrigin(Origin, cameraPos);
@@ -192,6 +192,8 @@ void RenderView::CopyFrom(Camera* camera, Viewport* viewport)
Frustum.GetInvMatrix(IVP); Frustum.GetInvMatrix(IVP);
CullingFrustum = Frustum; CullingFrustum = Frustum;
RenderLayersMask = camera->RenderLayersMask; RenderLayersMask = camera->RenderLayersMask;
Flags = camera->RenderFlags;
Mode = camera->RenderMode;
} }
void RenderView::GetWorldMatrix(const Transform& transform, Matrix& world) const void RenderView::GetWorldMatrix(const Transform& transform, Matrix& world) const

View File

@@ -102,6 +102,8 @@ namespace FlaxEngine
NonJitteredProjection = Projection; NonJitteredProjection = Projection;
TemporalAAJitter = Float4.Zero; TemporalAAJitter = Float4.Zero;
RenderLayersMask = camera.RenderLayersMask; RenderLayersMask = camera.RenderLayersMask;
Flags = camera.RenderFlags;
Mode = camera.RenderMode;
UpdateCachedData(); UpdateCachedData();
} }

View File

@@ -295,10 +295,12 @@ public:
/// <param name="angle">Camera's FOV angle (in degrees)</param> /// <param name="angle">Camera's FOV angle (in degrees)</param>
void SetProjector(float nearPlane, float farPlane, const Float3& position, const Float3& direction, const Float3& up, float angle); void SetProjector(float nearPlane, float farPlane, const Float3& position, const Float3& direction, const Float3& up, float angle);
// Copy view data from camera /// <summary>
// @param camera Camera to copy its data /// Copies view data from camera to the view.
// @param camera The custom viewport to use for view/projection matrices override. /// </summary>
void CopyFrom(Camera* camera, Viewport* viewport = nullptr); /// <param name="camera">The camera to copy its data.</param>
/// <param name="viewport">The custom viewport to use for view/projection matrices override.</param>
void CopyFrom(const Camera* camera, const Viewport* viewport = nullptr);
public: public:
FORCE_INLINE DrawPass GetShadowsDrawPassMask(ShadowsCastingMode shadowsMode) const FORCE_INLINE DrawPass GetShadowsDrawPassMask(ShadowsCastingMode shadowsMode) const

View File

@@ -415,6 +415,8 @@ void Camera::Serialize(SerializeStream& stream, const void* otherObj)
SERIALIZE_MEMBER(Far, _far); SERIALIZE_MEMBER(Far, _far);
SERIALIZE_MEMBER(OrthoScale, _orthoScale); SERIALIZE_MEMBER(OrthoScale, _orthoScale);
SERIALIZE(RenderLayersMask); SERIALIZE(RenderLayersMask);
SERIALIZE(RenderFlags);
SERIALIZE(RenderMode);
} }
void Camera::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) void Camera::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
@@ -429,6 +431,8 @@ void Camera::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier
DESERIALIZE_MEMBER(Far, _far); DESERIALIZE_MEMBER(Far, _far);
DESERIALIZE_MEMBER(OrthoScale, _orthoScale); DESERIALIZE_MEMBER(OrthoScale, _orthoScale);
DESERIALIZE(RenderLayersMask); DESERIALIZE(RenderLayersMask);
DESERIALIZE(RenderFlags);
DESERIALIZE(RenderMode);
} }
void Camera::OnEnable() void Camera::OnEnable()

View File

@@ -7,6 +7,7 @@
#include "Engine/Core/Math/Viewport.h" #include "Engine/Core/Math/Viewport.h"
#include "Engine/Core/Math/Ray.h" #include "Engine/Core/Math/Ray.h"
#include "Engine/Core/Types/LayersMask.h" #include "Engine/Core/Types/LayersMask.h"
#include "Engine/Graphics/Enums.h"
#include "Engine/Scripting/ScriptingObjectReference.h" #include "Engine/Scripting/ScriptingObjectReference.h"
#if USE_EDITOR #if USE_EDITOR
#include "Engine/Content/AssetReference.h" #include "Engine/Content/AssetReference.h"
@@ -134,6 +135,18 @@ public:
API_FIELD(Attributes="EditorOrder(100), EditorDisplay(\"Camera\")") API_FIELD(Attributes="EditorOrder(100), EditorDisplay(\"Camera\")")
LayersMask RenderLayersMask; LayersMask RenderLayersMask;
/// <summary>
/// Frame rendering flags used to switch between graphics features for this camera.
/// </summary>
API_FIELD(Attributes = "EditorOrder(110), EditorDisplay(\"Camera\")")
ViewFlags RenderFlags = ViewFlags::DefaultGame;
/// <summary>
/// Describes frame rendering modes for this camera.
/// </summary>
API_FIELD(Attributes = "EditorOrder(120), EditorDisplay(\"Camera\")")
ViewMode RenderMode = ViewMode::Default;
public: public:
/// <summary> /// <summary>
/// Projects the point from 3D world-space to game window coordinates (in screen pixels for default viewport calculated from <see cref="Viewport"/>). /// Projects the point from 3D world-space to game window coordinates (in screen pixels for default viewport calculated from <see cref="Viewport"/>).

View File

@@ -79,6 +79,7 @@ public:
void Serialize(SerializeStream& stream, const void* otherObj) override; void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
}; };
#endif
public: public:
/// <summary> /// <summary>
@@ -127,7 +128,6 @@ public:
{ {
return (input[2] << 24) | (input[1] << 16) | (input[0] << 8); return (input[2] << 24) | (input[1] << 16) | (input[0] << 8);
} }
#endif
}; };
#endif #endif

View File

@@ -314,6 +314,28 @@ namespace FlaxEngine.GUI
return false; return false;
} }
/// <inheritdoc />
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
{
if (base.OnMouseDoubleClick(location, button))
return true;
if (button == MouseButton.Left && _isPressed)
{
OnPressEnd();
OnClick();
return true;
}
if (button == MouseButton.Left && !_isPressed)
{
OnPressBegin();
return true;
}
return false;
}
/// <inheritdoc /> /// <inheritdoc />
public override bool OnTouchDown(Float2 location, int pointerId) public override bool OnTouchDown(Float2 location, int pointerId)
{ {

View File

@@ -277,6 +277,27 @@ namespace FlaxEngine.GUI
return base.OnMouseDown(location, button); return base.OnMouseDown(location, button);
} }
/// <inheritdoc />
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
{
if (button == MouseButton.Left && !_isPressed)
{
OnPressBegin();
return true;
}
if (button == MouseButton.Left && _isPressed)
{
OnPressEnd();
if (_box.Contains(ref location))
{
OnClick();
return true;
}
}
return base.OnMouseDoubleClick(location, button);
}
/// <inheritdoc /> /// <inheritdoc />
public override bool OnMouseUp(Float2 location, MouseButton button) public override bool OnMouseUp(Float2 location, MouseButton button)
{ {

View File

@@ -666,6 +666,30 @@ namespace FlaxEngine.GUI
return false; return false;
} }
/// <inheritdoc />
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
{
if (base.OnMouseDoubleClick(location, button))
return true;
if (_touchDown && button == MouseButton.Left)
{
_touchDown = false;
ShowPopup();
return true;
}
if (button == MouseButton.Left)
{
_touchDown = true;
if (!IsPopupOpened)
Focus();
return true;
}
return false;
}
/// <inheritdoc /> /// <inheritdoc />
public override bool OnTouchDown(Float2 location, int pointerId) public override bool OnTouchDown(Float2 location, int pointerId)
{ {

View File

@@ -501,6 +501,29 @@ namespace FlaxEngine.GUI
return false; return false;
} }
/// <inheritdoc />
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
{
if (base.OnMouseDoubleClick(location, button))
return true;
_mouseOverHeader = HeaderRectangle.Contains(location);
if (button == MouseButton.Left && _mouseOverHeader)
{
_mouseButtonLeftDown = true;
return true;
}
if (button == MouseButton.Left && _mouseButtonLeftDown)
{
_mouseButtonLeftDown = false;
if (_mouseOverHeader)
Toggle();
return true;
}
return false;
}
/// <inheritdoc /> /// <inheritdoc />
public override void OnMouseLeave() public override void OnMouseLeave()
{ {

View File

@@ -23,9 +23,9 @@ namespace FlaxEngine.GUI
// Scrolling // Scrolling
private float _clickChange = 20, _scrollChange = 100; private float _clickChange = 20, _scrollChange = 50;
private float _minimum, _maximum = 100; private float _minimum, _maximum = 100;
private float _value, _targetValue; private float _startValue, _value, _targetValue;
private readonly Orientation _orientation; private readonly Orientation _orientation;
private RootControl.UpdateDelegate _update; private RootControl.UpdateDelegate _update;
@@ -42,6 +42,7 @@ namespace FlaxEngine.GUI
// Smoothing // Smoothing
private float _thumbOpacity = DefaultMinimumOpacity; private float _thumbOpacity = DefaultMinimumOpacity;
private float _scrollAnimationProgress = 0f;
/// <summary> /// <summary>
/// Gets the orientation. /// Gets the orientation.
@@ -59,14 +60,19 @@ namespace FlaxEngine.GUI
public float TrackThickness { get; set; } = 2.0f; public float TrackThickness { get; set; } = 2.0f;
/// <summary> /// <summary>
/// Gets or sets the value smoothing scale (0 to not use it). /// The maximum time it takes to animate from current to target scroll position
/// </summary> /// </summary>
public float SmoothingScale { get; set; } = 0.6f; public float ScrollAnimationDuration { get; set; } = 0.18f;
/// <summary> /// <summary>
/// Gets a value indicating whether use scroll value smoothing. /// Gets a value indicating whether use scroll value smoothing.
/// </summary> /// </summary>
public bool UseSmoothing => !Mathf.IsZero(SmoothingScale); public bool UseSmoothing => EnableSmoothing && !Mathf.IsZero(ScrollAnimationDuration);
/// <summary>
/// Enables scroll smoothing
/// </summary>
public bool EnableSmoothing { get; set; } = true;
/// <summary> /// <summary>
/// Gets or sets the minimum value. /// Gets or sets the minimum value.
@@ -112,11 +118,15 @@ namespace FlaxEngine.GUI
if (!Mathf.NearEqual(value, _targetValue)) if (!Mathf.NearEqual(value, _targetValue))
{ {
_targetValue = value; _targetValue = value;
_startValue = _value;
_scrollAnimationProgress = 0f;
// Check if skip smoothing // Check if skip smoothing
if (!UseSmoothing) if (!UseSmoothing)
{ {
_value = value; _value = value;
_startValue = value;
_scrollAnimationProgress = 1f;
OnValueChanged(); OnValueChanged();
} }
else else
@@ -208,7 +218,8 @@ namespace FlaxEngine.GUI
{ {
if (!Mathf.NearEqual(_value, _targetValue)) if (!Mathf.NearEqual(_value, _targetValue))
{ {
_value = _targetValue; _value = _targetValue = _startValue;
_scrollAnimationProgress = 0f;
SetUpdate(ref _update, null); SetUpdate(ref _update, null);
OnValueChanged(); OnValueChanged();
} }
@@ -274,7 +285,8 @@ namespace FlaxEngine.GUI
internal void Reset() internal void Reset()
{ {
_value = _targetValue = 0; _value = _targetValue = _startValue = 0;
_scrollAnimationProgress = 0f;
} }
/// <summary> /// <summary>
@@ -296,22 +308,39 @@ namespace FlaxEngine.GUI
_thumbOpacity = isDeltaSlow ? targetOpacity : Mathf.Lerp(_thumbOpacity, targetOpacity, deltaTime * 10.0f); _thumbOpacity = isDeltaSlow ? targetOpacity : Mathf.Lerp(_thumbOpacity, targetOpacity, deltaTime * 10.0f);
bool needUpdate = Mathf.Abs(_thumbOpacity - targetOpacity) > 0.001f; bool needUpdate = Mathf.Abs(_thumbOpacity - targetOpacity) > 0.001f;
// Ensure scroll bar is visible // Ensure scroll bar is visible and smoothing is required
if (Visible) if (Visible && Mathf.Abs(_targetValue - _value) > 0.01f)
{ {
// Value smoothing // Interpolate or not if running slow
if (Mathf.Abs(_targetValue - _value) > 0.01f) float value;
if (!isDeltaSlow && UseSmoothing)
{ {
// Interpolate or not if running slow // percentage of scroll from 0 to _scrollChange, ex. 0.5 at _scrollChange / 2
float value; var minScrollChangeRatio = Mathf.Clamp(Mathf.Abs(_targetValue - _startValue) / _scrollChange, 0, 1);
if (!isDeltaSlow && UseSmoothing)
value = Mathf.Lerp(_value, _targetValue, deltaTime * 20.0f * SmoothingScale); // shorten the duration if we scrolled less than _scrollChange
else var actualDuration = ScrollAnimationDuration * minScrollChangeRatio;
value = _targetValue; var step = deltaTime / actualDuration;
_value = value;
OnValueChanged(); var progress = _scrollAnimationProgress;
needUpdate = true; progress = Mathf.Clamp(progress + step, 0, 1);
// https://easings.net/#easeOutSine
var easedProgress = Mathf.Sin((progress * Mathf.Pi) / 2);
value = Mathf.Lerp(_startValue, _targetValue, easedProgress);
_scrollAnimationProgress = progress;
} }
else
{
value = _targetValue;
_startValue = _targetValue;
_scrollAnimationProgress = 0f;
}
_value = value;
OnValueChanged();
needUpdate = true;
} }
// End updating if all animations are done // End updating if all animations are done
@@ -371,7 +400,7 @@ namespace FlaxEngine.GUI
float mousePosition = _orientation == Orientation.Vertical ? slidePosition.Y : slidePosition.X; float mousePosition = _orientation == Orientation.Vertical ? slidePosition.Y : slidePosition.X;
float percentage = (mousePosition - _mouseOffset - _thumbSize / 2) / (TrackSize - _thumbSize); float percentage = (mousePosition - _mouseOffset - _thumbSize / 2) / (TrackSize - _thumbSize);
Value = _minimum + percentage * (_maximum - _minimum); TargetValue = _minimum + percentage * (_maximum - _minimum);
} }
} }
@@ -381,7 +410,7 @@ namespace FlaxEngine.GUI
if (ThumbEnabled) if (ThumbEnabled)
{ {
// Scroll // Scroll
Value = _value - delta * _scrollChange; Value = _targetValue - delta * _scrollChange;
} }
return true; return true;
} }