Merge remote-tracking branch 'origin/master' into 1.9
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using FlaxEditor.CustomEditors.Elements;
|
||||
using FlaxEditor.Surface;
|
||||
using FlaxEngine;
|
||||
|
||||
@@ -12,6 +14,8 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
[CustomEditor(typeof(AnimatedModel)), DefaultEditor]
|
||||
public class AnimatedModelEditor : ActorEditor
|
||||
{
|
||||
private bool _parametersAdded = false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Initialize(LayoutElementsContainer layout)
|
||||
{
|
||||
@@ -31,6 +35,24 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
(instance, parameter, tag) => ((AnimatedModel)instance).GetParameterValue(parameter.Identifier),
|
||||
(instance, value, parameter, tag) => ((AnimatedModel)instance).SetParameterValue(parameter.Identifier, value),
|
||||
Values);
|
||||
_parametersAdded = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Refresh()
|
||||
{
|
||||
base.Refresh();
|
||||
|
||||
// Check if parameters group is still showing if not in play mode and hide it.
|
||||
if (!Editor.Instance.StateMachine.IsPlayMode && _parametersAdded)
|
||||
{
|
||||
var group = Layout.Children.Find(x => x is GroupElement g && g.Panel.HeaderText.Equals("Parameters", StringComparison.Ordinal));
|
||||
if (group != null)
|
||||
{
|
||||
RebuildLayout();
|
||||
_parametersAdded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,6 +178,8 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
return 1;
|
||||
if (Info.MetadataToken < other.Info.MetadataToken)
|
||||
return -1;
|
||||
// Keep declaration order if same metadata token.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// By name
|
||||
|
||||
@@ -138,18 +138,17 @@ namespace FlaxEditor.Gizmo
|
||||
|
||||
private void UpdateGizmoPosition()
|
||||
{
|
||||
var position = Vector3.Zero;
|
||||
|
||||
// Get gizmo pivot
|
||||
switch (_activePivotType)
|
||||
{
|
||||
case PivotType.ObjectCenter:
|
||||
if (SelectionCount > 0)
|
||||
Position = GetSelectedTransform(0).Translation;
|
||||
position = GetSelectedTransform(0).Translation;
|
||||
break;
|
||||
case PivotType.SelectionCenter:
|
||||
Position = GetSelectionCenter();
|
||||
break;
|
||||
case PivotType.WorldOrigin:
|
||||
Position = Vector3.Zero;
|
||||
position = GetSelectionCenter();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -157,11 +156,13 @@ namespace FlaxEditor.Gizmo
|
||||
if (_vertexSnapObject != null)
|
||||
{
|
||||
Vector3 vertexSnapPoint = _vertexSnapObject.Transform.LocalToWorld(_vertexSnapPoint);
|
||||
Position += vertexSnapPoint - Position;
|
||||
position += vertexSnapPoint - position;
|
||||
}
|
||||
|
||||
// Apply current movement
|
||||
Position += _translationDelta;
|
||||
position += _translationDelta;
|
||||
|
||||
Position = position;
|
||||
}
|
||||
|
||||
private void UpdateMatrices()
|
||||
@@ -213,10 +214,11 @@ namespace FlaxEditor.Gizmo
|
||||
ray.Position = Vector3.Transform(ray.Position, invRotationMatrix);
|
||||
Vector3.TransformNormal(ref ray.Direction, ref invRotationMatrix, out ray.Direction);
|
||||
|
||||
var planeXY = new Plane(Vector3.Backward, Vector3.Transform(Position, invRotationMatrix).Z);
|
||||
var planeYZ = new Plane(Vector3.Left, Vector3.Transform(Position, invRotationMatrix).X);
|
||||
var planeZX = new Plane(Vector3.Down, Vector3.Transform(Position, invRotationMatrix).Y);
|
||||
var dir = Vector3.Normalize(ray.Position - Position);
|
||||
var position = Position;
|
||||
var planeXY = new Plane(Vector3.Backward, Vector3.Transform(position, invRotationMatrix).Z);
|
||||
var planeYZ = new Plane(Vector3.Left, Vector3.Transform(position, invRotationMatrix).X);
|
||||
var planeZX = new Plane(Vector3.Down, Vector3.Transform(position, invRotationMatrix).Y);
|
||||
var dir = Vector3.Normalize(ray.Position - position);
|
||||
var planeDotXY = Mathf.Abs(Vector3.Dot(planeXY.Normal, dir));
|
||||
var planeDotYZ = Mathf.Abs(Vector3.Dot(planeYZ.Normal, dir));
|
||||
var planeDotZX = Mathf.Abs(Vector3.Dot(planeZX.Normal, dir));
|
||||
@@ -229,8 +231,8 @@ namespace FlaxEditor.Gizmo
|
||||
var plane = planeDotXY > planeDotZX ? planeXY : planeZX;
|
||||
if (ray.Intersects(ref plane, out intersection))
|
||||
{
|
||||
_intersectPosition = ray.Position + ray.Direction * intersection;
|
||||
if (_lastIntersectionPosition != Vector3.Zero)
|
||||
_intersectPosition = ray.GetPoint(intersection);
|
||||
if (!_lastIntersectionPosition.IsZero)
|
||||
_tDelta = _intersectPosition - _lastIntersectionPosition;
|
||||
delta = new Vector3(_tDelta.X, 0, 0);
|
||||
}
|
||||
@@ -241,8 +243,8 @@ namespace FlaxEditor.Gizmo
|
||||
var plane = planeDotXY > planeDotYZ ? planeXY : planeYZ;
|
||||
if (ray.Intersects(ref plane, out intersection))
|
||||
{
|
||||
_intersectPosition = ray.Position + ray.Direction * intersection;
|
||||
if (_lastIntersectionPosition != Vector3.Zero)
|
||||
_intersectPosition = ray.GetPoint(intersection);
|
||||
if (!_lastIntersectionPosition.IsZero)
|
||||
_tDelta = _intersectPosition - _lastIntersectionPosition;
|
||||
delta = new Vector3(0, _tDelta.Y, 0);
|
||||
}
|
||||
@@ -253,8 +255,8 @@ namespace FlaxEditor.Gizmo
|
||||
var plane = planeDotZX > planeDotYZ ? planeZX : planeYZ;
|
||||
if (ray.Intersects(ref plane, out intersection))
|
||||
{
|
||||
_intersectPosition = ray.Position + ray.Direction * intersection;
|
||||
if (_lastIntersectionPosition != Vector3.Zero)
|
||||
_intersectPosition = ray.GetPoint(intersection);
|
||||
if (!_lastIntersectionPosition.IsZero)
|
||||
_tDelta = _intersectPosition - _lastIntersectionPosition;
|
||||
delta = new Vector3(0, 0, _tDelta.Z);
|
||||
}
|
||||
@@ -264,8 +266,8 @@ namespace FlaxEditor.Gizmo
|
||||
{
|
||||
if (ray.Intersects(ref planeYZ, out intersection))
|
||||
{
|
||||
_intersectPosition = ray.Position + ray.Direction * intersection;
|
||||
if (_lastIntersectionPosition != Vector3.Zero)
|
||||
_intersectPosition = ray.GetPoint(intersection);
|
||||
if (!_lastIntersectionPosition.IsZero)
|
||||
_tDelta = _intersectPosition - _lastIntersectionPosition;
|
||||
delta = new Vector3(0, _tDelta.Y, _tDelta.Z);
|
||||
}
|
||||
@@ -275,8 +277,8 @@ namespace FlaxEditor.Gizmo
|
||||
{
|
||||
if (ray.Intersects(ref planeXY, out intersection))
|
||||
{
|
||||
_intersectPosition = ray.Position + ray.Direction * intersection;
|
||||
if (_lastIntersectionPosition != Vector3.Zero)
|
||||
_intersectPosition = ray.GetPoint(intersection);
|
||||
if (!_lastIntersectionPosition.IsZero)
|
||||
_tDelta = _intersectPosition - _lastIntersectionPosition;
|
||||
delta = new Vector3(_tDelta.X, _tDelta.Y, 0);
|
||||
}
|
||||
@@ -286,8 +288,8 @@ namespace FlaxEditor.Gizmo
|
||||
{
|
||||
if (ray.Intersects(ref planeZX, out intersection))
|
||||
{
|
||||
_intersectPosition = ray.Position + ray.Direction * intersection;
|
||||
if (_lastIntersectionPosition != Vector3.Zero)
|
||||
_intersectPosition = ray.GetPoint(intersection);
|
||||
if (!_lastIntersectionPosition.IsZero)
|
||||
_tDelta = _intersectPosition - _lastIntersectionPosition;
|
||||
delta = new Vector3(_tDelta.X, 0, _tDelta.Z);
|
||||
}
|
||||
@@ -299,8 +301,8 @@ namespace FlaxEditor.Gizmo
|
||||
var plane = new Plane(-Vector3.Normalize(gizmoToView), gizmoToView.Length);
|
||||
if (ray.Intersects(ref plane, out intersection))
|
||||
{
|
||||
_intersectPosition = ray.Position + ray.Direction * intersection;
|
||||
if (_lastIntersectionPosition != Vector3.Zero)
|
||||
_intersectPosition = ray.GetPoint(intersection);
|
||||
if (!_lastIntersectionPosition.IsZero)
|
||||
_tDelta = _intersectPosition - _lastIntersectionPosition;
|
||||
}
|
||||
delta = _tDelta;
|
||||
@@ -412,10 +414,8 @@ namespace FlaxEditor.Gizmo
|
||||
public override void Update(float dt)
|
||||
{
|
||||
LastDelta = Transform.Identity;
|
||||
|
||||
if (!IsActive)
|
||||
return;
|
||||
|
||||
bool isLeftBtnDown = Owner.IsLeftMouseButtonDown;
|
||||
|
||||
// Snap to ground
|
||||
@@ -516,6 +516,7 @@ namespace FlaxEditor.Gizmo
|
||||
{
|
||||
// Clear cache
|
||||
_accMoveDelta = Vector3.Zero;
|
||||
_lastIntersectionPosition = _intersectPosition = Vector3.Zero;
|
||||
EndTransforming();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -717,6 +717,9 @@ namespace FlaxEditor.Modules
|
||||
/// <param name="rebuild">Should rebuild entire database after addition.</param>
|
||||
public void AddProxy(ContentProxy proxy, bool rebuild = false)
|
||||
{
|
||||
var oldProxy = Proxy.Find(x => x.GetType().ToString().Equals(proxy.GetType().ToString(), StringComparison.Ordinal));
|
||||
if (oldProxy != null)
|
||||
RemoveProxy(oldProxy);
|
||||
Proxy.Insert(0, proxy);
|
||||
if (rebuild)
|
||||
Rebuild(true);
|
||||
|
||||
@@ -24,6 +24,13 @@ namespace FlaxEditor.Options
|
||||
[DefaultValue(1.0f), Limit(0.01f, 100.0f)]
|
||||
[EditorDisplay("General"), EditorOrder(101), Tooltip("The mouse wheel sensitivity applied to zoom in orthographic mode.")]
|
||||
public float MouseWheelSensitivity { get; set; } = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether to invert the Y rotation of the mouse in the editor viewport.
|
||||
/// </summary>
|
||||
[DefaultValue(false)]
|
||||
[EditorDisplay("General"), EditorOrder(102), Tooltip("Whether to invert the Y rotation of the mouse in the editor viewport.")]
|
||||
public bool InvertMouseYAxisRotation { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the total amount of steps the camera needs to go from minimum to maximum speed.
|
||||
|
||||
@@ -111,6 +111,9 @@ namespace FlaxEditor.Viewport
|
||||
IsMouseRightDown = useMouse && window.GetMouseButton(MouseButton.Right);
|
||||
IsMouseMiddleDown = useMouse && window.GetMouseButton(MouseButton.Middle);
|
||||
IsMouseLeftDown = useMouse && window.GetMouseButton(MouseButton.Left);
|
||||
|
||||
if (WasAltDownBefore && !IsMouseLeftDown && !IsAltDown)
|
||||
WasAltDownBefore = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1385,15 +1388,32 @@ namespace FlaxEditor.Viewport
|
||||
/// <summary>
|
||||
/// Converts the mouse position to the ray (in world space of the viewport).
|
||||
/// </summary>
|
||||
/// <param name="mousePosition">The mouse position.</param>
|
||||
/// <param name="mousePosition">The mouse position (in UI space of the viewport [0; Size]).</param>
|
||||
/// <returns>The result ray.</returns>
|
||||
public Ray ConvertMouseToRay(ref Float2 mousePosition)
|
||||
{
|
||||
// Prepare
|
||||
var viewport = new FlaxEngine.Viewport(0, 0, Width, Height);
|
||||
CreateProjectionMatrix(out var p);
|
||||
if (viewport.Width < Mathf.Epsilon || viewport.Height < Mathf.Epsilon)
|
||||
return ViewRay;
|
||||
|
||||
Vector3 viewOrigin = Task.View.Origin;
|
||||
Float3 position = ViewPosition - viewOrigin;
|
||||
|
||||
// Use different logic in orthographic projection
|
||||
if (_isOrtho)
|
||||
{
|
||||
var screenPosition = new Float2(mousePosition.X / viewport.Width - 0.5f, -mousePosition.Y / viewport.Height + 0.5f);
|
||||
var orientation = ViewOrientation;
|
||||
var direction = Float3.Forward * orientation;
|
||||
var rayOrigin = new Vector3(screenPosition.X * viewport.Width * _orthoSize, screenPosition.Y * viewport.Height * _orthoSize, 0);
|
||||
rayOrigin = position + Vector3.Transform(rayOrigin, orientation);
|
||||
rayOrigin += direction * _nearPlane;
|
||||
rayOrigin += viewOrigin;
|
||||
return new Ray(rayOrigin, direction);
|
||||
}
|
||||
|
||||
// Create view frustum
|
||||
CreateProjectionMatrix(out var p);
|
||||
CreateViewMatrix(position, out var v);
|
||||
Matrix.Multiply(ref v, ref p, out var ivp);
|
||||
ivp.Invert();
|
||||
@@ -1404,11 +1424,7 @@ namespace FlaxEditor.Viewport
|
||||
viewport.Unproject(ref nearPoint, ref ivp, out nearPoint);
|
||||
viewport.Unproject(ref farPoint, ref ivp, out farPoint);
|
||||
|
||||
// Create direction vector
|
||||
Vector3 direction = farPoint - nearPoint;
|
||||
direction.Normalize();
|
||||
|
||||
return new Ray(nearPoint + viewOrigin, direction);
|
||||
return new Ray(nearPoint + viewOrigin, Vector3.Normalize(farPoint - nearPoint));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1704,6 +1720,8 @@ namespace FlaxEditor.Viewport
|
||||
// Update
|
||||
moveDelta *= dt * (60.0f * 4.0f);
|
||||
mouseDelta *= 0.1833f * MouseSpeed * _mouseSensitivity;
|
||||
if (options.Viewport.InvertMouseYAxisRotation)
|
||||
mouseDelta *= new Float2(1, -1);
|
||||
UpdateView(dt, ref moveDelta, ref mouseDelta, out var centerMouse);
|
||||
|
||||
// Move mouse back to the root position
|
||||
|
||||
@@ -627,8 +627,8 @@ namespace FlaxEditor.Viewport
|
||||
}
|
||||
|
||||
// Debug draw all actors in prefab and collect actors
|
||||
var viewFlags = Task.ViewFlags;
|
||||
var collectActors = (viewFlags & ViewFlags.PhysicsDebug) != 0 || (viewFlags & ViewFlags.LightsDebug) != 0;
|
||||
var view = Task.View;
|
||||
var collectActors = (view.Flags & ViewFlags.PhysicsDebug) != 0 || view.Mode == ViewMode.PhysicsColliders || (view.Flags & ViewFlags.LightsDebug) != 0;
|
||||
_debugDrawActors.Clear();
|
||||
foreach (var child in SceneGraphRoot.ChildNodes)
|
||||
{
|
||||
@@ -641,19 +641,17 @@ namespace FlaxEditor.Viewport
|
||||
}
|
||||
|
||||
// Draw physics debug
|
||||
if ((viewFlags & ViewFlags.PhysicsDebug) != 0)
|
||||
if ((view.Flags & ViewFlags.PhysicsDebug) != 0 || view.Mode == ViewMode.PhysicsColliders)
|
||||
{
|
||||
foreach (var actor in _debugDrawActors)
|
||||
{
|
||||
if (actor is Collider c && c.IsActiveInHierarchy)
|
||||
{
|
||||
DebugDraw.DrawColliderDebugPhysics(c, renderContext.View);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw lights debug
|
||||
if ((viewFlags & ViewFlags.LightsDebug) != 0)
|
||||
if ((view.Flags & ViewFlags.LightsDebug) != 0)
|
||||
{
|
||||
foreach (var actor in _debugDrawActors)
|
||||
{
|
||||
|
||||
@@ -80,6 +80,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
private AnimationWindow Window;
|
||||
private Animation Asset;
|
||||
private ModelImportSettings ImportSettings = new ModelImportSettings();
|
||||
private bool EnablePreviewModelCache = true;
|
||||
|
||||
[EditorDisplay("Preview"), NoSerialize, AssetReference(true), Tooltip("The skinned model to preview the animation playback.")]
|
||||
public SkinnedModel PreviewModel
|
||||
@@ -134,6 +135,15 @@ namespace FlaxEditor.Windows.Assets
|
||||
value.WaitForLoaded(500);
|
||||
Window._preview.ViewportCamera.SetArcBallView(Window._preview.PreviewActor.Sphere);
|
||||
}
|
||||
|
||||
if (EnablePreviewModelCache)
|
||||
{
|
||||
var customDataName = Window.GetPreviewModelCacheName();
|
||||
if (value)
|
||||
Window.Editor.ProjectCache.SetCustomData(customDataName, value.ID.ToString());
|
||||
else
|
||||
Window.Editor.ProjectCache.RemoveCustomData(customDataName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +152,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
// Link
|
||||
Window = window;
|
||||
Asset = window.Asset;
|
||||
EnablePreviewModelCache = true;
|
||||
|
||||
// Try to restore target asset import options (useful for fast reimport)
|
||||
Editor.TryRestoreImportOptions(ref ImportSettings.Settings, window.Item.Path);
|
||||
@@ -150,6 +161,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
public void OnClean()
|
||||
{
|
||||
// Unlink
|
||||
EnablePreviewModelCache = false;
|
||||
PreviewModel = null;
|
||||
Window = null;
|
||||
Asset = null;
|
||||
@@ -287,12 +299,23 @@ namespace FlaxEditor.Windows.Assets
|
||||
UpdateToolstrip();
|
||||
}
|
||||
|
||||
private string GetPreviewModelCacheName()
|
||||
{
|
||||
return _asset.ID + ".PreviewModel";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnAssetLoaded()
|
||||
{
|
||||
_properties.OnLoad(this);
|
||||
_propertiesPresenter.BuildLayout();
|
||||
ClearEditedFlag();
|
||||
if (!_initialPreviewModel &&
|
||||
Editor.ProjectCache.TryGetCustomData(GetPreviewModelCacheName(), out string str) &&
|
||||
Guid.TryParse(str, out var id))
|
||||
{
|
||||
_initialPreviewModel = FlaxEngine.Content.LoadAsync<SkinnedModel>(id);
|
||||
}
|
||||
if (_initialPreviewModel)
|
||||
{
|
||||
_properties.PreviewModel = _initialPreviewModel;
|
||||
|
||||
@@ -396,6 +396,7 @@ void AudioClip::unload(bool isReloading)
|
||||
}
|
||||
|
||||
StopStreaming();
|
||||
CancelStreamingTasks();
|
||||
StreamingQueue.Clear();
|
||||
if (hasAnyBuffer && AudioBackend::Instance)
|
||||
{
|
||||
|
||||
@@ -788,7 +788,7 @@ void DebugDraw::Draw(RenderContext& renderContext, GPUTextureView* target, GPUTe
|
||||
Matrix vp;
|
||||
Matrix::Multiply(view.View, view.Projection, vp);
|
||||
Matrix::Transpose(vp, data.ViewProjection);
|
||||
data.ClipPosZBias = -0.2f; // Reduce Z-fighting artifacts (eg. editor grid)
|
||||
data.ClipPosZBias = view.IsPerspectiveProjection() ? -0.2f : 0.0f; // Reduce Z-fighting artifacts (eg. editor grid)
|
||||
data.EnableDepthTest = enableDepthTest;
|
||||
context->UpdateCB(cb, &data);
|
||||
context->BindCB(0, cb);
|
||||
@@ -953,11 +953,11 @@ void DebugDraw::DrawActorsTree(Actor* actor)
|
||||
}
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
void DebugDraw::DrawColliderDebugPhysics(Collider* collider, RenderView& view)
|
||||
{
|
||||
if (!collider)
|
||||
return;
|
||||
|
||||
collider->DrawPhysicsDebug(view);
|
||||
}
|
||||
|
||||
@@ -965,10 +965,11 @@ void DebugDraw::DrawLightDebug(Light* light, RenderView& view)
|
||||
{
|
||||
if (!light)
|
||||
return;
|
||||
|
||||
light->DrawLightsDebug(view);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void DebugDraw::DrawAxisFromDirection(const Vector3& origin, const Vector3& direction, float size, float duration, bool depthTest)
|
||||
{
|
||||
CHECK_DEBUG(direction.IsNormalized());
|
||||
|
||||
@@ -75,6 +75,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
|
||||
/// </summary>
|
||||
/// <param name="actor">The actor to start drawing at.</param>
|
||||
API_FUNCTION() static void DrawActorsTree(Actor* actor);
|
||||
|
||||
#if USE_EDITOR
|
||||
/// <summary>
|
||||
/// Draws the physics debug shapes for the given collider. Editor Only
|
||||
@@ -90,6 +91,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
|
||||
/// <param name="view">The render view to draw in.</param>
|
||||
API_FUNCTION() static void DrawLightDebug(Light* light, RenderView& view);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Draws the lines axis from direction.
|
||||
/// </summary>
|
||||
|
||||
@@ -60,6 +60,7 @@ namespace FlaxEngine
|
||||
~InputAxis()
|
||||
{
|
||||
Input.AxisValueChanged -= Handler;
|
||||
ValueChanged = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -68,6 +69,7 @@ namespace FlaxEngine
|
||||
public void Dispose()
|
||||
{
|
||||
Input.AxisValueChanged -= Handler;
|
||||
ValueChanged = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -70,6 +70,10 @@ namespace FlaxEngine
|
||||
~InputEvent()
|
||||
{
|
||||
Input.ActionTriggered -= Handler;
|
||||
Triggered = null;
|
||||
Pressed = null;
|
||||
Pressing = null;
|
||||
Released = null;
|
||||
}
|
||||
|
||||
private void Handler(string name, InputActionState state)
|
||||
@@ -100,6 +104,10 @@ namespace FlaxEngine
|
||||
public void Dispose()
|
||||
{
|
||||
Input.ActionTriggered -= Handler;
|
||||
Triggered = null;
|
||||
Pressed = null;
|
||||
Pressing = null;
|
||||
Released = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -157,6 +157,8 @@ void InputSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* m
|
||||
config.Gamepad = JsonTools::GetEnum(v, "Gamepad", InputGamepadIndex::All);
|
||||
config.PositiveButton = JsonTools::GetEnum(v, "PositiveButton", KeyboardKeys::None);
|
||||
config.NegativeButton = JsonTools::GetEnum(v, "NegativeButton", KeyboardKeys::None);
|
||||
config.GamepadPositiveButton = JsonTools::GetEnum(v, "GamepadPositiveButton", GamepadButton::None);
|
||||
config.GamepadNegativeButton = JsonTools::GetEnum(v, "GamepadNegativeButton", GamepadButton::None);
|
||||
config.DeadZone = JsonTools::GetFloat(v, "DeadZone", 0.1f);
|
||||
config.Sensitivity = JsonTools::GetFloat(v, "Sensitivity", 0.4f);
|
||||
config.Gravity = JsonTools::GetFloat(v, "Gravity", 1.0f);
|
||||
@@ -873,8 +875,8 @@ void InputService::Update()
|
||||
const AxisData& data = Axes[name];
|
||||
|
||||
// Get key raw value
|
||||
const bool isPositiveKey = Input::GetKey(config.PositiveButton);
|
||||
const bool isNegativeKey = Input::GetKey(config.NegativeButton);
|
||||
const bool isPositiveKey = Input::GetKey(config.PositiveButton) || Input::GetGamepadButton(config.Gamepad, config.GamepadPositiveButton);
|
||||
const bool isNegativeKey = Input::GetKey(config.NegativeButton) || Input::GetGamepadButton(config.Gamepad, config.GamepadNegativeButton);
|
||||
float keyRawValue = 0;
|
||||
if (isPositiveKey && !isNegativeKey)
|
||||
{
|
||||
|
||||
@@ -87,6 +87,18 @@ API_STRUCT() struct AxisConfig
|
||||
API_FIELD(Attributes="EditorOrder(40)")
|
||||
KeyboardKeys NegativeButton;
|
||||
|
||||
/// <summary>
|
||||
/// The button to be pressed for movement in positive direction. Use <see cref="GamepadButton.None"/> to ignore it.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(45)")
|
||||
GamepadButton GamepadPositiveButton;
|
||||
|
||||
/// <summary>
|
||||
/// The button to be pressed for movement in negative direction. Use <see cref="GamepadButton.None"/> to ignore it.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(46)")
|
||||
GamepadButton GamepadNegativeButton;
|
||||
|
||||
/// <summary>
|
||||
/// Any positive or negative values that are less than this number will register as zero. Useful for gamepads to specify the deadzone.
|
||||
/// </summary>
|
||||
|
||||
@@ -39,6 +39,7 @@ Camera::Camera(const SpawnParams& params)
|
||||
, _customAspectRatio(0.0f)
|
||||
, _near(10.0f)
|
||||
, _far(40000.0f)
|
||||
, _orthoSize(0.0f)
|
||||
, _orthoScale(1.0f)
|
||||
{
|
||||
#if USE_EDITOR
|
||||
@@ -120,6 +121,21 @@ void Camera::SetFarPlane(float value)
|
||||
}
|
||||
}
|
||||
|
||||
float Camera::GetOrthographicSize() const
|
||||
{
|
||||
return _orthoSize;
|
||||
}
|
||||
|
||||
void Camera::SetOrthographicSize(float value)
|
||||
{
|
||||
value = Math::Clamp(value, 0.0f, 1000000.0f);
|
||||
if (Math::NotNearEqual(_orthoSize, value))
|
||||
{
|
||||
_orthoSize = value;
|
||||
UpdateCache();
|
||||
}
|
||||
}
|
||||
|
||||
float Camera::GetOrthographicScale() const
|
||||
{
|
||||
return _orthoScale;
|
||||
@@ -191,39 +207,37 @@ Ray Camera::ConvertMouseToRay(const Float2& mousePosition) const
|
||||
|
||||
Ray Camera::ConvertMouseToRay(const Float2& mousePosition, const Viewport& viewport) const
|
||||
{
|
||||
#if 1
|
||||
// Gather camera properties
|
||||
Vector3 position = GetPosition();
|
||||
if (viewport.Width < ZeroTolerance || viewport.Height < ZeroTolerance)
|
||||
return Ray(position, GetDirection());
|
||||
|
||||
// Use different logic in orthographic projection
|
||||
if (!_usePerspective)
|
||||
{
|
||||
Float2 screenPosition(mousePosition.X / viewport.Width - 0.5f, -mousePosition.Y / viewport.Height + 0.5f);
|
||||
Quaternion orientation = GetOrientation();
|
||||
Float3 direction = orientation * Float3::Forward;
|
||||
const float orthoSize = (_orthoSize > 0.0f ? _orthoSize : viewport.Height) * _orthoScale;
|
||||
const float aspect = _customAspectRatio <= 0.0f ? viewport.GetAspectRatio() : _customAspectRatio;
|
||||
Vector3 rayOrigin(screenPosition.X * orthoSize * aspect, screenPosition.Y * orthoSize, 0);
|
||||
rayOrigin = position + Vector3::Transform(rayOrigin, orientation);
|
||||
rayOrigin += direction * _near;
|
||||
return Ray(rayOrigin, direction);
|
||||
}
|
||||
|
||||
// Create view frustum
|
||||
Matrix v, p, ivp;
|
||||
GetMatrices(v, p, viewport);
|
||||
Matrix::Multiply(v, p, ivp);
|
||||
ivp.Invert();
|
||||
|
||||
// Create near and far points
|
||||
Vector3 nearPoint(mousePosition, 0.0f);
|
||||
Vector3 farPoint(mousePosition, 1.0f);
|
||||
Vector3 nearPoint(mousePosition, _near);
|
||||
Vector3 farPoint(mousePosition, _far);
|
||||
viewport.Unproject(nearPoint, ivp, nearPoint);
|
||||
viewport.Unproject(farPoint, ivp, farPoint);
|
||||
|
||||
// Create direction vector
|
||||
Vector3 direction = farPoint - nearPoint;
|
||||
direction.Normalize();
|
||||
|
||||
return Ray(nearPoint, direction);
|
||||
#else
|
||||
// Create near and far points
|
||||
Vector3 nearPoint, farPoint;
|
||||
Matrix ivp;
|
||||
_frustum.GetInvMatrix(&ivp);
|
||||
viewport.Unproject(Vector3(mousePosition, 0.0f), ivp, nearPoint);
|
||||
viewport.Unproject(Vector3(mousePosition, 1.0f), ivp, farPoint);
|
||||
|
||||
// Create direction vector
|
||||
Vector3 direction = farPoint - nearPoint;
|
||||
direction.Normalize();
|
||||
|
||||
// Return result
|
||||
return Ray(nearPoint, direction);
|
||||
#endif
|
||||
return Ray(nearPoint, Vector3::Normalize(farPoint - nearPoint));
|
||||
}
|
||||
|
||||
Viewport Camera::GetViewport() const
|
||||
@@ -264,14 +278,15 @@ void Camera::GetMatrices(Matrix& view, Matrix& projection, const Viewport& viewp
|
||||
void Camera::GetMatrices(Matrix& view, Matrix& projection, const Viewport& viewport, const Vector3& origin) const
|
||||
{
|
||||
// Create projection matrix
|
||||
const float aspect = _customAspectRatio <= 0.0f ? viewport.GetAspectRatio() : _customAspectRatio;
|
||||
if (_usePerspective)
|
||||
{
|
||||
const float aspect = _customAspectRatio <= 0.0f ? viewport.GetAspectRatio() : _customAspectRatio;
|
||||
Matrix::PerspectiveFov(_fov * DegreesToRadians, aspect, _near, _far, projection);
|
||||
}
|
||||
else
|
||||
{
|
||||
Matrix::Ortho(viewport.Width * _orthoScale, viewport.Height * _orthoScale, _near, _far, projection);
|
||||
const float orthoSize = (_orthoSize > 0.0f ? _orthoSize : viewport.Height) * _orthoScale;
|
||||
Matrix::Ortho(orthoSize * aspect, orthoSize, _near, _far, projection);
|
||||
}
|
||||
|
||||
// Create view matrix
|
||||
|
||||
@@ -44,6 +44,7 @@ private:
|
||||
float _customAspectRatio;
|
||||
float _near;
|
||||
float _far;
|
||||
float _orthoSize;
|
||||
float _orthoScale;
|
||||
|
||||
#if USE_EDITOR
|
||||
@@ -88,7 +89,7 @@ public:
|
||||
/// <summary>
|
||||
/// Gets the custom aspect ratio. 0 if not use custom value.
|
||||
/// </summary>
|
||||
API_PROPERTY(Attributes="EditorOrder(50), DefaultValue(0.0f), Limit(0, 10, 0.01f), EditorDisplay(\"Camera\"), VisibleIf(nameof(UsePerspective))")
|
||||
API_PROPERTY(Attributes="EditorOrder(50), DefaultValue(0.0f), Limit(0, 10, 0.01f), EditorDisplay(\"Camera\")")
|
||||
float GetCustomAspectRatio() const;
|
||||
|
||||
/// <summary>
|
||||
@@ -118,6 +119,17 @@ public:
|
||||
/// </summary>
|
||||
API_PROPERTY() void SetFarPlane(float value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the orthographic projection view height (width is based on the aspect ratio). Use `0` for size to be based on the viewport size.
|
||||
/// </summary>
|
||||
API_PROPERTY(Attributes="EditorOrder(59), DefaultValue(0.0f), Limit(0.0f), EditorDisplay(\"Camera\"), VisibleIf(nameof(UsePerspective), true)")
|
||||
float GetOrthographicSize() const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the orthographic projection view height (width is based on the aspect ratio). Use `0` for size to be based on the viewport size.
|
||||
/// </summary>
|
||||
API_PROPERTY() void SetOrthographicSize(float value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the orthographic projection scale.
|
||||
/// </summary>
|
||||
|
||||
@@ -123,6 +123,7 @@ public:
|
||||
/// <returns>The scene object (loaded).</returns>
|
||||
API_FUNCTION() static Scene* GetScene(int32 index)
|
||||
{
|
||||
CHECK_RETURN(index < GetScenesCount(), nullptr);
|
||||
return Scenes[index];
|
||||
}
|
||||
|
||||
|
||||
@@ -219,7 +219,7 @@ Asset::LoadResult ParticleEmitter::load()
|
||||
ClearDependencies();
|
||||
for (const auto& node : Graph.Nodes)
|
||||
{
|
||||
if (node.Type == GRAPH_NODE_MAKE_TYPE(14, 300))
|
||||
if (node.Type == GRAPH_NODE_MAKE_TYPE(14, 300) && node.Assets.Count() > 0)
|
||||
{
|
||||
const auto function = node.Assets[0].As<ParticleEmitterFunction>();
|
||||
if (function)
|
||||
|
||||
@@ -143,9 +143,11 @@ namespace FlaxEngine.GUI
|
||||
if (!Mathf.NearEqual(value, _value))
|
||||
{
|
||||
_value = value;
|
||||
if (!UseSmoothing)
|
||||
if (!UseSmoothing || _firstUpdate)
|
||||
{
|
||||
_current = _value;
|
||||
if (_firstUpdate)
|
||||
_firstUpdate = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,6 +171,9 @@ namespace FlaxEngine.GUI
|
||||
[EditorDisplay("Bar Style"), EditorOrder(2012), Tooltip("The brush used for progress bar drawing.")]
|
||||
public IBrush BarBrush { get; set; }
|
||||
|
||||
// Used to remove initial lerp from the value on play.
|
||||
private bool _firstUpdate = true;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ProgressBar"/> class.
|
||||
/// </summary>
|
||||
|
||||
@@ -18,7 +18,7 @@ SpriteRender::SpriteRender(const SpawnParams& params)
|
||||
{
|
||||
_quadModel = Content::LoadAsyncInternal<Model>(TEXT("Engine/Models/Quad"));
|
||||
Material.Loaded.Bind<SpriteRender, &SpriteRender::OnMaterialLoaded>(this);
|
||||
Image.Changed.Bind<SpriteRender, &SpriteRender::SetImage>(this);
|
||||
Image.Changed.Bind<SpriteRender, &SpriteRender::SetImageParam>(this);
|
||||
}
|
||||
|
||||
Float2 SpriteRender::GetSize() const
|
||||
@@ -42,8 +42,7 @@ Color SpriteRender::GetColor() const
|
||||
void SpriteRender::SetColor(const Color& value)
|
||||
{
|
||||
_color = value;
|
||||
if (_paramColor)
|
||||
_paramColor->SetValue(value);
|
||||
SetColorParam();
|
||||
}
|
||||
|
||||
SpriteHandle SpriteRender::GetSprite() const
|
||||
@@ -54,7 +53,7 @@ SpriteHandle SpriteRender::GetSprite() const
|
||||
void SpriteRender::SetSprite(const SpriteHandle& value)
|
||||
{
|
||||
_sprite = value;
|
||||
SetImage();
|
||||
SetImageParam();
|
||||
}
|
||||
|
||||
void SpriteRender::OnMaterialLoaded()
|
||||
@@ -66,6 +65,7 @@ void SpriteRender::OnMaterialLoaded()
|
||||
_materialInstance->AddReference();
|
||||
}
|
||||
_materialInstance->SetBaseMaterial(Material);
|
||||
_materialInstance->ResetParameters();
|
||||
|
||||
// Cache parameters
|
||||
_paramImageMAD = _materialInstance->GetParameter(TEXT("ImageMAD"));
|
||||
@@ -75,15 +75,15 @@ void SpriteRender::OnMaterialLoaded()
|
||||
if (_paramImage && _paramImage->GetParameterType() != MaterialParameterType::Texture)
|
||||
_paramImage = nullptr;
|
||||
else if (_paramImage)
|
||||
SetImage();
|
||||
SetImageParam();
|
||||
_paramColor = _materialInstance->GetParameter(TEXT("Color"));
|
||||
if (_paramColor && _paramColor->GetParameterType() != MaterialParameterType::Color && _paramColor->GetParameterType() != MaterialParameterType::Vector4 && _paramColor->GetParameterType() != MaterialParameterType::Vector3)
|
||||
_paramColor = nullptr;
|
||||
else if (_paramColor)
|
||||
_paramColor->SetValue(_color);
|
||||
SetColorParam();
|
||||
}
|
||||
|
||||
void SpriteRender::SetImage()
|
||||
void SpriteRender::SetImageParam()
|
||||
{
|
||||
TextureBase* image = Image.Get();
|
||||
Vector4 imageMAD(Vector2::One, Vector2::Zero);
|
||||
@@ -94,9 +94,24 @@ void SpriteRender::SetImage()
|
||||
imageMAD = Vector4(sprite->Area.Size, sprite->Area.Location);
|
||||
}
|
||||
if (_paramImage)
|
||||
{
|
||||
_paramImage->SetValue(image);
|
||||
_paramImage->SetIsOverride(true);
|
||||
}
|
||||
if (_paramImageMAD)
|
||||
{
|
||||
_paramImageMAD->SetValue(imageMAD);
|
||||
_paramImageMAD->SetIsOverride(true);
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteRender::SetColorParam()
|
||||
{
|
||||
if (_paramColor)
|
||||
{
|
||||
_paramColor->SetValue(_color);
|
||||
_paramColor->SetIsOverride(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool SpriteRender::HasContentLoaded() const
|
||||
@@ -164,9 +179,8 @@ void SpriteRender::Deserialize(DeserializeStream& stream, ISerializeModifier* mo
|
||||
DESERIALIZE(DrawModes);
|
||||
DESERIALIZE(SortOrder);
|
||||
|
||||
SetImage();
|
||||
if (_paramColor)
|
||||
_paramColor->SetValue(_color);
|
||||
SetImageParam();
|
||||
SetColorParam();
|
||||
}
|
||||
|
||||
void SpriteRender::OnLayerChanged()
|
||||
|
||||
@@ -92,7 +92,8 @@ public:
|
||||
|
||||
private:
|
||||
void OnMaterialLoaded();
|
||||
void SetImage();
|
||||
void SetImageParam();
|
||||
void SetColorParam();
|
||||
|
||||
public:
|
||||
// [Actor]
|
||||
|
||||
@@ -2064,13 +2064,18 @@ namespace Flax.Build.Bindings
|
||||
GenerateCSharpAttributes(buildData, contents, indent, enumInfo, true);
|
||||
contents.Append(indent).Append(GenerateCSharpAccessLevel(enumInfo.Access));
|
||||
contents.Append("enum ").Append(enumInfo.Name);
|
||||
string managedType = string.Empty;
|
||||
if (enumInfo.UnderlyingType != null)
|
||||
contents.Append(" : ").Append(GenerateCSharpNativeToManaged(buildData, enumInfo.UnderlyingType, enumInfo));
|
||||
{
|
||||
managedType = GenerateCSharpNativeToManaged(buildData, enumInfo.UnderlyingType, enumInfo);
|
||||
contents.Append(" : ").Append(managedType);
|
||||
}
|
||||
contents.AppendLine();
|
||||
contents.Append(indent + "{");
|
||||
indent += " ";
|
||||
|
||||
// Entries
|
||||
bool usedMax = false;
|
||||
foreach (var entryInfo in enumInfo.Entries)
|
||||
{
|
||||
contents.AppendLine();
|
||||
@@ -2078,7 +2083,29 @@ namespace Flax.Build.Bindings
|
||||
GenerateCSharpAttributes(buildData, contents, indent, enumInfo, entryInfo.Attributes, entryInfo.Comment, true, false);
|
||||
contents.Append(indent).Append(entryInfo.Name);
|
||||
if (!string.IsNullOrEmpty(entryInfo.Value))
|
||||
contents.Append(" = ").Append(entryInfo.Value);
|
||||
{
|
||||
if (usedMax)
|
||||
usedMax = false;
|
||||
|
||||
string value;
|
||||
if (enumInfo.UnderlyingType != null)
|
||||
{
|
||||
value = GenerateCSharpDefaultValueNativeToManaged(buildData, entryInfo.Value, enumInfo, enumInfo.UnderlyingType, false, managedType);
|
||||
if (value.Contains($"{managedType}.MaxValue", StringComparison.Ordinal))
|
||||
usedMax = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = entryInfo.Value;
|
||||
}
|
||||
contents.Append(" = ").Append(value);
|
||||
}
|
||||
// Handle case of next value after Max value being zero if a value is not defined.
|
||||
else if (string.IsNullOrEmpty(entryInfo.Value) && usedMax)
|
||||
{
|
||||
contents.Append(" = ").Append('0');
|
||||
usedMax = false;
|
||||
}
|
||||
contents.Append(',');
|
||||
contents.AppendLine();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user