Merge branch 'master' into SnapToGrid
This commit is contained in:
BIN
Content/Editor/Particles/Smoke.flax
(Stored with Git LFS)
BIN
Content/Editor/Particles/Smoke.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Particles/Sparks.flax
(Stored with Git LFS)
BIN
Content/Editor/Particles/Sparks.flax
(Stored with Git LFS)
Binary file not shown.
@@ -33,4 +33,3 @@ public class %class% : Script
|
|||||||
// Here you can add code that needs to be called every frame
|
// Here you can add code that needs to be called every frame
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
"Version": {
|
"Version": {
|
||||||
"Major": 1,
|
"Major": 1,
|
||||||
"Minor": 7,
|
"Minor": 7,
|
||||||
"Build": 6402
|
"Revision": 0,
|
||||||
|
"Build": 6404
|
||||||
},
|
},
|
||||||
"Company": "Flax",
|
"Company": "Flax",
|
||||||
"Copyright": "Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.",
|
"Copyright": "Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.",
|
||||||
|
|||||||
@@ -259,10 +259,7 @@ namespace FlaxEditor.Options
|
|||||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||||
{
|
{
|
||||||
if (sourceType == typeof(string))
|
if (sourceType == typeof(string))
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
return base.CanConvertFrom(context, sourceType);
|
return base.CanConvertFrom(context, sourceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,9 +267,7 @@ namespace FlaxEditor.Options
|
|||||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
||||||
{
|
{
|
||||||
if (destinationType == typeof(string))
|
if (destinationType == typeof(string))
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
return base.CanConvertTo(context, destinationType);
|
return base.CanConvertTo(context, destinationType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +279,6 @@ namespace FlaxEditor.Options
|
|||||||
InputBinding.TryParse(str, out var result);
|
InputBinding.TryParse(str, out var result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ConvertFrom(context, culture, value);
|
return base.ConvertFrom(context, culture, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,7 +289,6 @@ namespace FlaxEditor.Options
|
|||||||
{
|
{
|
||||||
return ((InputBinding)value).ToString();
|
return ((InputBinding)value).ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.ConvertTo(context, culture, value, destinationType);
|
return base.ConvertTo(context, culture, value, destinationType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,45 +26,108 @@ namespace FlaxEditor.Options
|
|||||||
public float MouseWheelSensitivity { get; set; } = 1.0f;
|
public float MouseWheelSensitivity { get; set; } = 1.0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the default movement speed for the viewport camera (must match the dropdown menu values in the viewport).
|
/// Gets or sets the total amount of steps the camera needs to go from minimum to maximum speed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(1.0f), Limit(0.01f, 100.0f)]
|
[DefaultValue(64), Limit(1, 128)]
|
||||||
[EditorDisplay("Defaults"), EditorOrder(110), Tooltip("The default movement speed for the viewport camera (must match the dropdown menu values in the viewport).")]
|
[EditorDisplay("Camera"), EditorOrder(110), Tooltip("The total amount of steps the camera needs to go from minimum to maximum speed.")]
|
||||||
public float DefaultMovementSpeed { get; set; } = 1.0f;
|
public int TotalCameraSpeedSteps { get; set; } = 64;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the degree to which the camera will be eased when using camera flight in the editor window.
|
||||||
|
/// </summary>
|
||||||
|
[DefaultValue(3.0f), Limit(1.0f, 8.0f)]
|
||||||
|
[EditorDisplay("Camera"), EditorOrder(111), Tooltip("The degree to which the camera will be eased when using camera flight in the editor window (ignored if camera easing degree is enabled).")]
|
||||||
|
public float CameraEasingDegree { get; set; } = 3.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the default movement speed for the viewport camera (must be in range between minimum and maximum movement speed values).
|
||||||
|
/// </summary>
|
||||||
|
[DefaultValue(1.0f), Limit(0.05f, 32.0f)]
|
||||||
|
[EditorDisplay("Defaults"), EditorOrder(120), Tooltip("The default movement speed for the viewport camera (must be in range between minimum and maximum movement speed values).")]
|
||||||
|
public float MovementSpeed { get; set; } = 1.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the default minimum camera movement speed.
|
||||||
|
/// </summary>
|
||||||
|
[DefaultValue(0.05f), Limit(0.05f, 32.0f)]
|
||||||
|
[EditorDisplay("Defaults"), EditorOrder(121), Tooltip("The default minimum movement speed for the viewport camera.")]
|
||||||
|
public float MinMovementSpeed { get; set; } = 0.05f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the default maximum camera movement speed.
|
||||||
|
/// </summary>
|
||||||
|
[DefaultValue(32.0f), Limit(16.0f, 1000.0f)]
|
||||||
|
[EditorDisplay("Defaults"), EditorOrder(122), Tooltip("The default maximum movement speed for the viewport camera.")]
|
||||||
|
public float MaxMovementSpeed { get; set; } = 32f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the default camera easing mode.
|
||||||
|
/// </summary>
|
||||||
|
[DefaultValue(true)]
|
||||||
|
[EditorDisplay("Defaults"), EditorOrder(130), Tooltip("The default camera easing mode.")]
|
||||||
|
public bool UseCameraEasing { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the default near clipping plane distance for the viewport camera.
|
/// Gets or sets the default near clipping plane distance for the viewport camera.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(10.0f), Limit(0.001f, 1000.0f)]
|
[DefaultValue(10.0f), Limit(0.001f, 1000.0f)]
|
||||||
[EditorDisplay("Defaults"), EditorOrder(120), Tooltip("The default near clipping plane distance for the viewport camera.")]
|
[EditorDisplay("Defaults"), EditorOrder(140), Tooltip("The default near clipping plane distance for the viewport camera.")]
|
||||||
public float DefaultNearPlane { get; set; } = 10.0f;
|
public float NearPlane { get; set; } = 10.0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the default far clipping plane distance for the viewport camera.
|
/// Gets or sets the default far clipping plane distance for the viewport camera.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(40000.0f), Limit(10.0f)]
|
[DefaultValue(40000.0f), Limit(10.0f)]
|
||||||
[EditorDisplay("Defaults"), EditorOrder(130), Tooltip("The default far clipping plane distance for the viewport camera.")]
|
[EditorDisplay("Defaults"), EditorOrder(150), Tooltip("The default far clipping plane distance for the viewport camera.")]
|
||||||
public float DefaultFarPlane { get; set; } = 40000.0f;
|
public float FarPlane { get; set; } = 40000.0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the default field of view angle (in degrees) for the viewport camera.
|
/// Gets or sets the default field of view angle (in degrees) for the viewport camera.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(60.0f), Limit(35.0f, 160.0f, 0.1f)]
|
[DefaultValue(60.0f), Limit(35.0f, 160.0f, 0.1f)]
|
||||||
[EditorDisplay("Defaults", "Default Field Of View"), EditorOrder(140), Tooltip("The default field of view angle (in degrees) for the viewport camera.")]
|
[EditorDisplay("Defaults"), EditorOrder(160), Tooltip("The default field of view angle (in degrees) for the viewport camera.")]
|
||||||
public float DefaultFieldOfView { get; set; } = 60.0f;
|
public float FieldOfView { get; set; } = 60.0f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets if the panning direction is inverted for the viewport camera.
|
/// Gets or sets the default camera orthographic mode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(false)]
|
[DefaultValue(false)]
|
||||||
[EditorDisplay("Defaults"), EditorOrder(150), Tooltip("Invert the panning direction for the viewport camera.")]
|
[EditorDisplay("Defaults"), EditorOrder(170), Tooltip("The default camera orthographic mode.")]
|
||||||
public bool DefaultInvertPanning { get; set; } = false;
|
public bool UseOrthographicProjection { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Scales editor viewport grid.
|
/// Gets or sets the default camera orthographic scale (if camera uses orthographic mode).
|
||||||
|
/// </summary>
|
||||||
|
[DefaultValue(5.0f), Limit(0.001f, 100000.0f, 0.1f)]
|
||||||
|
[EditorDisplay("Defaults"), EditorOrder(180), Tooltip("The default camera orthographic scale (if camera uses orthographic mode).")]
|
||||||
|
public float OrthographicScale { get; set; } = 5.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the default panning direction for the viewport camera.
|
||||||
|
/// </summary>
|
||||||
|
[DefaultValue(false)]
|
||||||
|
[EditorDisplay("Defaults"), EditorOrder(190), Tooltip("The default panning direction for the viewport camera.")]
|
||||||
|
public bool InvertPanning { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the default relative panning mode.
|
||||||
|
/// </summary>
|
||||||
|
[DefaultValue(true)]
|
||||||
|
[EditorDisplay("Defaults"), EditorOrder(200), Tooltip("The default relative panning mode. Uses distance between camera and target to determine panning speed.")]
|
||||||
|
public bool UseRelativePanning { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the default panning speed (ignored if relative panning is speed enabled).
|
||||||
|
/// </summary>
|
||||||
|
[DefaultValue(0.8f), Limit(0.01f, 128.0f, 0.1f)]
|
||||||
|
[EditorDisplay("Defaults"), EditorOrder(210), Tooltip("The default camera panning speed (ignored if relative panning is enabled).")]
|
||||||
|
public float PanningSpeed { get; set; } = 0.8f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the default editor viewport grid scale.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(50.0f), Limit(25.0f, 500.0f, 5.0f)]
|
[DefaultValue(50.0f), Limit(25.0f, 500.0f, 5.0f)]
|
||||||
[EditorDisplay("Defaults"), EditorOrder(160), Tooltip("Scales editor viewport grid.")]
|
[EditorDisplay("Defaults"), EditorOrder(220), Tooltip("The default editor viewport grid scale.")]
|
||||||
public float ViewportGridScale { get; set; } = 50.0f;
|
public float ViewportGridScale { get; set; } = 50.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,7 +154,8 @@ bool ProjectInfo::LoadProject(const String& projectPath)
|
|||||||
Version = ::Version(
|
Version = ::Version(
|
||||||
JsonTools::GetInt(version, "Major", 0),
|
JsonTools::GetInt(version, "Major", 0),
|
||||||
JsonTools::GetInt(version, "Minor", 0),
|
JsonTools::GetInt(version, "Minor", 0),
|
||||||
JsonTools::GetInt(version, "Build", 0));
|
JsonTools::GetInt(version, "Build", -1),
|
||||||
|
JsonTools::GetInt(version, "Revision", -1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Version.Revision() == 0)
|
if (Version.Revision() == 0)
|
||||||
|
|||||||
@@ -23,17 +23,11 @@ namespace FlaxEditor
|
|||||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||||
{
|
{
|
||||||
if (value == null)
|
if (value == null)
|
||||||
{
|
|
||||||
writer.WriteNull();
|
writer.WriteNull();
|
||||||
}
|
|
||||||
else if (value is Version)
|
else if (value is Version)
|
||||||
{
|
|
||||||
writer.WriteValue(value.ToString());
|
writer.WriteValue(value.ToString());
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
throw new JsonSerializationException("Expected Version object value");
|
throw new JsonSerializationException("Expected Version object value");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -47,65 +41,60 @@ namespace FlaxEditor
|
|||||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||||
{
|
{
|
||||||
if (reader.TokenType == JsonToken.Null)
|
if (reader.TokenType == JsonToken.Null)
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
else
|
if (reader.TokenType == JsonToken.StartObject)
|
||||||
{
|
{
|
||||||
if (reader.TokenType == JsonToken.StartObject)
|
try
|
||||||
{
|
{
|
||||||
try
|
reader.Read();
|
||||||
|
var values = new Dictionary<string, int>();
|
||||||
|
while (reader.TokenType == JsonToken.PropertyName)
|
||||||
{
|
{
|
||||||
|
var key = reader.Value as string;
|
||||||
reader.Read();
|
reader.Read();
|
||||||
Dictionary<string, int> values = new Dictionary<string, int>();
|
var val = (long)reader.Value;
|
||||||
while (reader.TokenType == JsonToken.PropertyName)
|
reader.Read();
|
||||||
{
|
values.Add(key, (int)val);
|
||||||
var key = reader.Value as string;
|
}
|
||||||
reader.Read();
|
|
||||||
var val = (long)reader.Value;
|
|
||||||
reader.Read();
|
|
||||||
values.Add(key, (int)val);
|
|
||||||
}
|
|
||||||
|
|
||||||
int major = 0, minor = 0, build = 0;
|
values.TryGetValue("Major", out var major);
|
||||||
values.TryGetValue("Major", out major);
|
values.TryGetValue("Minor", out var minor);
|
||||||
values.TryGetValue("Minor", out minor);
|
if (!values.TryGetValue("Build", out var build))
|
||||||
values.TryGetValue("Build", out build);
|
build = -1;
|
||||||
|
if (!values.TryGetValue("Revision", out var revision))
|
||||||
|
revision = -1;
|
||||||
|
|
||||||
Version v = new Version(major, minor, build);
|
if (build <= 0)
|
||||||
return v;
|
return new Version(major, minor);
|
||||||
}
|
if (revision <= 0)
|
||||||
catch (Exception ex)
|
return new Version(major, minor, build);
|
||||||
{
|
return new Version(major, minor, build, revision);
|
||||||
throw new Exception(String.Format("Error parsing version string: {0}", reader.Value), ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (reader.TokenType == JsonToken.String)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
try
|
throw new Exception(String.Format("Error parsing version string: {0}", reader.Value), ex);
|
||||||
{
|
|
||||||
Version v = new Version((string)reader.Value!);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception(String.Format("Error parsing version string: {0}", reader.Value), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception(String.Format("Unexpected token or value when parsing version. Token: {0}, Value: {1}", reader.TokenType, reader.Value));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (reader.TokenType == JsonToken.String)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return new Version((string)reader.Value!);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception(String.Format("Error parsing version string: {0}", reader.Value), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception(String.Format("Unexpected token or value when parsing version. Token: {0}, Value: {1}", reader.TokenType, reader.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether this instance can convert the specified object type.
|
/// Determines whether this instance can convert the specified object type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="objectType">Type of the object.</param>
|
/// <param name="objectType">Type of the object.</param>
|
||||||
/// <returns>
|
/// <returns><c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.</returns>
|
||||||
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
|
|
||||||
/// </returns>
|
|
||||||
public override bool CanConvert(Type objectType)
|
public override bool CanConvert(Type objectType)
|
||||||
{
|
{
|
||||||
return objectType == typeof(Version);
|
return objectType == typeof(Version);
|
||||||
|
|||||||
@@ -259,7 +259,10 @@ namespace FlaxEditor.Viewport.Cameras
|
|||||||
// Pan
|
// Pan
|
||||||
if (input.IsPanning)
|
if (input.IsPanning)
|
||||||
{
|
{
|
||||||
var panningSpeed = 0.8f;
|
var panningSpeed = (Viewport.RelativePanning)
|
||||||
|
? Mathf.Abs((position - TargetPoint).Length) * 0.005f
|
||||||
|
: Viewport.PanningSpeed;
|
||||||
|
|
||||||
if (Viewport.InvertPanning)
|
if (Viewport.InvertPanning)
|
||||||
{
|
{
|
||||||
position += up * (mouseDelta.Y * panningSpeed);
|
position += up * (mouseDelta.Y * panningSpeed);
|
||||||
|
|||||||
@@ -128,12 +128,26 @@ namespace FlaxEditor.Viewport
|
|||||||
public const int FpsCameraFilteringFrames = 3;
|
public const int FpsCameraFilteringFrames = 3;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The speed widget button.
|
/// The camera settings widget.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected ViewportWidgetButton _speedWidget;
|
protected ViewportWidgetsContainer _cameraWidget;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The camera settings widget button.
|
||||||
|
/// </summary>
|
||||||
|
protected ViewportWidgetButton _cameraButton;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The orthographic mode widget button.
|
||||||
|
/// </summary>
|
||||||
|
protected ViewportWidgetButton _orthographicModeButton;
|
||||||
|
|
||||||
|
private readonly Editor _editor;
|
||||||
|
|
||||||
private float _mouseSensitivity;
|
private float _mouseSensitivity;
|
||||||
private float _movementSpeed;
|
private float _movementSpeed;
|
||||||
|
private float _minMovementSpeed;
|
||||||
|
private float _maxMovementSpeed;
|
||||||
private float _mouseAccelerationScale;
|
private float _mouseAccelerationScale;
|
||||||
private bool _useMouseFiltering;
|
private bool _useMouseFiltering;
|
||||||
private bool _useMouseAcceleration;
|
private bool _useMouseAcceleration;
|
||||||
@@ -174,11 +188,17 @@ namespace FlaxEditor.Viewport
|
|||||||
private float _fieldOfView;
|
private float _fieldOfView;
|
||||||
private float _nearPlane;
|
private float _nearPlane;
|
||||||
private float _farPlane;
|
private float _farPlane;
|
||||||
private float _orthoSize = 1.0f;
|
private float _orthoSize;
|
||||||
private bool _isOrtho = false;
|
private bool _isOrtho;
|
||||||
private float _wheelMovementChangeDeltaSum = 0;
|
private bool _useCameraEasing;
|
||||||
|
private float _cameraEasingDegree;
|
||||||
|
private float _panningSpeed;
|
||||||
|
private bool _relativePanning;
|
||||||
private bool _invertPanning;
|
private bool _invertPanning;
|
||||||
|
|
||||||
|
private int _speedStep;
|
||||||
|
private int _maxSpeedSteps;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Speed of the mouse.
|
/// Speed of the mouse.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -189,6 +209,25 @@ namespace FlaxEditor.Viewport
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float MouseWheelZoomSpeedFactor = 1;
|
public float MouseWheelZoomSpeedFactor = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Format of the text for the camera move speed.
|
||||||
|
/// </summary>
|
||||||
|
private string MovementSpeedTextFormat
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Mathf.Abs(_movementSpeed - _maxMovementSpeed) < Mathf.Epsilon || Mathf.Abs(_movementSpeed - _minMovementSpeed) < Mathf.Epsilon)
|
||||||
|
return "{0:0.##}";
|
||||||
|
|
||||||
|
if (_movementSpeed < 10.0f)
|
||||||
|
return "{0:0.00}";
|
||||||
|
else if (_movementSpeed < 100.0f)
|
||||||
|
return "{0:0.0}";
|
||||||
|
else
|
||||||
|
return "{0:#}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the camera movement speed.
|
/// Gets or sets the camera movement speed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -197,19 +236,40 @@ namespace FlaxEditor.Viewport
|
|||||||
get => _movementSpeed;
|
get => _movementSpeed;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
for (int i = 0; i < EditorViewportCameraSpeedValues.Length; i++)
|
_movementSpeed = value;
|
||||||
{
|
|
||||||
if (Math.Abs(value - EditorViewportCameraSpeedValues[i]) < 0.001f)
|
if (_cameraButton != null)
|
||||||
{
|
_cameraButton.Text = string.Format(MovementSpeedTextFormat, _movementSpeed);
|
||||||
_movementSpeed = EditorViewportCameraSpeedValues[i];
|
|
||||||
if (_speedWidget != null)
|
|
||||||
_speedWidget.Text = _movementSpeed.ToString();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the minimum camera movement speed.
|
||||||
|
/// </summary>
|
||||||
|
public float MinMovementSpeed
|
||||||
|
{
|
||||||
|
get => _minMovementSpeed;
|
||||||
|
set => _minMovementSpeed = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the maximum camera movement speed.
|
||||||
|
/// </summary>
|
||||||
|
public float MaxMovementSpeed
|
||||||
|
{
|
||||||
|
get => _maxMovementSpeed;
|
||||||
|
set => _maxMovementSpeed = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the camera easing mode.
|
||||||
|
/// </summary>
|
||||||
|
public bool UseCameraEasing
|
||||||
|
{
|
||||||
|
get => _useCameraEasing;
|
||||||
|
set => _useCameraEasing = value;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the mouse movement position delta (user press and move).
|
/// Gets the mouse movement position delta (user press and move).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -396,6 +456,15 @@ namespace FlaxEditor.Viewport
|
|||||||
set => _isOrtho = value;
|
set => _isOrtho = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets if the panning speed should be relative to the camera target.
|
||||||
|
/// </summary>
|
||||||
|
public bool RelativePanning
|
||||||
|
{
|
||||||
|
get => _relativePanning;
|
||||||
|
set => _relativePanning = value;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets if the panning direction is inverted.
|
/// Gets or sets if the panning direction is inverted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -405,6 +474,15 @@ namespace FlaxEditor.Viewport
|
|||||||
set => _invertPanning = value;
|
set => _invertPanning = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the camera panning speed.
|
||||||
|
/// </summary>
|
||||||
|
public float PanningSpeed
|
||||||
|
{
|
||||||
|
get => _panningSpeed;
|
||||||
|
set => _panningSpeed = value;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The input actions collection to processed during user input.
|
/// The input actions collection to processed during user input.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -419,6 +497,8 @@ namespace FlaxEditor.Viewport
|
|||||||
public EditorViewport(SceneRenderTask task, ViewportCamera camera, bool useWidgets)
|
public EditorViewport(SceneRenderTask task, ViewportCamera camera, bool useWidgets)
|
||||||
: base(task)
|
: base(task)
|
||||||
{
|
{
|
||||||
|
_editor = Editor.Instance;
|
||||||
|
|
||||||
_mouseAccelerationScale = 0.1f;
|
_mouseAccelerationScale = 0.1f;
|
||||||
_useMouseFiltering = false;
|
_useMouseFiltering = false;
|
||||||
_useMouseAcceleration = false;
|
_useMouseAcceleration = false;
|
||||||
@@ -431,43 +511,299 @@ namespace FlaxEditor.Viewport
|
|||||||
|
|
||||||
// Setup options
|
// Setup options
|
||||||
{
|
{
|
||||||
var options = Editor.Instance.Options.Options;
|
|
||||||
_movementSpeed = options.Viewport.DefaultMovementSpeed;
|
|
||||||
_nearPlane = options.Viewport.DefaultNearPlane;
|
|
||||||
_farPlane = options.Viewport.DefaultFarPlane;
|
|
||||||
_fieldOfView = options.Viewport.DefaultFieldOfView;
|
|
||||||
_invertPanning = options.Viewport.DefaultInvertPanning;
|
|
||||||
|
|
||||||
Editor.Instance.Options.OptionsChanged += OnEditorOptionsChanged;
|
Editor.Instance.Options.OptionsChanged += OnEditorOptionsChanged;
|
||||||
OnEditorOptionsChanged(options);
|
SetupViewportOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize camera values from cache
|
||||||
|
if (_editor.ProjectCache.TryGetCustomData("CameraMovementSpeedValue", out var cachedState))
|
||||||
|
MovementSpeed = float.Parse(cachedState);
|
||||||
|
if (_editor.ProjectCache.TryGetCustomData("CameraMinMovementSpeedValue", out cachedState))
|
||||||
|
_minMovementSpeed = float.Parse(cachedState);
|
||||||
|
if (_editor.ProjectCache.TryGetCustomData("CameraMaxMovementSpeedValue", out cachedState))
|
||||||
|
_maxMovementSpeed = float.Parse(cachedState);
|
||||||
|
if (_editor.ProjectCache.TryGetCustomData("UseCameraEasingState", out cachedState))
|
||||||
|
_useCameraEasing = bool.Parse(cachedState);
|
||||||
|
if (_editor.ProjectCache.TryGetCustomData("CameraPanningSpeedValue", out cachedState))
|
||||||
|
_panningSpeed = float.Parse(cachedState);
|
||||||
|
if (_editor.ProjectCache.TryGetCustomData("CameraInvertPanningState", out cachedState))
|
||||||
|
_invertPanning = bool.Parse(cachedState);
|
||||||
|
if (_editor.ProjectCache.TryGetCustomData("CameraRelativePanningState", out cachedState))
|
||||||
|
_relativePanning = bool.Parse(cachedState);
|
||||||
|
if (_editor.ProjectCache.TryGetCustomData("CameraOrthographicState", out cachedState))
|
||||||
|
_isOrtho = bool.Parse(cachedState);
|
||||||
|
if (_editor.ProjectCache.TryGetCustomData("CameraOrthographicSizeValue", out cachedState))
|
||||||
|
_orthoSize = float.Parse(cachedState);
|
||||||
|
if (_editor.ProjectCache.TryGetCustomData("CameraFieldOfViewValue", out cachedState))
|
||||||
|
_fieldOfView = float.Parse(cachedState);
|
||||||
|
if (_editor.ProjectCache.TryGetCustomData("CameraNearPlaneValue", out cachedState))
|
||||||
|
_nearPlane = float.Parse(cachedState);
|
||||||
|
if (_editor.ProjectCache.TryGetCustomData("CameraFarPlaneValue", out cachedState))
|
||||||
|
_farPlane = float.Parse(cachedState);
|
||||||
|
|
||||||
|
OnCameraMovementProgressChanged();
|
||||||
|
|
||||||
if (useWidgets)
|
if (useWidgets)
|
||||||
{
|
{
|
||||||
var largestText = "Invert Panning";
|
#region Camera settings widget
|
||||||
|
|
||||||
|
var largestText = "Relative Panning";
|
||||||
var textSize = Style.Current.FontMedium.MeasureText(largestText);
|
var textSize = Style.Current.FontMedium.MeasureText(largestText);
|
||||||
var xLocationForExtras = textSize.X + 5;
|
var xLocationForExtras = textSize.X + 5;
|
||||||
// Camera speed widget
|
var cameraSpeedTextWidth = Style.Current.FontMedium.MeasureText("0.00").X;
|
||||||
var camSpeed = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight);
|
|
||||||
var camSpeedCM = new ContextMenu();
|
// Camera Settings Widget
|
||||||
var camSpeedButton = new ViewportWidgetButton(_movementSpeed.ToString(), Editor.Instance.Icons.CamSpeed32, camSpeedCM)
|
_cameraWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight);
|
||||||
|
|
||||||
|
// Camera Settings Menu
|
||||||
|
var cameraCM = new ContextMenu();
|
||||||
|
_cameraButton = new ViewportWidgetButton(string.Format(MovementSpeedTextFormat, _movementSpeed), Editor.Instance.Icons.Camera64, cameraCM, false, cameraSpeedTextWidth)
|
||||||
{
|
{
|
||||||
Tag = this,
|
Tag = this,
|
||||||
TooltipText = "Camera speed scale"
|
TooltipText = "Camera Settings",
|
||||||
|
Parent = _cameraWidget
|
||||||
};
|
};
|
||||||
_speedWidget = camSpeedButton;
|
_cameraWidget.Parent = this;
|
||||||
for (int i = 0; i < EditorViewportCameraSpeedValues.Length; i++)
|
|
||||||
{
|
// Orthographic/Perspective Mode Widget
|
||||||
var v = EditorViewportCameraSpeedValues[i];
|
_orthographicModeButton = new ViewportWidgetButton(string.Empty, Editor.Instance.Icons.CamSpeed32, null, true)
|
||||||
var button = camSpeedCM.AddButton(v.ToString());
|
{
|
||||||
button.Tag = v;
|
Checked = !_isOrtho,
|
||||||
}
|
TooltipText = "Toggle Orthographic/Perspective Mode",
|
||||||
camSpeedCM.ButtonClicked += button => MovementSpeed = (float)button.Tag;
|
Parent = _cameraWidget
|
||||||
camSpeedCM.VisibleChanged += WidgetCamSpeedShowHide;
|
};
|
||||||
camSpeedButton.Parent = camSpeed;
|
_orthographicModeButton.Toggled += OnOrthographicModeToggled;
|
||||||
camSpeed.Parent = this;
|
|
||||||
|
// Camera Speed
|
||||||
|
var camSpeedButton = cameraCM.AddButton("Camera Speed");
|
||||||
|
camSpeedButton.CloseMenuOnClick = false;
|
||||||
|
var camSpeedValue = new FloatValueBox(_movementSpeed, xLocationForExtras, 2, 70.0f, _minMovementSpeed, _maxMovementSpeed, 0.5f)
|
||||||
|
{
|
||||||
|
Parent = camSpeedButton
|
||||||
|
};
|
||||||
|
|
||||||
|
camSpeedValue.ValueChanged += () => OnMovementSpeedChanged(camSpeedValue);
|
||||||
|
cameraCM.VisibleChanged += control => camSpeedValue.Value = _movementSpeed;
|
||||||
|
|
||||||
|
// Minimum & Maximum Camera Speed
|
||||||
|
var minCamSpeedButton = cameraCM.AddButton("Min Cam Speed");
|
||||||
|
minCamSpeedButton.CloseMenuOnClick = false;
|
||||||
|
var minCamSpeedValue = new FloatValueBox(_minMovementSpeed, xLocationForExtras, 2, 70.0f, 0.05f, _maxMovementSpeed, 0.5f)
|
||||||
|
{
|
||||||
|
Parent = minCamSpeedButton
|
||||||
|
};
|
||||||
|
var maxCamSpeedButton = cameraCM.AddButton("Max Cam Speed");
|
||||||
|
maxCamSpeedButton.CloseMenuOnClick = false;
|
||||||
|
var maxCamSpeedValue = new FloatValueBox(_maxMovementSpeed, xLocationForExtras, 2, 70.0f, _minMovementSpeed, 1000.0f, 0.5f)
|
||||||
|
{
|
||||||
|
Parent = maxCamSpeedButton
|
||||||
|
};
|
||||||
|
|
||||||
|
minCamSpeedValue.ValueChanged += () =>
|
||||||
|
{
|
||||||
|
OnMinMovementSpeedChanged(minCamSpeedValue);
|
||||||
|
|
||||||
|
maxCamSpeedValue.MinValue = minCamSpeedValue.Value;
|
||||||
|
|
||||||
|
if (Math.Abs(camSpeedValue.MinValue - minCamSpeedValue.Value) > Mathf.Epsilon)
|
||||||
|
camSpeedValue.MinValue = minCamSpeedValue.Value;
|
||||||
|
};
|
||||||
|
cameraCM.VisibleChanged += control => minCamSpeedValue.Value = _minMovementSpeed;
|
||||||
|
maxCamSpeedValue.ValueChanged += () =>
|
||||||
|
{
|
||||||
|
OnMaxMovementSpeedChanged(maxCamSpeedValue);
|
||||||
|
|
||||||
|
minCamSpeedValue.MaxValue = maxCamSpeedValue.Value;
|
||||||
|
|
||||||
|
if (Math.Abs(camSpeedValue.MaxValue - maxCamSpeedValue.Value) > Mathf.Epsilon)
|
||||||
|
camSpeedValue.MaxValue = maxCamSpeedValue.Value;
|
||||||
|
};
|
||||||
|
cameraCM.VisibleChanged += control => maxCamSpeedValue.Value = _maxMovementSpeed;
|
||||||
|
|
||||||
|
// Camera Easing
|
||||||
|
{
|
||||||
|
var useCameraEasing = cameraCM.AddButton("Camera Easing");
|
||||||
|
useCameraEasing.CloseMenuOnClick = false;
|
||||||
|
var useCameraEasingValue = new CheckBox(xLocationForExtras, 2, _useCameraEasing)
|
||||||
|
{
|
||||||
|
Parent = useCameraEasing
|
||||||
|
};
|
||||||
|
|
||||||
|
useCameraEasingValue.StateChanged += OnCameraEasingToggled;
|
||||||
|
cameraCM.VisibleChanged += control => useCameraEasingValue.Checked = _useCameraEasing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Panning Speed
|
||||||
|
{
|
||||||
|
var panningSpeed = cameraCM.AddButton("Panning Speed");
|
||||||
|
panningSpeed.CloseMenuOnClick = false;
|
||||||
|
var panningSpeedValue = new FloatValueBox(_panningSpeed, xLocationForExtras, 2, 70.0f, 0.01f, 128.0f, 0.1f)
|
||||||
|
{
|
||||||
|
Parent = panningSpeed
|
||||||
|
};
|
||||||
|
|
||||||
|
panningSpeedValue.ValueChanged += () => OnPanningSpeedChanged(panningSpeedValue);
|
||||||
|
cameraCM.VisibleChanged += control =>
|
||||||
|
{
|
||||||
|
panningSpeed.Visible = !_relativePanning;
|
||||||
|
panningSpeedValue.Value = _panningSpeed;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relative Panning
|
||||||
|
{
|
||||||
|
var relativePanning = cameraCM.AddButton("Relative Panning");
|
||||||
|
relativePanning.CloseMenuOnClick = false;
|
||||||
|
var relativePanningValue = new CheckBox(xLocationForExtras, 2, _relativePanning)
|
||||||
|
{
|
||||||
|
Parent = relativePanning
|
||||||
|
};
|
||||||
|
|
||||||
|
relativePanningValue.StateChanged += checkBox =>
|
||||||
|
{
|
||||||
|
if (checkBox.Checked != _relativePanning)
|
||||||
|
{
|
||||||
|
OnRelativePanningToggled(checkBox);
|
||||||
|
cameraCM.Hide();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
cameraCM.VisibleChanged += control => relativePanningValue.Checked = _relativePanning;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invert Panning
|
||||||
|
{
|
||||||
|
var invertPanning = cameraCM.AddButton("Invert Panning");
|
||||||
|
invertPanning.CloseMenuOnClick = false;
|
||||||
|
var invertPanningValue = new CheckBox(xLocationForExtras, 2, _invertPanning)
|
||||||
|
{
|
||||||
|
Parent = invertPanning
|
||||||
|
};
|
||||||
|
|
||||||
|
invertPanningValue.StateChanged += OnInvertPanningToggled;
|
||||||
|
cameraCM.VisibleChanged += control => invertPanningValue.Checked = _invertPanning;
|
||||||
|
}
|
||||||
|
|
||||||
|
cameraCM.AddSeparator();
|
||||||
|
|
||||||
|
// Camera Viewpoints
|
||||||
|
{
|
||||||
|
var cameraView = cameraCM.AddChildMenu("Viewpoints").ContextMenu;
|
||||||
|
for (int i = 0; i < EditorViewportCameraViewpointValues.Length; i++)
|
||||||
|
{
|
||||||
|
var co = EditorViewportCameraViewpointValues[i];
|
||||||
|
var button = cameraView.AddButton(co.Name);
|
||||||
|
button.Tag = co.Orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
cameraView.ButtonClicked += OnViewpointChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Orthographic Mode
|
||||||
|
{
|
||||||
|
var ortho = cameraCM.AddButton("Orthographic");
|
||||||
|
ortho.CloseMenuOnClick = false;
|
||||||
|
var orthoValue = new CheckBox(xLocationForExtras, 2, _isOrtho)
|
||||||
|
{
|
||||||
|
Parent = ortho
|
||||||
|
};
|
||||||
|
|
||||||
|
orthoValue.StateChanged += checkBox =>
|
||||||
|
{
|
||||||
|
if (checkBox.Checked != _isOrtho)
|
||||||
|
{
|
||||||
|
OnOrthographicModeToggled(checkBox);
|
||||||
|
cameraCM.Hide();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
cameraCM.VisibleChanged += control => orthoValue.Checked = _isOrtho;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Field of View
|
||||||
|
{
|
||||||
|
var fov = cameraCM.AddButton("Field Of View");
|
||||||
|
fov.CloseMenuOnClick = false;
|
||||||
|
var fovValue = new FloatValueBox(_fieldOfView, xLocationForExtras, 2, 70.0f, 35.0f, 160.0f, 0.1f)
|
||||||
|
{
|
||||||
|
Parent = fov
|
||||||
|
};
|
||||||
|
|
||||||
|
fovValue.ValueChanged += () => OnFieldOfViewChanged(fovValue);
|
||||||
|
cameraCM.VisibleChanged += control =>
|
||||||
|
{
|
||||||
|
fov.Visible = !_isOrtho;
|
||||||
|
fovValue.Value = _fieldOfView;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Orthographic Scale
|
||||||
|
{
|
||||||
|
var orthoSize = cameraCM.AddButton("Ortho Scale");
|
||||||
|
orthoSize.CloseMenuOnClick = false;
|
||||||
|
var orthoSizeValue = new FloatValueBox(_orthoSize, xLocationForExtras, 2, 70.0f, 0.001f, 100000.0f, 0.01f)
|
||||||
|
{
|
||||||
|
Parent = orthoSize
|
||||||
|
};
|
||||||
|
|
||||||
|
orthoSizeValue.ValueChanged += () => OnOrthographicSizeChanged(orthoSizeValue);
|
||||||
|
cameraCM.VisibleChanged += control =>
|
||||||
|
{
|
||||||
|
orthoSize.Visible = _isOrtho;
|
||||||
|
orthoSizeValue.Value = _orthoSize;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Near Plane
|
||||||
|
{
|
||||||
|
var nearPlane = cameraCM.AddButton("Near Plane");
|
||||||
|
nearPlane.CloseMenuOnClick = false;
|
||||||
|
var nearPlaneValue = new FloatValueBox(_nearPlane, xLocationForExtras, 2, 70.0f, 0.001f, 1000.0f)
|
||||||
|
{
|
||||||
|
Parent = nearPlane
|
||||||
|
};
|
||||||
|
|
||||||
|
nearPlaneValue.ValueChanged += () => OnNearPlaneChanged(nearPlaneValue);
|
||||||
|
cameraCM.VisibleChanged += control => nearPlaneValue.Value = _nearPlane;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Far Plane
|
||||||
|
{
|
||||||
|
var farPlane = cameraCM.AddButton("Far Plane");
|
||||||
|
farPlane.CloseMenuOnClick = false;
|
||||||
|
var farPlaneValue = new FloatValueBox(_farPlane, xLocationForExtras, 2, 70.0f, 10.0f)
|
||||||
|
{
|
||||||
|
Parent = farPlane
|
||||||
|
};
|
||||||
|
|
||||||
|
farPlaneValue.ValueChanged += () => OnFarPlaneChanged(farPlaneValue);
|
||||||
|
cameraCM.VisibleChanged += control => farPlaneValue.Value = _farPlane;
|
||||||
|
}
|
||||||
|
|
||||||
|
cameraCM.AddSeparator();
|
||||||
|
|
||||||
|
// Reset Button
|
||||||
|
{
|
||||||
|
var reset = cameraCM.AddButton("Reset to default");
|
||||||
|
reset.ButtonClicked += button =>
|
||||||
|
{
|
||||||
|
SetupViewportOptions();
|
||||||
|
|
||||||
|
// if the context menu is opened without triggering the value changes beforehand,
|
||||||
|
// the movement speed will not be correctly reset to its default value in certain cases
|
||||||
|
// therefore, a UI update needs to be triggered here
|
||||||
|
minCamSpeedValue.Value = _minMovementSpeed;
|
||||||
|
camSpeedValue.Value = _movementSpeed;
|
||||||
|
maxCamSpeedValue.Value = _maxMovementSpeed;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Camera settings widget
|
||||||
|
|
||||||
|
#region View mode widget
|
||||||
|
|
||||||
|
largestText = "Brightness";
|
||||||
|
textSize = Style.Current.FontMedium.MeasureText(largestText);
|
||||||
|
xLocationForExtras = textSize.X + 5;
|
||||||
|
|
||||||
// View mode widget
|
|
||||||
var viewMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperLeft);
|
var viewMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperLeft);
|
||||||
ViewWidgetButtonMenu = new ContextMenu();
|
ViewWidgetButtonMenu = new ContextMenu();
|
||||||
var viewModeButton = new ViewportWidgetButton("View", SpriteHandle.Invalid, ViewWidgetButtonMenu)
|
var viewModeButton = new ViewportWidgetButton("View", SpriteHandle.Invalid, ViewWidgetButtonMenu)
|
||||||
@@ -484,8 +820,8 @@ namespace FlaxEditor.Viewport
|
|||||||
// Show FPS
|
// Show FPS
|
||||||
{
|
{
|
||||||
InitFpsCounter();
|
InitFpsCounter();
|
||||||
_showFpsButon = ViewWidgetShowMenu.AddButton("FPS Counter", () => ShowFpsCounter = !ShowFpsCounter);
|
_showFpsButton = ViewWidgetShowMenu.AddButton("FPS Counter", () => ShowFpsCounter = !ShowFpsCounter);
|
||||||
_showFpsButon.CloseMenuOnClick = false;
|
_showFpsButton.CloseMenuOnClick = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -610,104 +946,6 @@ namespace FlaxEditor.Viewport
|
|||||||
|
|
||||||
ViewWidgetButtonMenu.AddSeparator();
|
ViewWidgetButtonMenu.AddSeparator();
|
||||||
|
|
||||||
// Orthographic
|
|
||||||
{
|
|
||||||
var ortho = ViewWidgetButtonMenu.AddButton("Orthographic");
|
|
||||||
ortho.CloseMenuOnClick = false;
|
|
||||||
var orthoValue = new CheckBox(xLocationForExtras, 2, _isOrtho)
|
|
||||||
{
|
|
||||||
Parent = ortho
|
|
||||||
};
|
|
||||||
orthoValue.StateChanged += checkBox =>
|
|
||||||
{
|
|
||||||
if (checkBox.Checked != _isOrtho)
|
|
||||||
{
|
|
||||||
_isOrtho = checkBox.Checked;
|
|
||||||
ViewWidgetButtonMenu.Hide();
|
|
||||||
if (_isOrtho)
|
|
||||||
{
|
|
||||||
var orient = ViewOrientation;
|
|
||||||
OrientViewport(ref orient);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ViewWidgetButtonMenu.VisibleChanged += control => orthoValue.Checked = _isOrtho;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Camera Viewpoints
|
|
||||||
{
|
|
||||||
var cameraView = ViewWidgetButtonMenu.AddChildMenu("Viewpoints").ContextMenu;
|
|
||||||
for (int i = 0; i < EditorViewportCameraViewpointValues.Length; i++)
|
|
||||||
{
|
|
||||||
var co = EditorViewportCameraViewpointValues[i];
|
|
||||||
var button = cameraView.AddButton(co.Name);
|
|
||||||
button.Tag = co.Orientation;
|
|
||||||
}
|
|
||||||
cameraView.ButtonClicked += button =>
|
|
||||||
{
|
|
||||||
var orient = Quaternion.Euler((Float3)button.Tag);
|
|
||||||
OrientViewport(ref orient);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Field of View
|
|
||||||
{
|
|
||||||
var fov = ViewWidgetButtonMenu.AddButton("Field Of View");
|
|
||||||
fov.CloseMenuOnClick = false;
|
|
||||||
var fovValue = new FloatValueBox(1, xLocationForExtras, 2, 70.0f, 35.0f, 160.0f, 0.1f)
|
|
||||||
{
|
|
||||||
Parent = fov
|
|
||||||
};
|
|
||||||
|
|
||||||
fovValue.ValueChanged += () => _fieldOfView = fovValue.Value;
|
|
||||||
ViewWidgetButtonMenu.VisibleChanged += control =>
|
|
||||||
{
|
|
||||||
fov.Visible = !_isOrtho;
|
|
||||||
fovValue.Value = _fieldOfView;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ortho Scale
|
|
||||||
{
|
|
||||||
var orthoSize = ViewWidgetButtonMenu.AddButton("Ortho Scale");
|
|
||||||
orthoSize.CloseMenuOnClick = false;
|
|
||||||
var orthoSizeValue = new FloatValueBox(_orthoSize, xLocationForExtras, 2, 70.0f, 0.001f, 100000.0f, 0.01f)
|
|
||||||
{
|
|
||||||
Parent = orthoSize
|
|
||||||
};
|
|
||||||
|
|
||||||
orthoSizeValue.ValueChanged += () => _orthoSize = orthoSizeValue.Value;
|
|
||||||
ViewWidgetButtonMenu.VisibleChanged += control =>
|
|
||||||
{
|
|
||||||
orthoSize.Visible = _isOrtho;
|
|
||||||
orthoSizeValue.Value = _orthoSize;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Near Plane
|
|
||||||
{
|
|
||||||
var nearPlane = ViewWidgetButtonMenu.AddButton("Near Plane");
|
|
||||||
nearPlane.CloseMenuOnClick = false;
|
|
||||||
var nearPlaneValue = new FloatValueBox(2.0f, xLocationForExtras, 2, 70.0f, 0.001f, 1000.0f)
|
|
||||||
{
|
|
||||||
Parent = nearPlane
|
|
||||||
};
|
|
||||||
nearPlaneValue.ValueChanged += () => _nearPlane = nearPlaneValue.Value;
|
|
||||||
ViewWidgetButtonMenu.VisibleChanged += control => nearPlaneValue.Value = _nearPlane;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Far Plane
|
|
||||||
{
|
|
||||||
var farPlane = ViewWidgetButtonMenu.AddButton("Far Plane");
|
|
||||||
farPlane.CloseMenuOnClick = false;
|
|
||||||
var farPlaneValue = new FloatValueBox(1000, xLocationForExtras, 2, 70.0f, 10.0f)
|
|
||||||
{
|
|
||||||
Parent = farPlane
|
|
||||||
};
|
|
||||||
farPlaneValue.ValueChanged += () => _farPlane = farPlaneValue.Value;
|
|
||||||
ViewWidgetButtonMenu.VisibleChanged += control => farPlaneValue.Value = _farPlane;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Brightness
|
// Brightness
|
||||||
{
|
{
|
||||||
var brightness = ViewWidgetButtonMenu.AddButton("Brightness");
|
var brightness = ViewWidgetButtonMenu.AddButton("Brightness");
|
||||||
@@ -732,24 +970,7 @@ namespace FlaxEditor.Viewport
|
|||||||
ViewWidgetButtonMenu.VisibleChanged += control => resolutionValue.Value = ResolutionScale;
|
ViewWidgetButtonMenu.VisibleChanged += control => resolutionValue.Value = ResolutionScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invert Panning
|
#endregion View mode widget
|
||||||
{
|
|
||||||
var invert = ViewWidgetButtonMenu.AddButton("Invert Panning");
|
|
||||||
invert.CloseMenuOnClick = false;
|
|
||||||
var invertValue = new CheckBox(xLocationForExtras, 2, _invertPanning)
|
|
||||||
{
|
|
||||||
Parent = invert
|
|
||||||
};
|
|
||||||
|
|
||||||
invertValue.StateChanged += checkBox =>
|
|
||||||
{
|
|
||||||
if (checkBox.Checked != _invertPanning)
|
|
||||||
{
|
|
||||||
_invertPanning = checkBox.Checked;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ViewWidgetButtonMenu.VisibleChanged += control => invertValue.Checked = _invertPanning;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InputActions.Add(options => options.ViewpointTop, () => OrientViewport(Quaternion.Euler(EditorViewportCameraViewpointValues.First(vp => vp.Name == "Top").Orientation)));
|
InputActions.Add(options => options.ViewpointTop, () => OrientViewport(Quaternion.Euler(EditorViewportCameraViewpointValues.First(vp => vp.Name == "Top").Orientation)));
|
||||||
@@ -766,6 +987,135 @@ namespace FlaxEditor.Viewport
|
|||||||
task.Begin += OnRenderBegin;
|
task.Begin += OnRenderBegin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the viewport options to the default values.
|
||||||
|
/// </summary>
|
||||||
|
private void SetupViewportOptions()
|
||||||
|
{
|
||||||
|
var options = Editor.Instance.Options.Options;
|
||||||
|
_minMovementSpeed = options.Viewport.MinMovementSpeed;
|
||||||
|
MovementSpeed = options.Viewport.MovementSpeed;
|
||||||
|
_maxMovementSpeed = options.Viewport.MaxMovementSpeed;
|
||||||
|
_useCameraEasing = options.Viewport.UseCameraEasing;
|
||||||
|
_panningSpeed = options.Viewport.PanningSpeed;
|
||||||
|
_invertPanning = options.Viewport.InvertPanning;
|
||||||
|
_relativePanning = options.Viewport.UseRelativePanning;
|
||||||
|
|
||||||
|
_isOrtho = options.Viewport.UseOrthographicProjection;
|
||||||
|
_orthoSize = options.Viewport.OrthographicScale;
|
||||||
|
_fieldOfView = options.Viewport.FieldOfView;
|
||||||
|
_nearPlane = options.Viewport.NearPlane;
|
||||||
|
_farPlane = options.Viewport.FarPlane;
|
||||||
|
|
||||||
|
OnEditorOptionsChanged(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMovementSpeedChanged(FloatValueBox control)
|
||||||
|
{
|
||||||
|
var value = Mathf.Clamp(control.Value, _minMovementSpeed, _maxMovementSpeed);
|
||||||
|
MovementSpeed = value;
|
||||||
|
|
||||||
|
OnCameraMovementProgressChanged();
|
||||||
|
_editor.ProjectCache.SetCustomData("CameraMovementSpeedValue", _movementSpeed.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMinMovementSpeedChanged(FloatValueBox control)
|
||||||
|
{
|
||||||
|
var value = Mathf.Clamp(control.Value, 0.05f, _maxMovementSpeed);
|
||||||
|
_minMovementSpeed = value;
|
||||||
|
|
||||||
|
if (_movementSpeed < value)
|
||||||
|
MovementSpeed = value;
|
||||||
|
|
||||||
|
OnCameraMovementProgressChanged();
|
||||||
|
_editor.ProjectCache.SetCustomData("CameraMinMovementSpeedValue", _minMovementSpeed.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMaxMovementSpeedChanged(FloatValueBox control)
|
||||||
|
{
|
||||||
|
var value = Mathf.Clamp(control.Value, _minMovementSpeed, 1000.0f);
|
||||||
|
_maxMovementSpeed = value;
|
||||||
|
|
||||||
|
if (_movementSpeed > value)
|
||||||
|
MovementSpeed = value;
|
||||||
|
|
||||||
|
OnCameraMovementProgressChanged();
|
||||||
|
_editor.ProjectCache.SetCustomData("CameraMaxMovementSpeedValue", _maxMovementSpeed.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCameraEasingToggled(Control control)
|
||||||
|
{
|
||||||
|
_useCameraEasing = !_useCameraEasing;
|
||||||
|
|
||||||
|
OnCameraMovementProgressChanged();
|
||||||
|
_editor.ProjectCache.SetCustomData("UseCameraEasingState", _useCameraEasing.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPanningSpeedChanged(FloatValueBox control)
|
||||||
|
{
|
||||||
|
_panningSpeed = control.Value;
|
||||||
|
_editor.ProjectCache.SetCustomData("CameraPanningSpeedValue", _panningSpeed.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRelativePanningToggled(Control control)
|
||||||
|
{
|
||||||
|
_relativePanning = !_relativePanning;
|
||||||
|
_editor.ProjectCache.SetCustomData("CameraRelativePanningState", _relativePanning.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInvertPanningToggled(Control control)
|
||||||
|
{
|
||||||
|
_invertPanning = !_invertPanning;
|
||||||
|
_editor.ProjectCache.SetCustomData("CameraInvertPanningState", _invertPanning.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void OnViewpointChanged(ContextMenuButton button)
|
||||||
|
{
|
||||||
|
var orient = Quaternion.Euler((Float3)button.Tag);
|
||||||
|
OrientViewport(ref orient);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFieldOfViewChanged(FloatValueBox control)
|
||||||
|
{
|
||||||
|
_fieldOfView = control.Value;
|
||||||
|
_editor.ProjectCache.SetCustomData("CameraFieldOfViewValue", _fieldOfView.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnOrthographicModeToggled(Control control)
|
||||||
|
{
|
||||||
|
_isOrtho = !_isOrtho;
|
||||||
|
|
||||||
|
if (_orthographicModeButton != null)
|
||||||
|
_orthographicModeButton.Checked = !_isOrtho;
|
||||||
|
|
||||||
|
if (_isOrtho)
|
||||||
|
{
|
||||||
|
var orient = ViewOrientation;
|
||||||
|
OrientViewport(ref orient);
|
||||||
|
}
|
||||||
|
|
||||||
|
_editor.ProjectCache.SetCustomData("CameraOrthographicState", _isOrtho.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnOrthographicSizeChanged(FloatValueBox control)
|
||||||
|
{
|
||||||
|
_orthoSize = control.Value;
|
||||||
|
_editor.ProjectCache.SetCustomData("CameraOrthographicSizeValue", _orthoSize.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnNearPlaneChanged(FloatValueBox control)
|
||||||
|
{
|
||||||
|
_nearPlane = control.Value;
|
||||||
|
_editor.ProjectCache.SetCustomData("CameraNearPlaneValue", _nearPlane.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFarPlaneChanged(FloatValueBox control)
|
||||||
|
{
|
||||||
|
_farPlane = control.Value;
|
||||||
|
_editor.ProjectCache.SetCustomData("CameraNearPlaneValue", _farPlane.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this viewport is using mouse currently (eg. user moving objects).
|
/// Gets a value indicating whether this viewport is using mouse currently (eg. user moving objects).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -798,33 +1148,59 @@ namespace FlaxEditor.Viewport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnCameraMovementProgressChanged()
|
||||||
|
{
|
||||||
|
// prevent NaN
|
||||||
|
if (Math.Abs(_minMovementSpeed - _maxMovementSpeed) < Mathf.Epsilon)
|
||||||
|
{
|
||||||
|
_speedStep = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.Abs(_movementSpeed - _maxMovementSpeed) < Mathf.Epsilon)
|
||||||
|
{
|
||||||
|
_speedStep = _maxSpeedSteps;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (Math.Abs(_movementSpeed - _minMovementSpeed) < Mathf.Epsilon)
|
||||||
|
{
|
||||||
|
_speedStep = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate current linear/eased progress
|
||||||
|
var progress = Mathf.Remap(_movementSpeed, _minMovementSpeed, _maxMovementSpeed, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
if (_useCameraEasing)
|
||||||
|
progress = Mathf.Pow(progress, 1.0f / _cameraEasingDegree);
|
||||||
|
|
||||||
|
_speedStep = Mathf.RoundToInt(progress * _maxSpeedSteps);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Increases or decreases the camera movement speed.
|
/// Increases or decreases the camera movement speed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="step">The stepping direction for speed adjustment.</param>
|
/// <param name="step">The stepping direction for speed adjustment.</param>
|
||||||
protected void AdjustCameraMoveSpeed(int step)
|
protected void AdjustCameraMoveSpeed(int step)
|
||||||
{
|
{
|
||||||
int camValueIndex = -1;
|
_speedStep = Mathf.Clamp(_speedStep + step, 0, _maxSpeedSteps);
|
||||||
for (int i = 0; i < EditorViewportCameraSpeedValues.Length; i++)
|
|
||||||
{
|
|
||||||
if (Mathf.NearEqual(EditorViewportCameraSpeedValues[i], _movementSpeed))
|
|
||||||
{
|
|
||||||
camValueIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (camValueIndex == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (step > 0)
|
// calculate new linear/eased progress
|
||||||
MovementSpeed = EditorViewportCameraSpeedValues[Mathf.Min(camValueIndex + 1, EditorViewportCameraSpeedValues.Length - 1)];
|
var progress = _useCameraEasing
|
||||||
else if (step < 0)
|
? Mathf.Pow((float)_speedStep / _maxSpeedSteps, _cameraEasingDegree)
|
||||||
MovementSpeed = EditorViewportCameraSpeedValues[Mathf.Max(camValueIndex - 1, 0)];
|
: (float)_speedStep / _maxSpeedSteps;
|
||||||
|
|
||||||
|
var speed = Mathf.Lerp(_minMovementSpeed, _maxMovementSpeed, progress);
|
||||||
|
MovementSpeed = (float)Math.Round(speed, 3);
|
||||||
|
_editor.ProjectCache.SetCustomData("CameraMovementSpeedValue", _movementSpeed.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnEditorOptionsChanged(EditorOptions options)
|
private void OnEditorOptionsChanged(EditorOptions options)
|
||||||
{
|
{
|
||||||
_mouseSensitivity = options.Viewport.MouseSensitivity;
|
_mouseSensitivity = options.Viewport.MouseSensitivity;
|
||||||
|
_maxSpeedSteps = options.Viewport.TotalCameraSpeedSteps;
|
||||||
|
_cameraEasingDegree = options.Viewport.CameraEasingDegree;
|
||||||
|
OnCameraMovementProgressChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRenderBegin(RenderTask task, GPUContext context)
|
private void OnRenderBegin(RenderTask task, GPUContext context)
|
||||||
@@ -863,7 +1239,7 @@ namespace FlaxEditor.Viewport
|
|||||||
}
|
}
|
||||||
|
|
||||||
private FpsCounter _fpsCounter;
|
private FpsCounter _fpsCounter;
|
||||||
private ContextMenuButton _showFpsButon;
|
private ContextMenuButton _showFpsButton;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether show or hide FPS counter.
|
/// Gets or sets a value indicating whether show or hide FPS counter.
|
||||||
@@ -875,7 +1251,7 @@ namespace FlaxEditor.Viewport
|
|||||||
{
|
{
|
||||||
_fpsCounter.Visible = value;
|
_fpsCounter.Visible = value;
|
||||||
_fpsCounter.Enabled = value;
|
_fpsCounter.Enabled = value;
|
||||||
_showFpsButon.Icon = value ? Style.Current.CheckBoxTick : SpriteHandle.Invalid;
|
_showFpsButton.Icon = value ? Style.Current.CheckBoxTick : SpriteHandle.Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1016,8 +1392,6 @@ namespace FlaxEditor.Viewport
|
|||||||
/// <param name="win">The parent window.</param>
|
/// <param name="win">The parent window.</param>
|
||||||
protected virtual void OnControlMouseBegin(Window win)
|
protected virtual void OnControlMouseBegin(Window win)
|
||||||
{
|
{
|
||||||
_wheelMovementChangeDeltaSum = 0;
|
|
||||||
|
|
||||||
// Hide cursor and start tracking mouse movement
|
// Hide cursor and start tracking mouse movement
|
||||||
win.StartTrackingMouse(false);
|
win.StartTrackingMouse(false);
|
||||||
win.Cursor = CursorType.Hidden;
|
win.Cursor = CursorType.Hidden;
|
||||||
@@ -1113,8 +1487,8 @@ namespace FlaxEditor.Viewport
|
|||||||
_camera.Update(deltaTime);
|
_camera.Update(deltaTime);
|
||||||
useMovementSpeed = _camera.UseMovementSpeed;
|
useMovementSpeed = _camera.UseMovementSpeed;
|
||||||
|
|
||||||
if (_speedWidget != null)
|
if (_cameraButton != null)
|
||||||
_speedWidget.Parent.Visible = useMovementSpeed;
|
_cameraButton.Parent.Visible = useMovementSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get parent window
|
// Get parent window
|
||||||
@@ -1217,18 +1591,8 @@ namespace FlaxEditor.Viewport
|
|||||||
rmbWheel = useMovementSpeed && (_input.IsMouseRightDown || _isVirtualMouseRightDown) && wheelInUse;
|
rmbWheel = useMovementSpeed && (_input.IsMouseRightDown || _isVirtualMouseRightDown) && wheelInUse;
|
||||||
if (rmbWheel)
|
if (rmbWheel)
|
||||||
{
|
{
|
||||||
const float step = 4.0f;
|
var step = _input.MouseWheelDelta * options.Viewport.MouseWheelSensitivity;
|
||||||
_wheelMovementChangeDeltaSum += _input.MouseWheelDelta * options.Viewport.MouseWheelSensitivity;
|
AdjustCameraMoveSpeed(step > 0.0f ? 1 : -1);
|
||||||
if (_wheelMovementChangeDeltaSum >= step)
|
|
||||||
{
|
|
||||||
_wheelMovementChangeDeltaSum -= step;
|
|
||||||
AdjustCameraMoveSpeed(1);
|
|
||||||
}
|
|
||||||
else if (_wheelMovementChangeDeltaSum <= -step)
|
|
||||||
{
|
|
||||||
_wheelMovementChangeDeltaSum += step;
|
|
||||||
AdjustCameraMoveSpeed(-1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1497,22 +1861,6 @@ namespace FlaxEditor.Viewport
|
|||||||
new CameraViewpoint("Bottom", new Float3(-90, 0, 0))
|
new CameraViewpoint("Bottom", new Float3(-90, 0, 0))
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly float[] EditorViewportCameraSpeedValues =
|
|
||||||
{
|
|
||||||
0.05f,
|
|
||||||
0.1f,
|
|
||||||
0.25f,
|
|
||||||
0.5f,
|
|
||||||
1.0f,
|
|
||||||
2.0f,
|
|
||||||
4.0f,
|
|
||||||
6.0f,
|
|
||||||
8.0f,
|
|
||||||
16.0f,
|
|
||||||
32.0f,
|
|
||||||
64.0f,
|
|
||||||
};
|
|
||||||
|
|
||||||
private struct ViewModeOptions
|
private struct ViewModeOptions
|
||||||
{
|
{
|
||||||
public readonly string Name;
|
public readonly string Name;
|
||||||
@@ -1568,24 +1916,6 @@ namespace FlaxEditor.Viewport
|
|||||||
new ViewModeOptions(ViewMode.GlobalIllumination, "Global Illumination"),
|
new ViewModeOptions(ViewMode.GlobalIllumination, "Global Illumination"),
|
||||||
};
|
};
|
||||||
|
|
||||||
private void WidgetCamSpeedShowHide(Control cm)
|
|
||||||
{
|
|
||||||
if (cm.Visible == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var ccm = (ContextMenu)cm;
|
|
||||||
foreach (var e in ccm.Items)
|
|
||||||
{
|
|
||||||
if (e is ContextMenuButton b)
|
|
||||||
{
|
|
||||||
var v = (float)b.Tag;
|
|
||||||
b.Icon = Mathf.Abs(MovementSpeed - v) < 0.001f
|
|
||||||
? Style.Current.CheckBoxTick
|
|
||||||
: SpriteHandle.Invalid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WidgetViewModeShowHideClicked(ContextMenuButton button)
|
private void WidgetViewModeShowHideClicked(ContextMenuButton button)
|
||||||
{
|
{
|
||||||
if (button.Tag is ViewMode v)
|
if (button.Tag is ViewMode v)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ namespace FlaxEditor.Viewport.Widgets
|
|||||||
private bool _checked;
|
private bool _checked;
|
||||||
private bool _autoCheck;
|
private bool _autoCheck;
|
||||||
private bool _isMosueDown;
|
private bool _isMosueDown;
|
||||||
|
private float _forcedTextWidth;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event fired when user toggles checked state.
|
/// Event fired when user toggles checked state.
|
||||||
@@ -63,14 +64,16 @@ namespace FlaxEditor.Viewport.Widgets
|
|||||||
/// <param name="text">The text.</param>
|
/// <param name="text">The text.</param>
|
||||||
/// <param name="icon">The icon.</param>
|
/// <param name="icon">The icon.</param>
|
||||||
/// <param name="contextMenu">The context menu.</param>
|
/// <param name="contextMenu">The context menu.</param>
|
||||||
/// <param name="autoCheck">if set to <c>true</c> will be automatic checked on mouse click.</param>
|
/// <param name="autoCheck">If set to <c>true</c> will be automatic checked on mouse click.</param>
|
||||||
public ViewportWidgetButton(string text, SpriteHandle icon, ContextMenu contextMenu = null, bool autoCheck = false)
|
/// <param name="textWidth">Forces the text to be drawn with the specified width.</param>
|
||||||
: base(0, 0, CalculateButtonWidth(0, icon.IsValid), ViewportWidgetsContainer.WidgetsHeight)
|
public ViewportWidgetButton(string text, SpriteHandle icon, ContextMenu contextMenu = null, bool autoCheck = false, float textWidth = 0.0f)
|
||||||
|
: base(0, 0, CalculateButtonWidth(textWidth, icon.IsValid), ViewportWidgetsContainer.WidgetsHeight)
|
||||||
{
|
{
|
||||||
_text = text;
|
_text = text;
|
||||||
Icon = icon;
|
Icon = icon;
|
||||||
_cm = contextMenu;
|
_cm = contextMenu;
|
||||||
_autoCheck = autoCheck;
|
_autoCheck = autoCheck;
|
||||||
|
_forcedTextWidth = textWidth;
|
||||||
|
|
||||||
if (_cm != null)
|
if (_cm != null)
|
||||||
_cm.VisibleChanged += CmOnVisibleChanged;
|
_cm.VisibleChanged += CmOnVisibleChanged;
|
||||||
@@ -160,7 +163,7 @@ namespace FlaxEditor.Viewport.Widgets
|
|||||||
var style = Style.Current;
|
var style = Style.Current;
|
||||||
|
|
||||||
if (style != null && style.FontMedium)
|
if (style != null && style.FontMedium)
|
||||||
Width = CalculateButtonWidth(style.FontMedium.MeasureText(_text).X, Icon.IsValid);
|
Width = CalculateButtonWidth(_forcedTextWidth > 0.0f ? _forcedTextWidth : style.FontMedium.MeasureText(_text).X, Icon.IsValid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,9 +13,7 @@ namespace FlaxEngine.TypeConverters
|
|||||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||||
{
|
{
|
||||||
if (sourceType == typeof(string))
|
if (sourceType == typeof(string))
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
return base.CanConvertFrom(context, sourceType);
|
return base.CanConvertFrom(context, sourceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,9 +21,7 @@ namespace FlaxEngine.TypeConverters
|
|||||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
||||||
{
|
{
|
||||||
if (destinationType == typeof(string))
|
if (destinationType == typeof(string))
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
return base.CanConvertTo(context, destinationType);
|
return base.CanConvertTo(context, destinationType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,34 +7,14 @@ using System.Globalization;
|
|||||||
|
|
||||||
namespace FlaxEngine.TypeConverters
|
namespace FlaxEngine.TypeConverters
|
||||||
{
|
{
|
||||||
internal class Double2Converter : TypeConverter
|
internal class Double2Converter : VectorConverter
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
|
||||||
{
|
|
||||||
if (sourceType == typeof(string))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return base.CanConvertFrom(context, sourceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
|
||||||
{
|
|
||||||
if (destinationType == typeof(string))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return base.CanConvertTo(context, destinationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
{
|
{
|
||||||
if (value is string str)
|
if (value is string str)
|
||||||
{
|
{
|
||||||
string[] v = str.Split(',');
|
string[] v = GetParts(str);
|
||||||
return new Double2(double.Parse(v[0], culture), double.Parse(v[1], culture));
|
return new Double2(double.Parse(v[0], culture), double.Parse(v[1], culture));
|
||||||
}
|
}
|
||||||
return base.ConvertFrom(context, culture, value);
|
return base.ConvertFrom(context, culture, value);
|
||||||
|
|||||||
@@ -7,34 +7,14 @@ using System.Globalization;
|
|||||||
|
|
||||||
namespace FlaxEngine.TypeConverters
|
namespace FlaxEngine.TypeConverters
|
||||||
{
|
{
|
||||||
internal class Double3Converter : TypeConverter
|
internal class Double3Converter : VectorConverter
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
|
||||||
{
|
|
||||||
if (sourceType == typeof(string))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return base.CanConvertFrom(context, sourceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
|
||||||
{
|
|
||||||
if (destinationType == typeof(string))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return base.CanConvertTo(context, destinationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
{
|
{
|
||||||
if (value is string str)
|
if (value is string str)
|
||||||
{
|
{
|
||||||
string[] v = str.Split(',');
|
string[] v = GetParts(str);
|
||||||
return new Double3(double.Parse(v[0], culture), double.Parse(v[1], culture), double.Parse(v[2], culture));
|
return new Double3(double.Parse(v[0], culture), double.Parse(v[1], culture), double.Parse(v[2], culture));
|
||||||
}
|
}
|
||||||
return base.ConvertFrom(context, culture, value);
|
return base.ConvertFrom(context, culture, value);
|
||||||
|
|||||||
@@ -7,34 +7,14 @@ using System.Globalization;
|
|||||||
|
|
||||||
namespace FlaxEngine.TypeConverters
|
namespace FlaxEngine.TypeConverters
|
||||||
{
|
{
|
||||||
internal class Double4Converter : TypeConverter
|
internal class Double4Converter : VectorConverter
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
|
||||||
{
|
|
||||||
if (sourceType == typeof(string))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return base.CanConvertFrom(context, sourceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
|
||||||
{
|
|
||||||
if (destinationType == typeof(string))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return base.CanConvertTo(context, destinationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
{
|
{
|
||||||
if (value is string str)
|
if (value is string str)
|
||||||
{
|
{
|
||||||
string[] v = str.Split(',');
|
string[] v = GetParts(str);
|
||||||
return new Double4(double.Parse(v[0], culture), double.Parse(v[1], culture), double.Parse(v[2], culture), double.Parse(v[3], culture));
|
return new Double4(double.Parse(v[0], culture), double.Parse(v[1], culture), double.Parse(v[2], culture), double.Parse(v[3], culture));
|
||||||
}
|
}
|
||||||
return base.ConvertFrom(context, culture, value);
|
return base.ConvertFrom(context, culture, value);
|
||||||
|
|||||||
@@ -7,34 +7,14 @@ using System.Globalization;
|
|||||||
|
|
||||||
namespace FlaxEngine.TypeConverters
|
namespace FlaxEngine.TypeConverters
|
||||||
{
|
{
|
||||||
internal class Float2Converter : TypeConverter
|
internal class Float2Converter : VectorConverter
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
|
||||||
{
|
|
||||||
if (sourceType == typeof(string))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return base.CanConvertFrom(context, sourceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
|
||||||
{
|
|
||||||
if (destinationType == typeof(string))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return base.CanConvertTo(context, destinationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
{
|
{
|
||||||
if (value is string str)
|
if (value is string str)
|
||||||
{
|
{
|
||||||
string[] v = str.Split(',');
|
string[] v = GetParts(str);
|
||||||
return new Float2(float.Parse(v[0], culture), float.Parse(v[1], culture));
|
return new Float2(float.Parse(v[0], culture), float.Parse(v[1], culture));
|
||||||
}
|
}
|
||||||
return base.ConvertFrom(context, culture, value);
|
return base.ConvertFrom(context, culture, value);
|
||||||
|
|||||||
@@ -7,34 +7,14 @@ using System.Globalization;
|
|||||||
|
|
||||||
namespace FlaxEngine.TypeConverters
|
namespace FlaxEngine.TypeConverters
|
||||||
{
|
{
|
||||||
internal class Float3Converter : TypeConverter
|
internal class Float3Converter : VectorConverter
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
|
||||||
{
|
|
||||||
if (sourceType == typeof(string))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return base.CanConvertFrom(context, sourceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
|
||||||
{
|
|
||||||
if (destinationType == typeof(string))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return base.CanConvertTo(context, destinationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
{
|
{
|
||||||
if (value is string str)
|
if (value is string str)
|
||||||
{
|
{
|
||||||
string[] v = str.Split(',');
|
string[] v = GetParts(str);
|
||||||
return new Float3(float.Parse(v[0], culture), float.Parse(v[1], culture), float.Parse(v[2], culture));
|
return new Float3(float.Parse(v[0], culture), float.Parse(v[1], culture), float.Parse(v[2], culture));
|
||||||
}
|
}
|
||||||
return base.ConvertFrom(context, culture, value);
|
return base.ConvertFrom(context, culture, value);
|
||||||
|
|||||||
@@ -7,15 +7,13 @@ using System.Globalization;
|
|||||||
|
|
||||||
namespace FlaxEngine.TypeConverters
|
namespace FlaxEngine.TypeConverters
|
||||||
{
|
{
|
||||||
internal class Float4Converter : TypeConverter
|
internal class VectorConverter : TypeConverter
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||||
{
|
{
|
||||||
if (sourceType == typeof(string))
|
if (sourceType == typeof(string))
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
return base.CanConvertFrom(context, sourceType);
|
return base.CanConvertFrom(context, sourceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,18 +21,32 @@ namespace FlaxEngine.TypeConverters
|
|||||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
||||||
{
|
{
|
||||||
if (destinationType == typeof(string))
|
if (destinationType == typeof(string))
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
return base.CanConvertTo(context, destinationType);
|
return base.CanConvertTo(context, destinationType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static string[] GetParts(string str)
|
||||||
|
{
|
||||||
|
string[] v = str.Split(',');
|
||||||
|
if (v.Length == 1)
|
||||||
|
{
|
||||||
|
// When converting from ToString()
|
||||||
|
v = str.Split(' ');
|
||||||
|
for (int i = 0; i < v.Length; i++)
|
||||||
|
v[i] = v[i].Substring(v[i].IndexOf(':') + 1);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class Float4Converter : VectorConverter
|
||||||
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
{
|
{
|
||||||
if (value is string str)
|
if (value is string str)
|
||||||
{
|
{
|
||||||
string[] v = str.Split(',');
|
string[] v = GetParts(str);
|
||||||
return new Float4(float.Parse(v[0], culture), float.Parse(v[1], culture), float.Parse(v[2], culture), float.Parse(v[3], culture));
|
return new Float4(float.Parse(v[0], culture), float.Parse(v[1], culture), float.Parse(v[2], culture), float.Parse(v[3], culture));
|
||||||
}
|
}
|
||||||
return base.ConvertFrom(context, culture, value);
|
return base.ConvertFrom(context, culture, value);
|
||||||
|
|||||||
@@ -7,34 +7,14 @@ using System.Globalization;
|
|||||||
|
|
||||||
namespace FlaxEngine.TypeConverters
|
namespace FlaxEngine.TypeConverters
|
||||||
{
|
{
|
||||||
internal class Int2Converter : TypeConverter
|
internal class Int2Converter : VectorConverter
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
|
||||||
{
|
|
||||||
if (sourceType == typeof(string))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return base.CanConvertFrom(context, sourceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
|
||||||
{
|
|
||||||
if (destinationType == typeof(string))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return base.CanConvertTo(context, destinationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
{
|
{
|
||||||
if (value is string str)
|
if (value is string str)
|
||||||
{
|
{
|
||||||
string[] v = str.Split(',');
|
string[] v = GetParts(str);
|
||||||
return new Int2(int.Parse(v[0], culture), int.Parse(v[1], culture));
|
return new Int2(int.Parse(v[0], culture), int.Parse(v[1], culture));
|
||||||
}
|
}
|
||||||
return base.ConvertFrom(context, culture, value);
|
return base.ConvertFrom(context, culture, value);
|
||||||
|
|||||||
@@ -7,34 +7,14 @@ using System.Globalization;
|
|||||||
|
|
||||||
namespace FlaxEngine.TypeConverters
|
namespace FlaxEngine.TypeConverters
|
||||||
{
|
{
|
||||||
internal class Int3Converter : TypeConverter
|
internal class Int3Converter : VectorConverter
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
|
||||||
{
|
|
||||||
if (sourceType == typeof(string))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return base.CanConvertFrom(context, sourceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
|
||||||
{
|
|
||||||
if (destinationType == typeof(string))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return base.CanConvertTo(context, destinationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
{
|
{
|
||||||
if (value is string str)
|
if (value is string str)
|
||||||
{
|
{
|
||||||
string[] v = str.Split(',');
|
string[] v = GetParts(str);
|
||||||
return new Int3(int.Parse(v[0], culture), int.Parse(v[1], culture), int.Parse(v[2], culture));
|
return new Int3(int.Parse(v[0], culture), int.Parse(v[1], culture), int.Parse(v[2], culture));
|
||||||
}
|
}
|
||||||
return base.ConvertFrom(context, culture, value);
|
return base.ConvertFrom(context, culture, value);
|
||||||
|
|||||||
@@ -7,34 +7,14 @@ using System.Globalization;
|
|||||||
|
|
||||||
namespace FlaxEngine.TypeConverters
|
namespace FlaxEngine.TypeConverters
|
||||||
{
|
{
|
||||||
internal class Int4Converter : TypeConverter
|
internal class Int4Converter : VectorConverter
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
|
||||||
{
|
|
||||||
if (sourceType == typeof(string))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return base.CanConvertFrom(context, sourceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
|
||||||
{
|
|
||||||
if (destinationType == typeof(string))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return base.CanConvertTo(context, destinationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
{
|
{
|
||||||
if (value is string str)
|
if (value is string str)
|
||||||
{
|
{
|
||||||
string[] v = str.Split(',');
|
string[] v = GetParts(str);
|
||||||
return new Int4(int.Parse(v[0], culture), int.Parse(v[1], culture), int.Parse(v[2], culture), int.Parse(v[3], culture));
|
return new Int4(int.Parse(v[0], culture), int.Parse(v[1], culture), int.Parse(v[2], culture), int.Parse(v[3], culture));
|
||||||
}
|
}
|
||||||
return base.ConvertFrom(context, culture, value);
|
return base.ConvertFrom(context, culture, value);
|
||||||
|
|||||||
@@ -7,34 +7,14 @@ using System.Globalization;
|
|||||||
|
|
||||||
namespace FlaxEngine.TypeConverters
|
namespace FlaxEngine.TypeConverters
|
||||||
{
|
{
|
||||||
internal class QuaternionConverter : TypeConverter
|
internal class QuaternionConverter : VectorConverter
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
|
||||||
{
|
|
||||||
if (sourceType == typeof(string))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return base.CanConvertFrom(context, sourceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
|
||||||
{
|
|
||||||
if (destinationType == typeof(string))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return base.CanConvertTo(context, destinationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
{
|
{
|
||||||
if (value is string str)
|
if (value is string str)
|
||||||
{
|
{
|
||||||
string[] v = str.Split(',');
|
string[] v = GetParts(str);
|
||||||
return new Quaternion(float.Parse(v[0], culture), float.Parse(v[1], culture), float.Parse(v[2], culture), float.Parse(v[3], culture));
|
return new Quaternion(float.Parse(v[0], culture), float.Parse(v[1], culture), float.Parse(v[2], culture), float.Parse(v[3], culture));
|
||||||
}
|
}
|
||||||
return base.ConvertFrom(context, culture, value);
|
return base.ConvertFrom(context, culture, value);
|
||||||
|
|||||||
@@ -7,34 +7,14 @@ using System.Globalization;
|
|||||||
|
|
||||||
namespace FlaxEngine.TypeConverters
|
namespace FlaxEngine.TypeConverters
|
||||||
{
|
{
|
||||||
internal class Vector2Converter : TypeConverter
|
internal class Vector2Converter : VectorConverter
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
|
||||||
{
|
|
||||||
if (sourceType == typeof(string))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return base.CanConvertFrom(context, sourceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
|
||||||
{
|
|
||||||
if (destinationType == typeof(string))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return base.CanConvertTo(context, destinationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
{
|
{
|
||||||
if (value is string str)
|
if (value is string str)
|
||||||
{
|
{
|
||||||
string[] v = str.Split(',');
|
string[] v = GetParts(str);
|
||||||
return new Vector2(float.Parse(v[0], culture), float.Parse(v[1], culture));
|
return new Vector2(float.Parse(v[0], culture), float.Parse(v[1], culture));
|
||||||
}
|
}
|
||||||
return base.ConvertFrom(context, culture, value);
|
return base.ConvertFrom(context, culture, value);
|
||||||
|
|||||||
@@ -7,34 +7,14 @@ using System.Globalization;
|
|||||||
|
|
||||||
namespace FlaxEngine.TypeConverters
|
namespace FlaxEngine.TypeConverters
|
||||||
{
|
{
|
||||||
internal class Vector3Converter : TypeConverter
|
internal class Vector3Converter : VectorConverter
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
|
||||||
{
|
|
||||||
if (sourceType == typeof(string))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return base.CanConvertFrom(context, sourceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
|
||||||
{
|
|
||||||
if (destinationType == typeof(string))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return base.CanConvertTo(context, destinationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
{
|
{
|
||||||
if (value is string str)
|
if (value is string str)
|
||||||
{
|
{
|
||||||
string[] v = str.Split(',');
|
string[] v = GetParts(str);
|
||||||
return new Vector3(float.Parse(v[0], culture), float.Parse(v[1], culture), float.Parse(v[2], culture));
|
return new Vector3(float.Parse(v[0], culture), float.Parse(v[1], culture), float.Parse(v[2], culture));
|
||||||
}
|
}
|
||||||
return base.ConvertFrom(context, culture, value);
|
return base.ConvertFrom(context, culture, value);
|
||||||
|
|||||||
@@ -7,34 +7,14 @@ using System.Globalization;
|
|||||||
|
|
||||||
namespace FlaxEngine.TypeConverters
|
namespace FlaxEngine.TypeConverters
|
||||||
{
|
{
|
||||||
internal class Vector4Converter : TypeConverter
|
internal class Vector4Converter : VectorConverter
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
|
||||||
{
|
|
||||||
if (sourceType == typeof(string))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return base.CanConvertFrom(context, sourceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
|
||||||
{
|
|
||||||
if (destinationType == typeof(string))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return base.CanConvertTo(context, destinationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
{
|
{
|
||||||
if (value is string str)
|
if (value is string str)
|
||||||
{
|
{
|
||||||
string[] v = str.Split(',');
|
string[] v = GetParts(str);
|
||||||
return new Vector4(float.Parse(v[0], culture), float.Parse(v[1], culture), float.Parse(v[2], culture), float.Parse(v[3], culture));
|
return new Vector4(float.Parse(v[0], culture), float.Parse(v[1], culture), float.Parse(v[2], culture), float.Parse(v[3], culture));
|
||||||
}
|
}
|
||||||
return base.ConvertFrom(context, culture, value);
|
return base.ConvertFrom(context, culture, value);
|
||||||
|
|||||||
@@ -646,6 +646,12 @@ inline Vector2Base<T> operator/(typename TOtherFloat<T>::Type a, const Vector2Ba
|
|||||||
return Vector2Base<T>(a) / b;
|
return Vector2Base<T>(a) / b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline uint32 GetHash(const Vector2Base<T>& key)
|
||||||
|
{
|
||||||
|
return (*(uint32*)&key.X * 397) ^ *(uint32*)&key.Y;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Math
|
namespace Math
|
||||||
{
|
{
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|||||||
@@ -977,6 +977,12 @@ inline Vector3Base<T> operator/(typename TOtherFloat<T>::Type a, const Vector3Ba
|
|||||||
return Vector3Base<T>(a) / b;
|
return Vector3Base<T>(a) / b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline uint32 GetHash(const Vector3Base<T>& key)
|
||||||
|
{
|
||||||
|
return (((*(uint32*)&key.X * 397) ^ *(uint32*)&key.Y) * 397) ^ *(uint32*)&key.Z;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Math
|
namespace Math
|
||||||
{
|
{
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|||||||
@@ -552,6 +552,12 @@ inline Vector4Base<T> operator/(typename TOtherFloat<T>::Type a, const Vector4Ba
|
|||||||
return Vector4Base<T>(a) / b;
|
return Vector4Base<T>(a) / b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline uint32 GetHash(const Vector4Base<T>& key)
|
||||||
|
{
|
||||||
|
return (((((*(uint32*)&key.X * 397) ^ *(uint32*)&key.Y) * 397) ^ *(uint32*)&key.Z) * 397) ^*(uint32*)&key.W;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Math
|
namespace Math
|
||||||
{
|
{
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|||||||
@@ -7,15 +7,15 @@ Version::Version(int32 major, int32 minor, int32 build, int32 revision)
|
|||||||
{
|
{
|
||||||
_major = Math::Max(major, 0);
|
_major = Math::Max(major, 0);
|
||||||
_minor = Math::Max(minor, 0);
|
_minor = Math::Max(minor, 0);
|
||||||
_build = Math::Max(build, 0);
|
_build = Math::Max(build, -1);
|
||||||
_revision = Math::Max(revision, 0);
|
_revision = Math::Max(revision, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Version::Version(int32 major, int32 minor, int32 build)
|
Version::Version(int32 major, int32 minor, int32 build)
|
||||||
{
|
{
|
||||||
_major = Math::Max(major, 0);
|
_major = Math::Max(major, 0);
|
||||||
_minor = Math::Max(minor, 0);
|
_minor = Math::Max(minor, 0);
|
||||||
_build = Math::Max(build, 0);
|
_build = Math::Max(build, -1);
|
||||||
_revision = -1;
|
_revision = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1302,7 +1302,8 @@ namespace FlaxEngine.Interop
|
|||||||
#if !USE_AOT
|
#if !USE_AOT
|
||||||
internal bool TryGetDelegate(out Invoker.MarshalAndInvokeDelegate outDeleg, out object outDelegInvoke)
|
internal bool TryGetDelegate(out Invoker.MarshalAndInvokeDelegate outDeleg, out object outDelegInvoke)
|
||||||
{
|
{
|
||||||
if (invokeDelegate == null)
|
// Skip using in-built delegate for value types (eg. Transform) to properly handle instance value passing to method
|
||||||
|
if (invokeDelegate == null && !method.DeclaringType.IsValueType)
|
||||||
{
|
{
|
||||||
List<Type> methodTypes = new List<Type>();
|
List<Type> methodTypes = new List<Type>();
|
||||||
if (!method.IsStatic)
|
if (!method.IsStatic)
|
||||||
|
|||||||
@@ -313,6 +313,8 @@ bool GPUDevice::Init()
|
|||||||
|
|
||||||
_res->TasksManager.SetExecutor(CreateTasksExecutor());
|
_res->TasksManager.SetExecutor(CreateTasksExecutor());
|
||||||
LOG(Info, "Total graphics memory: {0}", Utilities::BytesToText(TotalGraphicsMemory));
|
LOG(Info, "Total graphics memory: {0}", Utilities::BytesToText(TotalGraphicsMemory));
|
||||||
|
if (!Limits.HasCompute)
|
||||||
|
LOG(Warning, "Compute Shaders are not supported");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,11 @@ bool GPUShader::Create(MemoryReadStream& stream)
|
|||||||
GPUShaderProgramInitializer initializer;
|
GPUShaderProgramInitializer initializer;
|
||||||
#if !BUILD_RELEASE
|
#if !BUILD_RELEASE
|
||||||
initializer.Owner = this;
|
initializer.Owner = this;
|
||||||
|
const StringView name = GetName();
|
||||||
|
#else
|
||||||
|
const StringView name;
|
||||||
#endif
|
#endif
|
||||||
|
const bool hasCompute = GPUDevice::Instance->Limits.HasCompute;
|
||||||
for (int32 i = 0; i < shadersCount; i++)
|
for (int32 i = 0; i < shadersCount; i++)
|
||||||
{
|
{
|
||||||
const ShaderStage type = static_cast<ShaderStage>(stream.ReadByte());
|
const ShaderStage type = static_cast<ShaderStage>(stream.ReadByte());
|
||||||
@@ -117,10 +121,15 @@ bool GPUShader::Create(MemoryReadStream& stream)
|
|||||||
stream.ReadBytes(&initializer.Bindings, sizeof(ShaderBindings));
|
stream.ReadBytes(&initializer.Bindings, sizeof(ShaderBindings));
|
||||||
|
|
||||||
// Create shader program
|
// Create shader program
|
||||||
|
if (type == ShaderStage::Compute && !hasCompute)
|
||||||
|
{
|
||||||
|
LOG(Warning, "Failed to create {} Shader program '{}' ({}).", ::ToString(type), String(initializer.Name), name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
GPUShaderProgram* shader = CreateGPUShaderProgram(type, initializer, cache, cacheSize, stream);
|
GPUShaderProgram* shader = CreateGPUShaderProgram(type, initializer, cache, cacheSize, stream);
|
||||||
if (shader == nullptr)
|
if (shader == nullptr)
|
||||||
{
|
{
|
||||||
LOG(Error, "Failed to create {} Shader program '{}'.", ::ToString(type), String(initializer.Name));
|
LOG(Error, "Failed to create {} Shader program '{}' ({}).", ::ToString(type), String(initializer.Name), name);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,19 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
class GPUShaderProgramVS : public GPUShaderProgram
|
class GPUShaderProgramVS : public GPUShaderProgram
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
// Input element run-time data (see VertexShaderMeta::InputElement for compile-time data)
|
||||||
|
PACK_STRUCT(struct InputElement
|
||||||
|
{
|
||||||
|
byte Type; // VertexShaderMeta::InputType
|
||||||
|
byte Index;
|
||||||
|
byte Format; // PixelFormat
|
||||||
|
byte InputSlot;
|
||||||
|
uint32 AlignedByteOffset; // Fixed value or INPUT_LAYOUT_ELEMENT_ALIGN if auto
|
||||||
|
byte InputSlotClass; // INPUT_LAYOUT_ELEMENT_PER_VERTEX_DATA or INPUT_LAYOUT_ELEMENT_PER_INSTANCE_DATA
|
||||||
|
uint32 InstanceDataStepRate; // 0 if per-vertex
|
||||||
|
});
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets input layout description handle (platform dependent).
|
/// Gets input layout description handle (platform dependent).
|
||||||
|
|||||||
@@ -15,32 +15,21 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
|||||||
{
|
{
|
||||||
case ShaderStage::Vertex:
|
case ShaderStage::Vertex:
|
||||||
{
|
{
|
||||||
D3D11_INPUT_ELEMENT_DESC inputLayoutDesc[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
|
// Load Input Layout
|
||||||
|
|
||||||
// Temporary variables
|
|
||||||
byte Type, Format, Index, InputSlot, InputSlotClass;
|
|
||||||
uint32 AlignedByteOffset, InstanceDataStepRate;
|
|
||||||
|
|
||||||
// Load Input Layout (it may be empty)
|
|
||||||
byte inputLayoutSize;
|
byte inputLayoutSize;
|
||||||
stream.ReadByte(&inputLayoutSize);
|
stream.ReadByte(&inputLayoutSize);
|
||||||
ASSERT(inputLayoutSize <= VERTEX_SHADER_MAX_INPUT_ELEMENTS);
|
ASSERT(inputLayoutSize <= VERTEX_SHADER_MAX_INPUT_ELEMENTS);
|
||||||
|
D3D11_INPUT_ELEMENT_DESC inputLayoutDesc[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
|
||||||
for (int32 a = 0; a < inputLayoutSize; a++)
|
for (int32 a = 0; a < inputLayoutSize; a++)
|
||||||
{
|
{
|
||||||
// Read description
|
// Read description
|
||||||
// TODO: maybe use struct and load at once?
|
GPUShaderProgramVS::InputElement inputElement;
|
||||||
stream.ReadByte(&Type);
|
stream.Read(inputElement);
|
||||||
stream.ReadByte(&Index);
|
|
||||||
stream.ReadByte(&Format);
|
|
||||||
stream.ReadByte(&InputSlot);
|
|
||||||
stream.ReadUint32(&AlignedByteOffset);
|
|
||||||
stream.ReadByte(&InputSlotClass);
|
|
||||||
stream.ReadUint32(&InstanceDataStepRate);
|
|
||||||
|
|
||||||
// Get semantic name
|
// Get semantic name
|
||||||
const char* semanticName = nullptr;
|
const char* semanticName = nullptr;
|
||||||
// TODO: maybe use enum+mapping ?
|
// TODO: maybe use enum+mapping ?
|
||||||
switch (Type)
|
switch (inputElement.Type)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
semanticName = "POSITION";
|
semanticName = "POSITION";
|
||||||
@@ -70,7 +59,7 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
|||||||
semanticName = "BLENDWEIGHT";
|
semanticName = "BLENDWEIGHT";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(Fatal, "Invalid vertex shader element semantic type: {0}", Type);
|
LOG(Fatal, "Invalid vertex shader element semantic type: {0}", inputElement.Type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,12 +67,12 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
|||||||
inputLayoutDesc[a] =
|
inputLayoutDesc[a] =
|
||||||
{
|
{
|
||||||
semanticName,
|
semanticName,
|
||||||
static_cast<UINT>(Index),
|
static_cast<UINT>(inputElement.Index),
|
||||||
static_cast<DXGI_FORMAT>(Format),
|
static_cast<DXGI_FORMAT>(inputElement.Format),
|
||||||
static_cast<UINT>(InputSlot),
|
static_cast<UINT>(inputElement.InputSlot),
|
||||||
static_cast<UINT>(AlignedByteOffset),
|
static_cast<UINT>(inputElement.AlignedByteOffset),
|
||||||
static_cast<D3D11_INPUT_CLASSIFICATION>(InputSlotClass),
|
static_cast<D3D11_INPUT_CLASSIFICATION>(inputElement.InputSlotClass),
|
||||||
static_cast<UINT>(InstanceDataStepRate)
|
static_cast<UINT>(inputElement.InstanceDataStepRate)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,32 +20,21 @@ GPUShaderProgram* GPUShaderDX12::CreateGPUShaderProgram(ShaderStage type, const
|
|||||||
{
|
{
|
||||||
case ShaderStage::Vertex:
|
case ShaderStage::Vertex:
|
||||||
{
|
{
|
||||||
D3D12_INPUT_ELEMENT_DESC inputLayout[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
|
|
||||||
|
|
||||||
// Temporary variables
|
|
||||||
byte Type, Format, Index, InputSlot, InputSlotClass;
|
|
||||||
uint32 AlignedByteOffset, InstanceDataStepRate;
|
|
||||||
|
|
||||||
// Load Input Layout (it may be empty)
|
// Load Input Layout (it may be empty)
|
||||||
byte inputLayoutSize;
|
byte inputLayoutSize;
|
||||||
stream.ReadByte(&inputLayoutSize);
|
stream.ReadByte(&inputLayoutSize);
|
||||||
ASSERT(inputLayoutSize <= VERTEX_SHADER_MAX_INPUT_ELEMENTS);
|
ASSERT(inputLayoutSize <= VERTEX_SHADER_MAX_INPUT_ELEMENTS);
|
||||||
|
D3D12_INPUT_ELEMENT_DESC inputLayout[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
|
||||||
for (int32 a = 0; a < inputLayoutSize; a++)
|
for (int32 a = 0; a < inputLayoutSize; a++)
|
||||||
{
|
{
|
||||||
// Read description
|
// Read description
|
||||||
// TODO: maybe use struct and load at once?
|
GPUShaderProgramVS::InputElement inputElement;
|
||||||
stream.ReadByte(&Type);
|
stream.Read(inputElement);
|
||||||
stream.ReadByte(&Index);
|
|
||||||
stream.ReadByte(&Format);
|
|
||||||
stream.ReadByte(&InputSlot);
|
|
||||||
stream.ReadUint32(&AlignedByteOffset);
|
|
||||||
stream.ReadByte(&InputSlotClass);
|
|
||||||
stream.ReadUint32(&InstanceDataStepRate);
|
|
||||||
|
|
||||||
// Get semantic name
|
// Get semantic name
|
||||||
const char* semanticName = nullptr;
|
const char* semanticName = nullptr;
|
||||||
// TODO: maybe use enum+mapping ?
|
// TODO: maybe use enum+mapping ?
|
||||||
switch (Type)
|
switch (inputElement.Type)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
semanticName = "POSITION";
|
semanticName = "POSITION";
|
||||||
@@ -75,7 +64,7 @@ GPUShaderProgram* GPUShaderDX12::CreateGPUShaderProgram(ShaderStage type, const
|
|||||||
semanticName = "BLENDWEIGHT";
|
semanticName = "BLENDWEIGHT";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(Fatal, "Invalid vertex shader element semantic type: {0}", Type);
|
LOG(Fatal, "Invalid vertex shader element semantic type: {0}", inputElement.Type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,12 +72,12 @@ GPUShaderProgram* GPUShaderDX12::CreateGPUShaderProgram(ShaderStage type, const
|
|||||||
inputLayout[a] =
|
inputLayout[a] =
|
||||||
{
|
{
|
||||||
semanticName,
|
semanticName,
|
||||||
static_cast<UINT>(Index),
|
static_cast<UINT>(inputElement.Index),
|
||||||
static_cast<DXGI_FORMAT>(Format),
|
static_cast<DXGI_FORMAT>(inputElement.Format),
|
||||||
static_cast<UINT>(InputSlot),
|
static_cast<UINT>(inputElement.InputSlot),
|
||||||
static_cast<UINT>(AlignedByteOffset),
|
static_cast<UINT>(inputElement.AlignedByteOffset),
|
||||||
static_cast<D3D12_INPUT_CLASSIFICATION>(InputSlotClass),
|
static_cast<D3D12_INPUT_CLASSIFICATION>(inputElement.InputSlotClass),
|
||||||
static_cast<UINT>(InstanceDataStepRate)
|
static_cast<UINT>(inputElement.InstanceDataStepRate)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,9 @@
|
|||||||
#include "Engine/Graphics/PixelFormatExtensions.h"
|
#include "Engine/Graphics/PixelFormatExtensions.h"
|
||||||
|
|
||||||
#if PLATFORM_DESKTOP
|
#if PLATFORM_DESKTOP
|
||||||
#define VULKAN_UNIFORM_RING_BUFFER_SIZE 24 * 1024 * 1024
|
#define VULKAN_UNIFORM_RING_BUFFER_SIZE (24 * 1024 * 1024)
|
||||||
#else
|
#else
|
||||||
#define VULKAN_UNIFORM_RING_BUFFER_SIZE 8 * 1024 * 1024
|
#define VULKAN_UNIFORM_RING_BUFFER_SIZE (8 * 1024 * 1024)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
UniformBufferUploaderVulkan::UniformBufferUploaderVulkan(GPUDeviceVulkan* device)
|
UniformBufferUploaderVulkan::UniformBufferUploaderVulkan(GPUDeviceVulkan* device)
|
||||||
@@ -153,10 +153,6 @@ GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, cons
|
|||||||
vertexBindingDescriptions[i].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
vertexBindingDescriptions[i].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temporary variables
|
|
||||||
byte Type, Format, Index, InputSlot, InputSlotClass;
|
|
||||||
uint32 AlignedByteOffset, InstanceDataStepRate;
|
|
||||||
|
|
||||||
// Load Input Layout (it may be empty)
|
// Load Input Layout (it may be empty)
|
||||||
byte inputLayoutSize;
|
byte inputLayoutSize;
|
||||||
stream.ReadByte(&inputLayoutSize);
|
stream.ReadByte(&inputLayoutSize);
|
||||||
@@ -167,32 +163,26 @@ GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, cons
|
|||||||
for (int32 a = 0; a < inputLayoutSize; a++)
|
for (int32 a = 0; a < inputLayoutSize; a++)
|
||||||
{
|
{
|
||||||
// Read description
|
// Read description
|
||||||
// TODO: maybe use struct and load at once?
|
GPUShaderProgramVS::InputElement inputElement;
|
||||||
stream.ReadByte(&Type);
|
stream.Read(inputElement);
|
||||||
stream.ReadByte(&Index);
|
|
||||||
stream.ReadByte(&Format);
|
|
||||||
stream.ReadByte(&InputSlot);
|
|
||||||
stream.ReadUint32(&AlignedByteOffset);
|
|
||||||
stream.ReadByte(&InputSlotClass);
|
|
||||||
stream.ReadUint32(&InstanceDataStepRate);
|
|
||||||
|
|
||||||
const auto size = PixelFormatExtensions::SizeInBytes((PixelFormat)Format);
|
const auto size = PixelFormatExtensions::SizeInBytes((PixelFormat)inputElement.Format);
|
||||||
if (AlignedByteOffset != INPUT_LAYOUT_ELEMENT_ALIGN)
|
if (inputElement.AlignedByteOffset != INPUT_LAYOUT_ELEMENT_ALIGN)
|
||||||
offset = AlignedByteOffset;
|
offset = inputElement.AlignedByteOffset;
|
||||||
|
|
||||||
auto& vertexBindingDescription = vertexBindingDescriptions[InputSlot];
|
auto& vertexBindingDescription = vertexBindingDescriptions[inputElement.InputSlot];
|
||||||
vertexBindingDescription.binding = InputSlot;
|
vertexBindingDescription.binding = inputElement.InputSlot;
|
||||||
vertexBindingDescription.stride = Math::Max(vertexBindingDescription.stride, (uint32_t)(offset + size));
|
vertexBindingDescription.stride = Math::Max(vertexBindingDescription.stride, (uint32_t)(offset + size));
|
||||||
vertexBindingDescription.inputRate = InputSlotClass == INPUT_LAYOUT_ELEMENT_PER_VERTEX_DATA ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
|
vertexBindingDescription.inputRate = inputElement.InputSlotClass == INPUT_LAYOUT_ELEMENT_PER_VERTEX_DATA ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
|
||||||
ASSERT(InstanceDataStepRate == 0 || InstanceDataStepRate == 1);
|
ASSERT(inputElement.InstanceDataStepRate == 0 || inputElement.InstanceDataStepRate == 1);
|
||||||
|
|
||||||
auto& vertexAttributeDescription = vertexAttributeDescriptions[a];
|
auto& vertexAttributeDescription = vertexAttributeDescriptions[a];
|
||||||
vertexAttributeDescription.location = a;
|
vertexAttributeDescription.location = a;
|
||||||
vertexAttributeDescription.binding = InputSlot;
|
vertexAttributeDescription.binding = inputElement.InputSlot;
|
||||||
vertexAttributeDescription.format = RenderToolsVulkan::ToVulkanFormat((PixelFormat)Format);
|
vertexAttributeDescription.format = RenderToolsVulkan::ToVulkanFormat((PixelFormat)inputElement.Format);
|
||||||
vertexAttributeDescription.offset = offset;
|
vertexAttributeDescription.offset = offset;
|
||||||
|
|
||||||
bindingsCount = Math::Max(bindingsCount, (uint32)InputSlot + 1);
|
bindingsCount = Math::Max(bindingsCount, (uint32)inputElement.InputSlot + 1);
|
||||||
offset += size;
|
offset += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ PrefabManagerService PrefabManagerServiceInstance;
|
|||||||
Actor* PrefabManager::SpawnPrefab(Prefab* prefab)
|
Actor* PrefabManager::SpawnPrefab(Prefab* prefab)
|
||||||
{
|
{
|
||||||
Actor* parent = Level::Scenes.Count() != 0 ? Level::Scenes.Get()[0] : nullptr;
|
Actor* parent = Level::Scenes.Count() != 0 ? Level::Scenes.Get()[0] : nullptr;
|
||||||
return SpawnPrefab(prefab, Transform::Identity, parent, nullptr);
|
return SpawnPrefab(prefab, Transform(Vector3::Minimum), parent, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Actor* PrefabManager::SpawnPrefab(Prefab* prefab, const Vector3& position)
|
Actor* PrefabManager::SpawnPrefab(Prefab* prefab, const Vector3& position)
|
||||||
@@ -73,12 +73,12 @@ Actor* PrefabManager::SpawnPrefab(Prefab* prefab, Actor* parent, const Transform
|
|||||||
|
|
||||||
Actor* PrefabManager::SpawnPrefab(Prefab* prefab, Actor* parent)
|
Actor* PrefabManager::SpawnPrefab(Prefab* prefab, Actor* parent)
|
||||||
{
|
{
|
||||||
return SpawnPrefab(prefab, Transform::Identity, parent, nullptr);
|
return SpawnPrefab(prefab, Transform(Vector3::Minimum), parent, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Actor* PrefabManager::SpawnPrefab(Prefab* prefab, Actor* parent, Dictionary<Guid, const void*>* objectsCache, bool withSynchronization)
|
Actor* PrefabManager::SpawnPrefab(Prefab* prefab, Actor* parent, Dictionary<Guid, const void*>* objectsCache, bool withSynchronization)
|
||||||
{
|
{
|
||||||
return SpawnPrefab(prefab, Transform::Identity, parent, objectsCache, withSynchronization);
|
return SpawnPrefab(prefab, Transform(Vector3::Minimum), parent, objectsCache, withSynchronization);
|
||||||
}
|
}
|
||||||
|
|
||||||
Actor* PrefabManager::SpawnPrefab(Prefab* prefab, const Transform& transform, Actor* parent, Dictionary<Guid, const void*>* objectsCache, bool withSynchronization)
|
Actor* PrefabManager::SpawnPrefab(Prefab* prefab, const Transform& transform, Actor* parent, Dictionary<Guid, const void*>* objectsCache, bool withSynchronization)
|
||||||
@@ -191,7 +191,7 @@ Actor* PrefabManager::SpawnPrefab(Prefab* prefab, const Transform& transform, Ac
|
|||||||
parent->Children.Add(root);
|
parent->Children.Add(root);
|
||||||
|
|
||||||
// Move root to the right location
|
// Move root to the right location
|
||||||
if (transform != Transform::Identity)
|
if (transform.Translation != Vector3::Minimum)
|
||||||
root->SetTransform(transform);
|
root->SetTransform(transform);
|
||||||
|
|
||||||
// Link actors hierarchy
|
// Link actors hierarchy
|
||||||
|
|||||||
@@ -1334,7 +1334,8 @@ void ParticlesSystem::Job(int32 index)
|
|||||||
auto emitter = particleSystem->Emitters[track.AsEmitter.Index].Get();
|
auto emitter = particleSystem->Emitters[track.AsEmitter.Index].Get();
|
||||||
auto& data = instance.Emitters[track.AsEmitter.Index];
|
auto& data = instance.Emitters[track.AsEmitter.Index];
|
||||||
ASSERT(emitter && emitter->IsLoaded());
|
ASSERT(emitter && emitter->IsLoaded());
|
||||||
ASSERT(emitter->Capacity != 0 && emitter->Graph.Layout.Size != 0);
|
if (emitter->Capacity == 0 || emitter->Graph.Layout.Size == 0)
|
||||||
|
continue;
|
||||||
PROFILE_CPU_ASSET(emitter);
|
PROFILE_CPU_ASSET(emitter);
|
||||||
|
|
||||||
// Calculate new time position
|
// Calculate new time position
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#include "PhysicsColliderActor.h"
|
#include "PhysicsColliderActor.h"
|
||||||
#include "Engine/Scripting/Script.h"
|
|
||||||
#include "RigidBody.h"
|
#include "RigidBody.h"
|
||||||
|
|
||||||
PhysicsColliderActor::PhysicsColliderActor(const SpawnParams& params)
|
PhysicsColliderActor::PhysicsColliderActor(const SpawnParams& params)
|
||||||
|
|||||||
@@ -117,9 +117,7 @@ void SimulationEventCallback::onContact(const PxContactPairHeader& pairHeader, c
|
|||||||
{
|
{
|
||||||
// Skip sending events to removed actors
|
// Skip sending events to removed actors
|
||||||
if (pairHeader.flags & (PxContactPairHeaderFlag::eREMOVED_ACTOR_0 | PxContactPairHeaderFlag::eREMOVED_ACTOR_1))
|
if (pairHeader.flags & (PxContactPairHeaderFlag::eREMOVED_ACTOR_0 | PxContactPairHeaderFlag::eREMOVED_ACTOR_1))
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
Collision c;
|
Collision c;
|
||||||
PxContactPairExtraDataIterator j(pairHeader.extraDataStream, pairHeader.extraDataStreamSize);
|
PxContactPairExtraDataIterator j(pairHeader.extraDataStream, pairHeader.extraDataStreamSize);
|
||||||
@@ -193,7 +191,7 @@ void SimulationEventCallback::onContact(const PxContactPairHeader& pairHeader, c
|
|||||||
RemovedCollisions.Add(c);
|
RemovedCollisions.Add(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ASSERT(!j.nextItemSet());
|
//ASSERT(!j.nextItemSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimulationEventCallback::onTrigger(PxTriggerPair* pairs, PxU32 count)
|
void SimulationEventCallback::onTrigger(PxTriggerPair* pairs, PxU32 count)
|
||||||
|
|||||||
@@ -451,6 +451,7 @@ DialogResult MessageBox::Show(Window* parent, const StringView& text, const Stri
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
flags |= MB_TASKMODAL;
|
||||||
|
|
||||||
// Show dialog
|
// Show dialog
|
||||||
int result = MessageBoxW(parent ? static_cast<HWND>(parent->GetNativePtr()) : nullptr, String(text).GetText(), String(caption).GetText(), flags);
|
int result = MessageBoxW(parent ? static_cast<HWND>(parent->GetNativePtr()) : nullptr, String(text).GetText(), String(caption).GetText(), flags);
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ void DepthOfFieldPass::Render(RenderContext& renderContext, GPUTexture*& frame,
|
|||||||
{
|
{
|
||||||
DepthOfFieldSettings& dofSettings = renderContext.List->Settings.DepthOfField;
|
DepthOfFieldSettings& dofSettings = renderContext.List->Settings.DepthOfField;
|
||||||
const bool useDoF = EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::DepthOfField) && dofSettings.Enabled;
|
const bool useDoF = EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::DepthOfField) && dofSettings.Enabled;
|
||||||
if (!useDoF || _platformSupportsDoF || checkIfSkipPass())
|
if (!useDoF || !_platformSupportsDoF || checkIfSkipPass())
|
||||||
return;
|
return;
|
||||||
auto device = GPUDevice::Instance;
|
auto device = GPUDevice::Instance;
|
||||||
auto context = device->GetMainContext();
|
auto context = device->GetMainContext();
|
||||||
|
|||||||
@@ -1270,7 +1270,11 @@ bool ManagedBinaryModule::InvokeMethod(void* method, const Variant& instance, Sp
|
|||||||
|
|
||||||
// Invoke the method
|
// Invoke the method
|
||||||
MObject* exception = nullptr;
|
MObject* exception = nullptr;
|
||||||
|
#if USE_NETCORE // NetCore uses the same path for both virtual and non-virtual calls
|
||||||
|
MObject* resultObject = mMethod->Invoke(mInstance, params, &exception);
|
||||||
|
#else
|
||||||
MObject* resultObject = withInterfaces ? mMethod->InvokeVirtual((MObject*)mInstance, params, &exception) : mMethod->Invoke(mInstance, params, &exception);
|
MObject* resultObject = withInterfaces ? mMethod->InvokeVirtual((MObject*)mInstance, params, &exception) : mMethod->Invoke(mInstance, params, &exception);
|
||||||
|
#endif
|
||||||
if (exception)
|
if (exception)
|
||||||
{
|
{
|
||||||
MException ex(exception);
|
MException ex(exception);
|
||||||
|
|||||||
@@ -460,16 +460,15 @@ bool ShaderCompiler::WriteCustomDataVS(ShaderCompilationContext* context, Shader
|
|||||||
auto& element = layout[a];
|
auto& element = layout[a];
|
||||||
if (!layoutVisible[a])
|
if (!layoutVisible[a])
|
||||||
continue;
|
continue;
|
||||||
|
GPUShaderProgramVS::InputElement data;
|
||||||
// TODO: serialize whole struct?
|
data.Type = static_cast<byte>(element.Type);
|
||||||
|
data.Index = element.Index;
|
||||||
output->WriteByte(static_cast<byte>(element.Type));
|
data.Format = static_cast<byte>(element.Format);
|
||||||
output->WriteByte(element.Index);
|
data.InputSlot = element.InputSlot;
|
||||||
output->WriteByte(static_cast<byte>(element.Format));
|
data.AlignedByteOffset = element.AlignedByteOffset;
|
||||||
output->WriteByte(element.InputSlot);
|
data.InputSlotClass = element.InputSlotClass;
|
||||||
output->WriteUint32(element.AlignedByteOffset);
|
data.InstanceDataStepRate = element.InstanceDataStepRate;
|
||||||
output->WriteByte(element.InputSlotClass);
|
output->Write(data);
|
||||||
output->WriteUint32(element.InstanceDataStepRate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ ${PBXResourcesGroup}
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
HEADER_SEARCH_PATHS = ${HeaderSearchPaths};
|
HEADER_SEARCH_PATHS = "${HeaderSearchPaths}";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
@@ -275,7 +275,7 @@ ${PBXResourcesGroup}
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
HEADER_SEARCH_PATHS = ${HeaderSearchPaths};
|
HEADER_SEARCH_PATHS = "${HeaderSearchPaths}";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
|
|||||||
9
Source/ThirdParty/volk/volk.Build.cs
vendored
9
Source/ThirdParty/volk/volk.Build.cs
vendored
@@ -1,5 +1,6 @@
|
|||||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Flax.Build;
|
using Flax.Build;
|
||||||
using Flax.Build.NativeCpp;
|
using Flax.Build.NativeCpp;
|
||||||
@@ -62,4 +63,12 @@ public class volk : ThirdPartyModule
|
|||||||
Log.ErrorOnce("Missing VulkanSDK.", ref _missingSDKError);
|
Log.ErrorOnce("Missing VulkanSDK.", ref _missingSDKError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void GetFilesToDeploy(List<string> files)
|
||||||
|
{
|
||||||
|
base.GetFilesToDeploy(files);
|
||||||
|
|
||||||
|
files.Add(Path.Combine(FolderPath, "volk.h"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3135,14 +3135,17 @@ namespace Flax.Build.Bindings
|
|||||||
contents.AppendLine("#pragma once");
|
contents.AppendLine("#pragma once");
|
||||||
contents.AppendLine();
|
contents.AppendLine();
|
||||||
contents.AppendLine($"#define {binaryModuleNameUpper}_NAME \"{binaryModuleName}\"");
|
contents.AppendLine($"#define {binaryModuleNameUpper}_NAME \"{binaryModuleName}\"");
|
||||||
if (version.Build == -1)
|
if (version.Build <= 0)
|
||||||
contents.AppendLine($"#define {binaryModuleNameUpper}_VERSION Version({version.Major}, {version.Minor})");
|
contents.AppendLine($"#define {binaryModuleNameUpper}_VERSION Version({version.Major}, {version.Minor})");
|
||||||
else
|
else if (version.Revision <= 0)
|
||||||
contents.AppendLine($"#define {binaryModuleNameUpper}_VERSION Version({version.Major}, {version.Minor}, {version.Build})");
|
contents.AppendLine($"#define {binaryModuleNameUpper}_VERSION Version({version.Major}, {version.Minor}, {version.Build})");
|
||||||
|
else
|
||||||
|
contents.AppendLine($"#define {binaryModuleNameUpper}_VERSION Version({version.Major}, {version.Minor}, {version.Build}, {version.Revision})");
|
||||||
contents.AppendLine($"#define {binaryModuleNameUpper}_VERSION_TEXT \"{version}\"");
|
contents.AppendLine($"#define {binaryModuleNameUpper}_VERSION_TEXT \"{version}\"");
|
||||||
contents.AppendLine($"#define {binaryModuleNameUpper}_VERSION_MAJOR {version.Major}");
|
contents.AppendLine($"#define {binaryModuleNameUpper}_VERSION_MAJOR {version.Major}");
|
||||||
contents.AppendLine($"#define {binaryModuleNameUpper}_VERSION_MINOR {version.Minor}");
|
contents.AppendLine($"#define {binaryModuleNameUpper}_VERSION_MINOR {version.Minor}");
|
||||||
contents.AppendLine($"#define {binaryModuleNameUpper}_VERSION_BUILD {version.Build}");
|
contents.AppendLine($"#define {binaryModuleNameUpper}_VERSION_BUILD {version.Build}");
|
||||||
|
contents.AppendLine($"#define {binaryModuleNameUpper}_VERSION_REVISION {version.Revision}");
|
||||||
contents.AppendLine($"#define {binaryModuleNameUpper}_COMPANY \"{project.Company}\"");
|
contents.AppendLine($"#define {binaryModuleNameUpper}_COMPANY \"{project.Company}\"");
|
||||||
contents.AppendLine($"#define {binaryModuleNameUpper}_COPYRIGHT \"{project.Copyright}\"");
|
contents.AppendLine($"#define {binaryModuleNameUpper}_COPYRIGHT \"{project.Copyright}\"");
|
||||||
contents.AppendLine();
|
contents.AppendLine();
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ namespace Flax.Build
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Writes the JSON representation of the object.
|
/// Writes the JSON representation of the object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
|
/// <param name="writer">The <see cref="Utf8JsonWriter"/> to write to.</param>
|
||||||
/// <param name="value">The value.</param>
|
/// <param name="value">The value.</param>
|
||||||
/// <param name="serializer">The calling serializer.</param>
|
/// <param name="options">The calling serializer.</param>
|
||||||
public override void Write(Utf8JsonWriter writer, Version value, JsonSerializerOptions options)
|
public override void Write(Utf8JsonWriter writer, Version value, JsonSerializerOptions options)
|
||||||
{
|
{
|
||||||
writer.WriteStringValue(value.ToString());
|
writer.WriteStringValue(value.ToString());
|
||||||
@@ -25,73 +25,68 @@ namespace Flax.Build
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads the JSON representation of the object.
|
/// Reads the JSON representation of the object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
|
/// <param name="reader">The <see cref="Utf8JsonReader"/> to read from.</param>
|
||||||
/// <param name="objectType">Type of the object.</param>
|
/// <param name="typeToConvert">Type of the object.</param>
|
||||||
/// <param name="existingValue">The existing property value of the JSON that is being converted.</param>
|
/// <param name="options">The serializer options.</param>
|
||||||
/// <param name="serializer">The calling serializer.</param>
|
|
||||||
/// <returns>The object value.</returns>
|
/// <returns>The object value.</returns>
|
||||||
public override Version? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
public override Version? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
{
|
{
|
||||||
if (reader.TokenType == JsonTokenType.Null)
|
if (reader.TokenType == JsonTokenType.Null)
|
||||||
{
|
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
else
|
if (reader.TokenType == JsonTokenType.StartObject)
|
||||||
{
|
{
|
||||||
if (reader.TokenType == JsonTokenType.StartObject)
|
try
|
||||||
{
|
{
|
||||||
try
|
reader.Read();
|
||||||
|
var values = new Dictionary<string, int>();
|
||||||
|
while (reader.TokenType == JsonTokenType.PropertyName)
|
||||||
{
|
{
|
||||||
|
var key = reader.GetString();
|
||||||
reader.Read();
|
reader.Read();
|
||||||
Dictionary<string, int> values = new Dictionary<string, int>();
|
var val = reader.GetInt32();
|
||||||
while (reader.TokenType == JsonTokenType.PropertyName)
|
reader.Read();
|
||||||
{
|
values.Add(key, val);
|
||||||
var key = reader.GetString();
|
}
|
||||||
reader.Read();
|
|
||||||
var val = reader.GetInt32();
|
|
||||||
reader.Read();
|
|
||||||
values.Add(key, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
int major = 0, minor = 0, build = 0;
|
values.TryGetValue("Major", out var major);
|
||||||
values.TryGetValue("Major", out major);
|
values.TryGetValue("Minor", out var minor);
|
||||||
values.TryGetValue("Minor", out minor);
|
if (!values.TryGetValue("Build", out var build))
|
||||||
values.TryGetValue("Build", out build);
|
build = -1;
|
||||||
|
if (!values.TryGetValue("Revision", out var revision))
|
||||||
|
revision = -1;
|
||||||
|
|
||||||
Version v = new Version(major, minor, build);
|
if (build <= 0)
|
||||||
return v;
|
return new Version(major, minor);
|
||||||
}
|
if (revision <= 0)
|
||||||
catch (Exception ex)
|
return new Version(major, minor, build);
|
||||||
{
|
return new Version(major, minor, build, revision);
|
||||||
throw new Exception(String.Format("Error parsing version string: {0}", reader.GetString()), ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (reader.TokenType == JsonTokenType.String)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
try
|
throw new Exception(string.Format("Error parsing version string: {0}", reader.GetString()), ex);
|
||||||
{
|
|
||||||
Version v = new Version((string)reader.GetString()!);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception(String.Format("Error parsing version string: {0}", reader.GetString()), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception(String.Format("Unexpected token or value when parsing version. Token: {0}, Value: {1}", reader.TokenType, reader.GetString()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reader.TokenType == JsonTokenType.String)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return new Version((string)reader.GetString()!);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception(string.Format("Error parsing version string: {0}", reader.GetString()), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception(string.Format("Unexpected token or value when parsing version. Token: {0}, Value: {1}", reader.TokenType, reader.GetString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether this instance can convert the specified object type.
|
/// Determines whether this instance can convert the specified object type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="objectType">Type of the object.</param>
|
/// <param name="objectType">Type of the object.</param>
|
||||||
/// <returns>
|
/// <returns><c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.</returns>
|
||||||
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
|
|
||||||
/// </returns>
|
|
||||||
public override bool CanConvert(Type objectType)
|
public override bool CanConvert(Type objectType)
|
||||||
{
|
{
|
||||||
return objectType == typeof(Version);
|
return objectType == typeof(Version);
|
||||||
@@ -318,7 +313,7 @@ namespace Flax.Build
|
|||||||
Log.Verbose("Loading project file from \"" + path + "\"...");
|
Log.Verbose("Loading project file from \"" + path + "\"...");
|
||||||
var contents = File.ReadAllText(path);
|
var contents = File.ReadAllText(path);
|
||||||
var project = JsonSerializer.Deserialize<ProjectInfo>(contents.AsSpan(),
|
var project = JsonSerializer.Deserialize<ProjectInfo>(contents.AsSpan(),
|
||||||
new JsonSerializerOptions() { Converters = { new FlaxVersionConverter() }, IncludeFields = true, TypeInfoResolver = ProjectInfoSourceGenerationContext.Default });
|
new JsonSerializerOptions() { Converters = { new FlaxVersionConverter() }, IncludeFields = true, TypeInfoResolver = ProjectInfoSourceGenerationContext.Default });
|
||||||
project.ProjectPath = path;
|
project.ProjectPath = path;
|
||||||
project.ProjectFolderPath = Path.GetDirectoryName(path);
|
project.ProjectFolderPath = Path.GetDirectoryName(path);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user