Merge branch 'master' into AnimationSampleNode-AnimationAssetReferencePort

This commit is contained in:
Nils Hausfeld
2023-10-06 17:50:36 +02:00
30 changed files with 404 additions and 60 deletions

View File

@@ -125,6 +125,8 @@ namespace FlaxEditor.GUI.Timeline.Tracks
fov = cam.FieldOfView;
customAspectRatio = cam.CustomAspectRatio;
view.RenderLayersMask = cam.RenderLayersMask;
view.Flags = cam.RenderFlags;
view.Mode = cam.RenderMode;
}
// 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.Linq;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.Windows;
using FlaxEngine;
namespace FlaxEditor.SceneGraph.Actors
@@ -22,9 +23,9 @@ namespace FlaxEditor.SceneGraph.Actors
}
/// <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;
if (actor && actor.SkinnedModel)

View File

@@ -6,6 +6,8 @@ using Real = System.Double;
using Real = System.Single;
#endif
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.Windows;
using FlaxEngine;
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 />
public override bool RayCastSelf(ref RayCastData ray, out Real distance, out Vector3 normal)
{

View File

@@ -3,6 +3,7 @@
using System.IO;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.SceneGraph.GUI;
using FlaxEditor.Windows;
using FlaxEngine;
namespace FlaxEditor.SceneGraph.Actors
@@ -65,7 +66,7 @@ namespace FlaxEditor.SceneGraph.Actors
public override SceneNode ParentScene => this;
/// <inheritdoc />
public override void OnContextMenu(ContextMenu contextMenu)
public override void OnContextMenu(ContextMenu contextMenu, EditorWindow window)
{
contextMenu.AddSeparator();
var path = Scene.Path;
@@ -80,7 +81,7 @@ namespace FlaxEditor.SceneGraph.Actors
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;
base.OnContextMenu(contextMenu);
base.OnContextMenu(contextMenu, window);
}
private void OnSelect()

View File

@@ -9,6 +9,7 @@ using Real = System.Single;
using System;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.Modules;
using FlaxEditor.Windows;
using FlaxEngine;
using FlaxEngine.Json;
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)
@@ -272,9 +273,9 @@ namespace FlaxEditor.SceneGraph.Actors
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()
@@ -354,9 +355,9 @@ namespace FlaxEditor.SceneGraph.Actors
}
/// <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 collider", OnAddSplineCollider);

View File

@@ -3,6 +3,7 @@
using System;
using FlaxEditor.Content;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.Windows;
using FlaxEngine;
namespace FlaxEditor.SceneGraph.Actors
@@ -21,9 +22,9 @@ namespace FlaxEditor.SceneGraph.Actors
}
/// <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;
}

View File

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

View File

