Merge branch 'FlaxEngine:master' into Nodes
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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"/>).
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user