Merge branch 'master' into Visject-ImprovedNodeSearching

This commit is contained in:
Nils Hausfeld
2023-10-28 16:49:22 +02:00
20 changed files with 178 additions and 193 deletions
Binary file not shown.
Binary file not shown.
+2 -1
View File
@@ -3,7 +3,8 @@
"Version": {
"Major": 1,
"Minor": 7,
"Build": 6402
"Revision": 0,
"Build": 6404
},
"Company": "Flax",
"Copyright": "Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.",
+2 -1
View File
@@ -154,7 +154,8 @@ bool ProjectInfo::LoadProject(const String& projectPath)
Version = ::Version(
JsonTools::GetInt(version, "Major", 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)
+37 -48
View File
@@ -23,17 +23,11 @@ namespace FlaxEditor
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value == null)
{
writer.WriteNull();
}
else if (value is Version)
{
writer.WriteValue(value.ToString());
}
else
{
throw new JsonSerializationException("Expected Version object value");
}
}
/// <summary>
@@ -47,65 +41,60 @@ namespace FlaxEditor
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.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();
Dictionary<string, int> values = new Dictionary<string, int>();
while (reader.TokenType == JsonToken.PropertyName)
{
var key = reader.Value as string;
reader.Read();
var val = (long)reader.Value;
reader.Read();
values.Add(key, (int)val);
}
var val = (long)reader.Value;
reader.Read();
values.Add(key, (int)val);
}
int major = 0, minor = 0, build = 0;
values.TryGetValue("Major", out major);
values.TryGetValue("Minor", out minor);
values.TryGetValue("Build", out build);
values.TryGetValue("Major", out var major);
values.TryGetValue("Minor", out var minor);
if (!values.TryGetValue("Build", out var build))
build = -1;
if (!values.TryGetValue("Revision", out var revision))
revision = -1;
Version v = new Version(major, minor, build);
return v;
}
catch (Exception ex)
{
throw new Exception(String.Format("Error parsing version string: {0}", reader.Value), ex);
}
if (build <= 0)
return new Version(major, minor);
if (revision <= 0)
return new Version(major, minor, build);
return new Version(major, minor, build, revision);
}
else if (reader.TokenType == JsonToken.String)
catch (Exception ex)
{
try
{
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));
throw new Exception(String.Format("Error parsing version string: {0}", reader.Value), ex);
}
}
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>
/// Determines whether this instance can convert the specified object type.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <returns>
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
/// </returns>
/// <returns><c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.</returns>
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Version);
+3 -3
View File
@@ -7,15 +7,15 @@ Version::Version(int32 major, int32 minor, int32 build, int32 revision)
{
_major = Math::Max(major, 0);
_minor = Math::Max(minor, 0);
_build = Math::Max(build, 0);
_revision = Math::Max(revision, 0);
_build = Math::Max(build, -1);
_revision = Math::Max(revision, -1);
}
Version::Version(int32 major, int32 minor, int32 build)
{
_major = Math::Max(major, 0);
_minor = Math::Max(minor, 0);
_build = Math::Max(build, 0);
_build = Math::Max(build, -1);
_revision = -1;
}
+2 -1
View File
@@ -1302,7 +1302,8 @@ namespace FlaxEngine.Interop
#if !USE_AOT
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>();
if (!method.IsStatic)
+2
View File
@@ -313,6 +313,8 @@ bool GPUDevice::Init()
_res->TasksManager.SetExecutor(CreateTasksExecutor());
LOG(Info, "Total graphics memory: {0}", Utilities::BytesToText(TotalGraphicsMemory));
if (!Limits.HasCompute)
LOG(Warning, "Compute Shaders are not supported");
return false;
}
+10 -1
View File
@@ -87,7 +87,11 @@ bool GPUShader::Create(MemoryReadStream& stream)
GPUShaderProgramInitializer initializer;
#if !BUILD_RELEASE
initializer.Owner = this;
const StringView name = GetName();
#else
const StringView name;
#endif
const bool hasCompute = GPUDevice::Instance->Limits.HasCompute;
for (int32 i = 0; i < shadersCount; i++)
{
const ShaderStage type = static_cast<ShaderStage>(stream.ReadByte());
@@ -117,10 +121,15 @@ bool GPUShader::Create(MemoryReadStream& stream)
stream.ReadBytes(&initializer.Bindings, sizeof(ShaderBindings));
// 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);
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;
}
@@ -122,6 +122,19 @@ public:
/// </summary>
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:
/// <summary>
/// Gets input layout description handle (platform dependent).
@@ -15,32 +15,21 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
{
case ShaderStage::Vertex:
{
D3D11_INPUT_ELEMENT_DESC inputLayoutDesc[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
byte inputLayoutSize;
stream.ReadByte(&inputLayoutSize);
ASSERT(inputLayoutSize <= VERTEX_SHADER_MAX_INPUT_ELEMENTS);
D3D11_INPUT_ELEMENT_DESC inputLayoutDesc[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
for (int32 a = 0; a < inputLayoutSize; a++)
{
// Read description
// TODO: maybe use struct and load at once?
stream.ReadByte(&Type);
stream.ReadByte(&Index);
stream.ReadByte(&Format);
stream.ReadByte(&InputSlot);
stream.ReadUint32(&AlignedByteOffset);
stream.ReadByte(&InputSlotClass);
stream.ReadUint32(&InstanceDataStepRate);
GPUShaderProgramVS::InputElement inputElement;
stream.Read(inputElement);
// Get semantic name
const char* semanticName = nullptr;
// TODO: maybe use enum+mapping ?
switch (Type)
switch (inputElement.Type)
{
case 1:
semanticName = "POSITION";
@@ -70,7 +59,7 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
semanticName = "BLENDWEIGHT";
break;
default:
LOG(Fatal, "Invalid vertex shader element semantic type: {0}", Type);
LOG(Fatal, "Invalid vertex shader element semantic type: {0}", inputElement.Type);
break;
}
@@ -78,12 +67,12 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
inputLayoutDesc[a] =
{
semanticName,
static_cast<UINT>(Index),
static_cast<DXGI_FORMAT>(Format),
static_cast<UINT>(InputSlot),
static_cast<UINT>(AlignedByteOffset),
static_cast<D3D11_INPUT_CLASSIFICATION>(InputSlotClass),
static_cast<UINT>(InstanceDataStepRate)
static_cast<UINT>(inputElement.Index),
static_cast<DXGI_FORMAT>(inputElement.Format),
static_cast<UINT>(inputElement.InputSlot),
static_cast<UINT>(inputElement.AlignedByteOffset),
static_cast<D3D11_INPUT_CLASSIFICATION>(inputElement.InputSlotClass),
static_cast<UINT>(inputElement.InstanceDataStepRate)
};
}
@@ -20,32 +20,21 @@ GPUShaderProgram* GPUShaderDX12::CreateGPUShaderProgram(ShaderStage type, const
{
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)
byte inputLayoutSize;
stream.ReadByte(&inputLayoutSize);
ASSERT(inputLayoutSize <= VERTEX_SHADER_MAX_INPUT_ELEMENTS);
D3D12_INPUT_ELEMENT_DESC inputLayout[VERTEX_SHADER_MAX_INPUT_ELEMENTS];
for (int32 a = 0; a < inputLayoutSize; a++)
{
// Read description
// TODO: maybe use struct and load at once?
stream.ReadByte(&Type);
stream.ReadByte(&Index);
stream.ReadByte(&Format);
stream.ReadByte(&InputSlot);
stream.ReadUint32(&AlignedByteOffset);
stream.ReadByte(&InputSlotClass);
stream.ReadUint32(&InstanceDataStepRate);
GPUShaderProgramVS::InputElement inputElement;
stream.Read(inputElement);
// Get semantic name
const char* semanticName = nullptr;
// TODO: maybe use enum+mapping ?
switch (Type)
switch (inputElement.Type)
{
case 1:
semanticName = "POSITION";
@@ -75,7 +64,7 @@ GPUShaderProgram* GPUShaderDX12::CreateGPUShaderProgram(ShaderStage type, const
semanticName = "BLENDWEIGHT";
break;
default:
LOG(Fatal, "Invalid vertex shader element semantic type: {0}", Type);
LOG(Fatal, "Invalid vertex shader element semantic type: {0}", inputElement.Type);
break;
}
@@ -83,12 +72,12 @@ GPUShaderProgram* GPUShaderDX12::CreateGPUShaderProgram(ShaderStage type, const
inputLayout[a] =
{
semanticName,
static_cast<UINT>(Index),
static_cast<DXGI_FORMAT>(Format),
static_cast<UINT>(InputSlot),
static_cast<UINT>(AlignedByteOffset),
static_cast<D3D12_INPUT_CLASSIFICATION>(InputSlotClass),
static_cast<UINT>(InstanceDataStepRate)
static_cast<UINT>(inputElement.Index),
static_cast<DXGI_FORMAT>(inputElement.Format),
static_cast<UINT>(inputElement.InputSlot),
static_cast<UINT>(inputElement.AlignedByteOffset),
static_cast<D3D12_INPUT_CLASSIFICATION>(inputElement.InputSlotClass),
static_cast<UINT>(inputElement.InstanceDataStepRate)
};
}
@@ -14,9 +14,9 @@
#include "Engine/Graphics/PixelFormatExtensions.h"
#if PLATFORM_DESKTOP
#define VULKAN_UNIFORM_RING_BUFFER_SIZE 24 * 1024 * 1024
#define VULKAN_UNIFORM_RING_BUFFER_SIZE (24 * 1024 * 1024)
#else
#define VULKAN_UNIFORM_RING_BUFFER_SIZE 8 * 1024 * 1024
#define VULKAN_UNIFORM_RING_BUFFER_SIZE (8 * 1024 * 1024)
#endif
UniformBufferUploaderVulkan::UniformBufferUploaderVulkan(GPUDeviceVulkan* device)
@@ -153,10 +153,6 @@ GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, cons
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)
byte inputLayoutSize;
stream.ReadByte(&inputLayoutSize);
@@ -167,32 +163,26 @@ GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, cons
for (int32 a = 0; a < inputLayoutSize; a++)
{
// Read description
// TODO: maybe use struct and load at once?
stream.ReadByte(&Type);
stream.ReadByte(&Index);
stream.ReadByte(&Format);
stream.ReadByte(&InputSlot);
stream.ReadUint32(&AlignedByteOffset);
stream.ReadByte(&InputSlotClass);
stream.ReadUint32(&InstanceDataStepRate);
GPUShaderProgramVS::InputElement inputElement;
stream.Read(inputElement);
const auto size = PixelFormatExtensions::SizeInBytes((PixelFormat)Format);
if (AlignedByteOffset != INPUT_LAYOUT_ELEMENT_ALIGN)
offset = AlignedByteOffset;
const auto size = PixelFormatExtensions::SizeInBytes((PixelFormat)inputElement.Format);
if (inputElement.AlignedByteOffset != INPUT_LAYOUT_ELEMENT_ALIGN)
offset = inputElement.AlignedByteOffset;
auto& vertexBindingDescription = vertexBindingDescriptions[InputSlot];
vertexBindingDescription.binding = InputSlot;
auto& vertexBindingDescription = vertexBindingDescriptions[inputElement.InputSlot];
vertexBindingDescription.binding = inputElement.InputSlot;
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;
ASSERT(InstanceDataStepRate == 0 || InstanceDataStepRate == 1);
vertexBindingDescription.inputRate = inputElement.InputSlotClass == INPUT_LAYOUT_ELEMENT_PER_VERTEX_DATA ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
ASSERT(inputElement.InstanceDataStepRate == 0 || inputElement.InstanceDataStepRate == 1);
auto& vertexAttributeDescription = vertexAttributeDescriptions[a];
vertexAttributeDescription.location = a;
vertexAttributeDescription.binding = InputSlot;
vertexAttributeDescription.format = RenderToolsVulkan::ToVulkanFormat((PixelFormat)Format);
vertexAttributeDescription.binding = inputElement.InputSlot;
vertexAttributeDescription.format = RenderToolsVulkan::ToVulkanFormat((PixelFormat)inputElement.Format);
vertexAttributeDescription.offset = offset;
bindingsCount = Math::Max(bindingsCount, (uint32)InputSlot + 1);
bindingsCount = Math::Max(bindingsCount, (uint32)inputElement.InputSlot + 1);
offset += size;
}
+2 -1
View File
@@ -1334,7 +1334,8 @@ void ParticlesSystem::Job(int32 index)
auto emitter = particleSystem->Emitters[track.AsEmitter.Index].Get();
auto& data = instance.Emitters[track.AsEmitter.Index];
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);
// Calculate new time position
@@ -1,7 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
#include "PhysicsColliderActor.h"
#include "Engine/Scripting/Script.h"
#include "RigidBody.h"
PhysicsColliderActor::PhysicsColliderActor(const SpawnParams& params)
+4
View File
@@ -1270,7 +1270,11 @@ bool ManagedBinaryModule::InvokeMethod(void* method, const Variant& instance, Sp
// Invoke the method
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);
#endif
if (exception)
{
MException ex(exception);
@@ -460,16 +460,15 @@ bool ShaderCompiler::WriteCustomDataVS(ShaderCompilationContext* context, Shader
auto& element = layout[a];
if (!layoutVisible[a])
continue;
// TODO: serialize whole struct?
output->WriteByte(static_cast<byte>(element.Type));
output->WriteByte(element.Index);
output->WriteByte(static_cast<byte>(element.Format));
output->WriteByte(element.InputSlot);
output->WriteUint32(element.AlignedByteOffset);
output->WriteByte(element.InputSlotClass);
output->WriteUint32(element.InstanceDataStepRate);
GPUShaderProgramVS::InputElement data;
data.Type = static_cast<byte>(element.Type);
data.Index = element.Index;
data.Format = static_cast<byte>(element.Format);
data.InputSlot = element.InputSlot;
data.AlignedByteOffset = element.AlignedByteOffset;
data.InputSlotClass = element.InputSlotClass;
data.InstanceDataStepRate = element.InstanceDataStepRate;
output->Write(data);
}
return false;
@@ -222,7 +222,7 @@ ${PBXResourcesGroup}
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = ${HeaderSearchPaths};
HEADER_SEARCH_PATHS = "${HeaderSearchPaths}";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
@@ -275,7 +275,7 @@ ${PBXResourcesGroup}
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = ${HeaderSearchPaths};
HEADER_SEARCH_PATHS = "${HeaderSearchPaths}";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
@@ -3135,14 +3135,17 @@ namespace Flax.Build.Bindings
contents.AppendLine("#pragma once");
contents.AppendLine();
contents.AppendLine($"#define {binaryModuleNameUpper}_NAME \"{binaryModuleName}\"");
if (version.Build == -1)
if (version.Build <= 0)
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})");
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_MAJOR {version.Major}");
contents.AppendLine($"#define {binaryModuleNameUpper}_VERSION_MINOR {version.Minor}");
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}_COPYRIGHT \"{project.Copyright}\"");
contents.AppendLine();
+44 -49
View File
@@ -14,9 +14,9 @@ namespace Flax.Build
/// <summary>
/// Writes the JSON representation of the object.
/// </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="serializer">The calling serializer.</param>
/// <param name="options">The calling serializer.</param>
public override void Write(Utf8JsonWriter writer, Version value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
@@ -25,73 +25,68 @@ namespace Flax.Build
/// <summary>
/// Reads the JSON representation of the object.
/// </summary>
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
/// <param name="objectType">Type of the object.</param>
/// <param name="existingValue">The existing property value of the JSON that is being converted.</param>
/// <param name="serializer">The calling serializer.</param>
/// <param name="reader">The <see cref="Utf8JsonReader"/> to read from.</param>
/// <param name="typeToConvert">Type of the object.</param>
/// <param name="options">The serializer options.</param>
/// <returns>The object value.</returns>
public override Version? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.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();
Dictionary<string, int> values = new Dictionary<string, int>();
while (reader.TokenType == JsonTokenType.PropertyName)
{
var key = reader.GetString();
reader.Read();
var val = reader.GetInt32();
reader.Read();
values.Add(key, val);
}
var val = reader.GetInt32();
reader.Read();
values.Add(key, val);
}
int major = 0, minor = 0, build = 0;
values.TryGetValue("Major", out major);
values.TryGetValue("Minor", out minor);
values.TryGetValue("Build", out build);
values.TryGetValue("Major", out var major);
values.TryGetValue("Minor", out var minor);
if (!values.TryGetValue("Build", out var build))
build = -1;
if (!values.TryGetValue("Revision", out var revision))
revision = -1;
Version v = new Version(major, minor, build);
return v;
}
catch (Exception ex)
{
throw new Exception(String.Format("Error parsing version string: {0}", reader.GetString()), ex);
}
if (build <= 0)
return new Version(major, minor);
if (revision <= 0)
return new Version(major, minor, build);
return new Version(major, minor, build, revision);
}
else if (reader.TokenType == JsonTokenType.String)
catch (Exception ex)
{
try
{
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()));
throw new Exception(string.Format("Error parsing version string: {0}", reader.GetString()), ex);
}
}
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>
/// Determines whether this instance can convert the specified object type.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <returns>
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
/// </returns>
/// <returns><c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.</returns>
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Version);
@@ -318,7 +313,7 @@ namespace Flax.Build
Log.Verbose("Loading project file from \"" + path + "\"...");
var contents = File.ReadAllText(path);
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.ProjectFolderPath = Path.GetDirectoryName(path);