@@ -11,6 +11,7 @@ using System.Collections.Generic;
using System.Linq;
using FlaxEditor.Modules;
using FlaxEditor.SceneGraph.Actors;
using FlaxEditor.Windows;
using FlaxEngine;
namespace FlaxEditor.SceneGraph
@@ -339,7 +340,7 @@ namespace FlaxEditor.SceneGraph
/// <summary>
/// Called when scene tree window wants to show the context menu. Allows to add custom options.
/// </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;
@@ -838,6 +838,15 @@ namespace FlaxEditor.Surface.Archetypes
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 />
public override void OnDestroy()
{
@@ -999,6 +1008,15 @@ namespace FlaxEditor.Surface.Archetypes
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 />
public override void OnDestroy()
{

View File

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

View File

@@ -820,8 +820,62 @@ namespace FlaxEditor.Surface.Elements
if (useCaster)
{
// Connect via Caster
//AddCaster(oB, iB);
throw new NotImplementedException("AddCaster(..) function");
const float casterXOffset = 250;
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
{

View File

@@ -2,6 +2,7 @@
using System;
using System.Linq;
using FlaxEditor.Content.Settings;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.GUI.Input;
using FlaxEditor.Options;
@@ -9,6 +10,8 @@ using FlaxEditor.Viewport.Cameras;
using FlaxEditor.Viewport.Widgets;
using FlaxEngine;
using FlaxEngine.GUI;
using Newtonsoft.Json;
using JsonSerializer = FlaxEngine.Json.JsonSerializer;
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
{
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("Disable flags", () => Task.ViewFlags = ViewFlags.None).Icon = Editor.Instance.Icons.Rotate32;
viewFlags.AddSeparator();
for (int i = 0; i < EditorViewportViewFlagsValues.Length; i++)
{
@@ -504,7 +560,7 @@ namespace FlaxEditor.Viewport
{
var v = (ViewFlags)button.Tag;
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;
@@ -513,6 +569,18 @@ namespace FlaxEditor.Viewport
// Debug View
{
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++)
{
ref var v = ref EditorViewportViewModeValues[i];
@@ -1084,9 +1152,9 @@ namespace FlaxEditor.Viewport
_isVirtualMouseRightDown = false; // Cancel when mouse right or escape is pressed
if (_wasVirtualMouseRightDown)
wasControllingMouse = true;
if (_isVirtualMouseRightDown)
if (_isVirtualMouseRightDown)
_isControllingMouse = _isVirtualMouseRightDown;
if (wasControllingMouse != _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)
{
var value = FlaxEngine.Input.GetGamepadAxis(InputGamepadIndex.All, axis);

View File

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

View File

@@ -151,7 +151,7 @@ namespace FlaxEditor.Windows.Assets
Graph = new LocalSceneGraph(new CustomRootNode(this));
_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,
};
_tree.AddChild(Graph.Root.TreeNode);

View File

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

View File

@@ -74,7 +74,7 @@ namespace FlaxEditor.Windows
root.TreeNode.Expand();
_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,
};
_tree.AddChild(root.TreeNode);

View File

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

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 vTangent = mesh.Tangents.HasItems() ? mesh.Tangents[vertexIndex] : Float3::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;
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 vTangent = mesh.Tangents.HasItems() ? mesh.Tangents[vertexIndex] : Float3::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;
for (int32 v = startIndex; v < end; v++)
@@ -201,6 +205,8 @@ int32 FindVertex(const MeshData& mesh, int32 vertexIndex, int32 startIndex, int3
continue;
if (mesh.LightmapUVs.HasItems() && (vLightmapUV - mesh.LightmapUVs[v]).LengthSquared() > uvEpsSqr)
continue;
if (mesh.Colors.HasItems() && vColor != mesh.Colors[v])
continue;
// TODO: check more components?
return v;

View File

@@ -39,5 +39,19 @@ namespace FlaxEngine
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;
}
void RenderView::CopyFrom(Camera* camera, Viewport* viewport)
void RenderView::CopyFrom(const Camera* camera, const Viewport* viewport)
{
const Vector3 cameraPos = camera->GetPosition();
LargeWorlds::UpdateOrigin(Origin, cameraPos);
@@ -192,6 +192,8 @@ void RenderView::CopyFrom(Camera* camera, Viewport* viewport)
Frustum.GetInvMatrix(IVP);
CullingFrustum = Frustum;
RenderLayersMask = camera->RenderLayersMask;
Flags = camera->RenderFlags;
Mode = camera->RenderMode;
}
void RenderView::GetWorldMatrix(const Transform& transform, Matrix& world) const

View File

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

View File

@@ -295,10 +295,12 @@ public:
/// <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);
// Copy view data from camera
// @param camera Camera to copy its data
// @param camera The custom viewport to use for view/projection matrices override.
void CopyFrom(Camera* camera, Viewport* viewport = nullptr);
/// <summary>
/// Copies view data from camera to the view.
/// </summary>
/// <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:
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(OrthoScale, _orthoScale);
SERIALIZE(RenderLayersMask);
SERIALIZE(RenderFlags);
SERIALIZE(RenderMode);
}
void Camera::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
@@ -429,6 +431,8 @@ void Camera::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier
DESERIALIZE_MEMBER(Far, _far);
DESERIALIZE_MEMBER(OrthoScale, _orthoScale);
DESERIALIZE(RenderLayersMask);
DESERIALIZE(RenderFlags);
DESERIALIZE(RenderMode);
}
void Camera::OnEnable()

View File

@@ -7,6 +7,7 @@
#include "Engine/Core/Math/Viewport.h"
#include "Engine/Core/Math/Ray.h"
#include "Engine/Core/Types/LayersMask.h"
#include "Engine/Graphics/Enums.h"
#include "Engine/Scripting/ScriptingObjectReference.h"
#if USE_EDITOR
#include "Engine/Content/AssetReference.h"
@@ -134,6 +135,18 @@ public:
API_FIELD(Attributes="EditorOrder(100), EditorDisplay(\"Camera\")")
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:
/// <summary>
/// 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 Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
};
#endif
public:
/// <summary>
@@ -127,7 +128,6 @@ public:
{
return (input[2] << 24) | (input[1] << 16) | (input[0] << 8);
}
#endif
};
#endif

View File

@@ -314,6 +314,28 @@ namespace FlaxEngine.GUI
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 />
public override bool OnTouchDown(Float2 location, int pointerId)
{

View File

@@ -277,6 +277,27 @@ namespace FlaxEngine.GUI
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 />
public override bool OnMouseUp(Float2 location, MouseButton button)
{

View File

@@ -666,6 +666,30 @@ namespace FlaxEngine.GUI
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 />
public override bool OnTouchDown(Float2 location, int pointerId)
{

View File

@@ -501,6 +501,29 @@ namespace FlaxEngine.GUI
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 />
public override void OnMouseLeave()
{

View File

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