diff --git a/Content/Shaders/BitonicSort.flax b/Content/Shaders/BitonicSort.flax
index 1d5b8a581..c9dd81dc9 100644
--- a/Content/Shaders/BitonicSort.flax
+++ b/Content/Shaders/BitonicSort.flax
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f46a61cf8d5183230176e661a51208bfeece16cc7238655f406288ff448af64e
-size 6721
+oid sha256:0c780dc1881ef96dece237bde3e87fca3c9e4e542d89ebde7c9308f00f81c6a9
+size 6808
diff --git a/Flax.flaxproj b/Flax.flaxproj
index cc643346f..681c1dc55 100644
--- a/Flax.flaxproj
+++ b/Flax.flaxproj
@@ -3,7 +3,7 @@
"Version": {
"Major": 1,
"Minor": 1,
- "Build": 6217
+ "Build": 6218
},
"Company": "Flax",
"Copyright": "Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.",
diff --git a/Flax.sln.DotSettings b/Flax.sln.DotSettings
index b940e9c03..c91a48bfe 100644
--- a/Flax.sln.DotSettings
+++ b/Flax.sln.DotSettings
@@ -234,6 +234,7 @@
Deprecated
(?<=\W|^)(?<TAG>\[Deprecated)(\W|$)(.*)
Normal
+ True
True
True
True
diff --git a/Source/Editor/Content/Create/SettingsCreateEntry.cs b/Source/Editor/Content/Create/SettingsCreateEntry.cs
index 369cc01e5..974de76cc 100644
--- a/Source/Editor/Content/Create/SettingsCreateEntry.cs
+++ b/Source/Editor/Content/Create/SettingsCreateEntry.cs
@@ -53,6 +53,11 @@ namespace FlaxEditor.Content.Create
///
NavigationSettings,
+ ///
+ /// The localization settings.
+ ///
+ LocalizationSettings,
+
///
/// The build settings.
///
@@ -92,6 +97,11 @@ namespace FlaxEditor.Content.Create
/// The Android settings
///
AndroidPlatformSettings,
+
+ ///
+ /// The Switch settings
+ ///
+ SwitchPlatformSettings,
}
private static readonly Type[] _types =
@@ -103,6 +113,7 @@ namespace FlaxEditor.Content.Create
typeof(PhysicsSettings),
typeof(GraphicsSettings),
typeof(NavigationSettings),
+ typeof(LocalizationSettings),
typeof(BuildSettings),
typeof(InputSettings),
typeof(WindowsPlatformSettings),
@@ -111,6 +122,7 @@ namespace FlaxEditor.Content.Create
TypeUtils.GetManagedType(GameSettings.PS4PlatformSettingsTypename),
TypeUtils.GetManagedType(GameSettings.XboxScarlettPlatformSettingsTypename),
typeof(AndroidPlatformSettings),
+ TypeUtils.GetManagedType(GameSettings.SwitchPlatformSettingsTypename),
};
///
diff --git a/Source/Editor/Content/Import/ImportFileEntry.cs b/Source/Editor/Content/Import/ImportFileEntry.cs
index 80cab94d3..5d21d3726 100644
--- a/Source/Editor/Content/Import/ImportFileEntry.cs
+++ b/Source/Editor/Content/Import/ImportFileEntry.cs
@@ -116,8 +116,7 @@ namespace FlaxEditor.Content.Import
if (FileTypes.TryGetValue(extension, out ImportFileEntryHandler createDelegate))
return createDelegate(ref request);
- // Use default type
- return request.IsBinaryAsset ? new AssetImportEntry(ref request) : new ImportFileEntry(ref request);
+ return request.IsInBuilt ? new AssetImportEntry(ref request) : new ImportFileEntry(ref request);
}
internal static void RegisterDefaultTypes()
diff --git a/Source/Editor/Content/Import/Request.cs b/Source/Editor/Content/Import/Request.cs
index b9da30afb..d38b0bfd0 100644
--- a/Source/Editor/Content/Import/Request.cs
+++ b/Source/Editor/Content/Import/Request.cs
@@ -21,9 +21,9 @@ namespace FlaxEditor.Content.Import
public string OutputPath;
///
- /// Flag set to true for binary assets handled by the engine internally.
+ /// Flag set to true for the assets handled by the engine internally.
///
- public bool IsBinaryAsset;
+ public bool IsInBuilt;
///
/// Flag used to skip showing import settings dialog to used. Can be used for importing assets from code by plugins.
diff --git a/Source/Editor/Content/Items/VisualScriptItem.cs b/Source/Editor/Content/Items/VisualScriptItem.cs
index 22f1d75cc..e2a390b60 100644
--- a/Source/Editor/Content/Items/VisualScriptItem.cs
+++ b/Source/Editor/Content/Items/VisualScriptItem.cs
@@ -75,6 +75,7 @@ namespace FlaxEditor.Content
}
}
+ ///
public int MetadataToken => 0;
///
diff --git a/Source/Editor/Content/Proxy/JsonAssetProxy.cs b/Source/Editor/Content/Proxy/JsonAssetProxy.cs
index 25155d39d..41cc06ee1 100644
--- a/Source/Editor/Content/Proxy/JsonAssetProxy.cs
+++ b/Source/Editor/Content/Proxy/JsonAssetProxy.cs
@@ -2,7 +2,6 @@
using System;
using FlaxEditor.Content.Create;
-using FlaxEditor.Content.Settings;
using FlaxEditor.CustomEditors;
using FlaxEditor.CustomEditors.Editors;
using FlaxEditor.Windows;
@@ -45,18 +44,12 @@ namespace FlaxEditor.Content
///
public override bool IsProxyFor(ContentItem item)
{
- return item is JsonAssetItem;
+ return item is JsonAssetItem json && json.TypeName == TypeName;
}
///
public override Color AccentColor => Color.FromRGB(0xd14f67);
- ///
- public override bool AcceptsAsset(string typeName, string path)
- {
- return typeName == TypeName && base.AcceptsAsset(typeName, path);
- }
-
///
public override AssetItem ConstructItem(string path, string typeName, ref Guid id)
{
@@ -143,6 +136,12 @@ namespace FlaxEditor.Content
return path.EndsWith(FileExtension, StringComparison.OrdinalIgnoreCase);
}
+ ///
+ public override bool IsProxyFor(ContentItem item)
+ {
+ return item is JsonAssetItem;
+ }
+
///
public override bool CanCreate(ContentFolder targetLocation)
{
diff --git a/Source/Editor/Content/Proxy/LocalizedStringTableProxy.cs b/Source/Editor/Content/Proxy/LocalizedStringTableProxy.cs
new file mode 100644
index 000000000..2e15f9543
--- /dev/null
+++ b/Source/Editor/Content/Proxy/LocalizedStringTableProxy.cs
@@ -0,0 +1,24 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+using FlaxEditor.Windows;
+using FlaxEditor.Windows.Assets;
+using FlaxEngine;
+
+namespace FlaxEditor.Content
+{
+ ///
+ /// proxy.
+ ///
+ ///
+ public class LocalizedStringTableProxy : JsonAssetProxy
+ {
+ ///
+ public override EditorWindow Open(Editor editor, ContentItem item)
+ {
+ return new LocalizedStringTableWindow(editor, (JsonAssetItem)item);
+ }
+
+ ///
+ public override string TypeName => "FlaxEngine.LocalizedStringTable";
+ }
+}
diff --git a/Source/Editor/Cooker/CookingData.h b/Source/Editor/Cooker/CookingData.h
index 56b15af23..77774a9df 100644
--- a/Source/Editor/Cooker/CookingData.h
+++ b/Source/Editor/Cooker/CookingData.h
@@ -7,6 +7,7 @@
#include "Engine/Core/Collections/Array.h"
#include "Engine/Core/Collections/HashSet.h"
#include "Engine/Core/Collections/Dictionary.h"
+#include "Engine/Core/Types/Guid.h"
class GameCooker;
class PlatformTools;
@@ -87,34 +88,14 @@ API_ENUM() enum class BuildPlatform
///
API_ENUM(Attributes="EditorDisplay(null, \"Android ARM64 (arm64-v8a)\")")
AndroidARM64 = 9,
+
+ ///
+ /// Switch.
+ ///
+ Switch = 10,
};
-inline const Char* ToString(const BuildPlatform platform)
-{
- switch (platform)
- {
- case BuildPlatform::Windows32:
- return TEXT("Windows x86");
- case BuildPlatform::Windows64:
- return TEXT("Windows x64");
- case BuildPlatform::UWPx86:
- return TEXT("Windows Store x86");
- case BuildPlatform::UWPx64:
- return TEXT("Windows Store x64");
- case BuildPlatform::XboxOne:
- return TEXT("Xbox One");
- case BuildPlatform::LinuxX64:
- return TEXT("Linux x64");
- case BuildPlatform::PS4:
- return TEXT("PlayStation 4");
- case BuildPlatform::XboxScarlett:
- return TEXT("Xbox Scarlett");
- case BuildPlatform::AndroidARM64:
- return TEXT("Android ARM64");
- default:
- return TEXT("?");
- }
-}
+extern FLAXENGINE_API const Char* ToString(const BuildPlatform platform);
///
/// Game build configuration modes.
@@ -137,20 +118,7 @@ API_ENUM() enum class BuildConfiguration
Release = 2,
};
-inline const Char* ToString(const BuildConfiguration configuration)
-{
- switch (configuration)
- {
- case BuildConfiguration::Debug:
- return TEXT("Debug");
- case BuildConfiguration::Development:
- return TEXT("Development");
- case BuildConfiguration::Release:
- return TEXT("Release");
- default:
- return TEXT("?");
- }
-}
+extern FLAXENGINE_API const Char* ToString(const BuildConfiguration configuration);
#define BUILD_STEP_CANCEL_CHECK if (GameCooker::IsCancelRequested()) return true
@@ -185,9 +153,14 @@ struct FLAXENGINE_API CookingData
String OriginalOutputPath;
///
- /// The output path.
+ /// The output path for data files (Content, Mono, etc.).
///
- String OutputPath;
+ String DataOutputPath;
+
+ ///
+ /// The output path for binaries (executable and code libraries).
+ ///
+ String CodeOutputPath;
///
/// The platform tools.
diff --git a/Source/Editor/Cooker/GameCooker.cpp b/Source/Editor/Cooker/GameCooker.cpp
index 9eca81eba..c50b10572 100644
--- a/Source/Editor/Cooker/GameCooker.cpp
+++ b/Source/Editor/Cooker/GameCooker.cpp
@@ -39,7 +39,6 @@
#endif
#if PLATFORM_TOOLS_PS4
#include "Platforms/PS4/Editor/PlatformTools/PS4PlatformTools.h"
-#include "Platforms/PS4/Engine/Platform/PS4PlatformSettings.h"
#endif
#if PLATFORM_TOOLS_XBOX_SCARLETT
#include "Platforms/XboxScarlett/Editor/PlatformTools/XboxScarlettPlatformTools.h"
@@ -47,6 +46,9 @@
#if PLATFORM_TOOLS_ANDROID
#include "Platform/Android/AndroidPlatformTools.h"
#endif
+#if PLATFORM_TOOLS_SWITCH
+#include "Platforms/Switch/Editor/PlatformTools/SwitchPlatformTools.h"
+#endif
namespace GameCookerImpl
{
@@ -89,6 +91,50 @@ using namespace GameCookerImpl;
Delegate GameCooker::OnEvent;
Delegate GameCooker::OnProgress;
+const Char* ToString(const BuildPlatform platform)
+{
+ switch (platform)
+ {
+ case BuildPlatform::Windows32:
+ return TEXT("Windows x86");
+ case BuildPlatform::Windows64:
+ return TEXT("Windows x64");
+ case BuildPlatform::UWPx86:
+ return TEXT("Windows Store x86");
+ case BuildPlatform::UWPx64:
+ return TEXT("Windows Store x64");
+ case BuildPlatform::XboxOne:
+ return TEXT("Xbox One");
+ case BuildPlatform::LinuxX64:
+ return TEXT("Linux x64");
+ case BuildPlatform::PS4:
+ return TEXT("PlayStation 4");
+ case BuildPlatform::XboxScarlett:
+ return TEXT("Xbox Scarlett");
+ case BuildPlatform::AndroidARM64:
+ return TEXT("Android ARM64");
+ case BuildPlatform::Switch:
+ return TEXT("Switch");
+ default:
+ return TEXT("?");
+ }
+}
+
+const Char* ToString(const BuildConfiguration configuration)
+{
+ switch (configuration)
+ {
+ case BuildConfiguration::Debug:
+ return TEXT("Debug");
+ case BuildConfiguration::Development:
+ return TEXT("Development");
+ case BuildConfiguration::Release:
+ return TEXT("Release");
+ default:
+ return TEXT("?");
+ }
+}
+
bool CookingData::AssetTypeStatistics::operator<(const AssetTypeStatistics& other) const
{
if (ContentSize != other.ContentSize)
@@ -250,6 +296,11 @@ PlatformTools* GameCooker::GetTools(BuildPlatform platform)
case BuildPlatform::AndroidARM64:
result = New(ArchitectureType::ARM64);
break;
+#endif
+#if PLATFORM_TOOLS_SWITCH
+ case BuildPlatform::Switch:
+ result = New();
+ break;
#endif
}
Tools.Add(platform, result);
@@ -282,9 +333,10 @@ void GameCooker::Build(BuildPlatform platform, BuildConfiguration configuration,
data.Configuration = configuration;
data.Options = options;
data.CustomDefines = customDefines;
- data.OutputPath = outputPath;
- FileSystem::NormalizePath(data.OutputPath);
- data.OutputPath = data.OriginalOutputPath = FileSystem::ConvertRelativePathToAbsolute(Globals::ProjectFolder, data.OutputPath);
+ data.OriginalOutputPath = outputPath;
+ FileSystem::NormalizePath(data.OriginalOutputPath);
+ data.OriginalOutputPath = FileSystem::ConvertRelativePathToAbsolute(Globals::ProjectFolder, data.OriginalOutputPath);
+ data.CodeOutputPath = data.DataOutputPath = data.OriginalOutputPath;
data.CacheDirectory = Globals::ProjectCacheFolder / TEXT("Cooker") / tools->GetName();
if (!FileSystem::DirectoryExists(data.CacheDirectory))
{
@@ -367,7 +419,7 @@ bool GameCookerImpl::Build()
CookingData& data = Data;
LOG(Info, "Starting Game Cooker...");
LOG(Info, "Platform: {0}, Configuration: {2}, Options: {1}", ::ToString(data.Platform), (int32)data.Options, ::ToString(data.Configuration));
- LOG(Info, "Output Path: {0}", data.OutputPath);
+ LOG(Info, "Output Path: {0}", data.OriginalOutputPath);
// Late init feature
if (Steps.IsEmpty())
diff --git a/Source/Editor/Cooker/Platform/Android/AndroidPlatformTools.cpp b/Source/Editor/Cooker/Platform/Android/AndroidPlatformTools.cpp
index fcc53f26a..3987fcb4a 100644
--- a/Source/Editor/Cooker/Platform/Android/AndroidPlatformTools.cpp
+++ b/Source/Editor/Cooker/Platform/Android/AndroidPlatformTools.cpp
@@ -104,7 +104,8 @@ PixelFormat AndroidPlatformTools::GetTextureFormat(CookingData& data, TextureBas
void AndroidPlatformTools::OnBuildStarted(CookingData& data)
{
// Adjust the cooking output folder to be located inside the Gradle assets directory
- data.OutputPath /= TEXT("app/assets");
+ data.DataOutputPath /= TEXT("app/assets");
+ data.CodeOutputPath /= TEXT("app/assets");
PlatformTools::OnBuildStarted(data);
}
@@ -114,7 +115,7 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
const auto gameSettings = GameSettings::Get();
const auto platformSettings = AndroidPlatformSettings::Get();
const auto platformDataPath = data.GetPlatformBinariesRoot();
- const auto assetsPath = data.OutputPath;
+ const auto assetsPath = data.DataOutputPath;
const auto jniLibsPath = data.OriginalOutputPath / TEXT("app/jniLibs");
const auto projectVersion = Editor::Project->Version.ToString();
const Char* abi;
diff --git a/Source/Editor/Cooker/Platform/Linux/LinuxPlatformTools.cpp b/Source/Editor/Cooker/Platform/Linux/LinuxPlatformTools.cpp
index 69521e172..57562f537 100644
--- a/Source/Editor/Cooker/Platform/Linux/LinuxPlatformTools.cpp
+++ b/Source/Editor/Cooker/Platform/Linux/LinuxPlatformTools.cpp
@@ -38,7 +38,7 @@ bool LinuxPlatformTools::OnDeployBinaries(CookingData& data)
{
const auto gameSettings = GameSettings::Get();
const auto platformSettings = LinuxPlatformSettings::Get();
- const auto outputPath = data.OutputPath;
+ const auto outputPath = data.DataOutputPath;
// Copy binaries
{
diff --git a/Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp b/Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp
index 7a6d6ad84..e6516bf67 100644
--- a/Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp
+++ b/Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp
@@ -25,7 +25,7 @@ bool UWPPlatformTools::OnScriptsStepDone(CookingData& data)
{
// Override Newtonsoft.Json.dll for some platforms (that don't support runtime code generation)
const String customBinPath = data.GetPlatformBinariesRoot() / TEXT("Newtonsoft.Json.dll");
- const String assembliesPath = data.OutputPath;
+ const String assembliesPath = data.CodeOutputPath;
if (FileSystem::CopyFile(assembliesPath / TEXT("Newtonsoft.Json.dll"), customBinPath))
{
data.Error(TEXT("Failed to copy deploy custom assembly."));
@@ -64,7 +64,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
return true;
}
- if (FileSystem::CopyFile(data.OutputPath / StringUtils::GetFileName(files[i]), files[i]))
+ if (FileSystem::CopyFile(data.DataOutputPath / StringUtils::GetFileName(files[i]), files[i]))
{
data.Error(TEXT("Failed to setup output directory."));
return true;
@@ -92,7 +92,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
// Prepare certificate
const auto srcCertificatePath = Globals::ProjectFolder / platformSettings->CertificateLocation;
- const auto dstCertificatePath = data.OutputPath / TEXT("WSACertificate.pfx");
+ const auto dstCertificatePath = data.DataOutputPath / TEXT("WSACertificate.pfx");
if (platformSettings->CertificateLocation.HasChars() && FileSystem::FileExists(srcCertificatePath))
{
// Use cert from settings
@@ -115,7 +115,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
}
// Copy assets
- const auto dstAssetsPath = data.OutputPath / TEXT("Assets");
+ const auto dstAssetsPath = data.DataOutputPath / TEXT("Assets");
const auto srcAssetsPath = uwpDataPath / TEXT("Assets");
if (!FileSystem::DirectoryExists(dstAssetsPath))
{
@@ -125,7 +125,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
return true;
}
}
- const auto dstPropertiesPath = data.OutputPath / TEXT("Properties");
+ const auto dstPropertiesPath = data.DataOutputPath / TEXT("Properties");
if (!FileSystem::DirectoryExists(dstPropertiesPath))
{
if (FileSystem::CreateDirectory(dstPropertiesPath))
@@ -176,7 +176,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
return true;
}
}
- const auto dstAppPath = data.OutputPath / TEXT("App.cs");
+ const auto dstAppPath = data.DataOutputPath / TEXT("App.cs");
const auto srcAppPath = uwpDataPath / TEXT("App.cs");
if (!FileSystem::FileExists(dstAppPath))
{
@@ -205,7 +205,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
return true;
}
}
- const auto dstFlaxGeneratedPath = data.OutputPath / TEXT("FlaxGenerated.cs");
+ const auto dstFlaxGeneratedPath = data.DataOutputPath / TEXT("FlaxGenerated.cs");
const auto srcFlaxGeneratedPath = uwpDataPath / TEXT("FlaxGenerated.cs");
{
// Get template
@@ -264,7 +264,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
}
// Create solution
- const auto dstSolutionPath = data.OutputPath / projectName + TEXT(".sln");
+ const auto dstSolutionPath = data.DataOutputPath / projectName + TEXT(".sln");
const auto srcSolutionPath = uwpDataPath / TEXT("Solution.sln");
if (!FileSystem::FileExists(dstSolutionPath))
{
@@ -297,7 +297,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
}
// Create project
- const auto dstProjectPath = data.OutputPath / projectName + TEXT(".csproj");
+ const auto dstProjectPath = data.DataOutputPath / projectName + TEXT(".csproj");
const auto srcProjectPath = uwpDataPath / TEXT("Project.csproj");
{
// Get template
@@ -347,7 +347,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
}
// Create manifest
- const auto dstManifestPath = data.OutputPath / TEXT("Package.appxmanifest");
+ const auto dstManifestPath = data.DataOutputPath / TEXT("Package.appxmanifest");
const auto srcManifestPath = uwpDataPath / TEXT("Package.appxmanifest");
if (!FileSystem::FileExists(dstManifestPath))
{
@@ -484,8 +484,8 @@ bool UWPPlatformTools::OnPostProcess(CookingData& data)
// Special case for UWP
// FlaxEngine.dll cannot be added to the solution as `Content` item (due to conflicts with C++ /CX FlaxEngine.dll)
// Use special directory for it (generated UWP project handles this case and copies lib to the output)
- const String assembliesPath = data.OutputPath;
- const auto dstPath1 = data.OutputPath / TEXT("DataSecondary");
+ const String assembliesPath = data.DataOutputPath;
+ const auto dstPath1 = data.DataOutputPath / TEXT("DataSecondary");
if (!FileSystem::DirectoryExists(dstPath1))
{
if (FileSystem::CreateDirectory(dstPath1))
diff --git a/Source/Editor/Cooker/Platform/Windows/WindowsPlatformTools.cpp b/Source/Editor/Cooker/Platform/Windows/WindowsPlatformTools.cpp
index 348930dd5..d5dc1c933 100644
--- a/Source/Editor/Cooker/Platform/Windows/WindowsPlatformTools.cpp
+++ b/Source/Editor/Cooker/Platform/Windows/WindowsPlatformTools.cpp
@@ -36,7 +36,7 @@ ArchitectureType WindowsPlatformTools::GetArchitecture() const
bool WindowsPlatformTools::OnDeployBinaries(CookingData& data)
{
const auto platformSettings = WindowsPlatformSettings::Get();
- const auto& outputPath = data.OutputPath;
+ const auto& outputPath = data.CodeOutputPath;
// Apply executable icon
Array files;
diff --git a/Source/Editor/Cooker/PlatformTools.h b/Source/Editor/Cooker/PlatformTools.h
index c98c008bc..20d578d2e 100644
--- a/Source/Editor/Cooker/PlatformTools.h
+++ b/Source/Editor/Cooker/PlatformTools.h
@@ -144,8 +144,8 @@ public:
AotConfig(CookingData& data)
{
Platform::GetEnvironmentVariables(EnvVars);
- EnvVars[TEXT("MONO_PATH")] = data.OutputPath / TEXT("Mono/lib/mono/4.5");
- AssembliesSearchDirs.Add(data.OutputPath / TEXT("Mono/lib/mono/4.5"));
+ EnvVars[TEXT("MONO_PATH")] = data.DataOutputPath / TEXT("Mono/lib/mono/4.5");
+ AssembliesSearchDirs.Add(data.DataOutputPath / TEXT("Mono/lib/mono/4.5"));
}
};
diff --git a/Source/Editor/Cooker/Steps/CompileScriptsStep.cpp b/Source/Editor/Cooker/Steps/CompileScriptsStep.cpp
index c5c585f60..5d3125960 100644
--- a/Source/Editor/Cooker/Steps/CompileScriptsStep.cpp
+++ b/Source/Editor/Cooker/Steps/CompileScriptsStep.cpp
@@ -119,7 +119,7 @@ bool CompileScriptsStep::DeployBinaries(CookingData& data, const String& path, c
}
for (auto& file : files)
{
- const String dst = data.OutputPath / StringUtils::GetFileName(file);
+ const String dst = data.CodeOutputPath / StringUtils::GetFileName(file);
if (dst != file && FileSystem::CopyFile(dst, file))
{
data.Error(TEXT("Failed to copy file from {0} to {1}."), file, dst);
@@ -180,7 +180,12 @@ bool CompileScriptsStep::Perform(CookingData& data)
platform = TEXT("Android");
architecture = TEXT("ARM64");
break;
+ case BuildPlatform::Switch:
+ platform = TEXT("Switch");
+ architecture = TEXT("ARM64");
+ break;
default:
+ LOG(Error, "Unknown or unsupported build platform.");
return true;
}
_extensionsToSkip.Clear();
@@ -289,7 +294,7 @@ bool CompileScriptsStep::Perform(CookingData& data)
}
writer.EndObject();
- const String outputBuildInfo = data.OutputPath / TEXT("Game.Build.json");
+ const String outputBuildInfo = data.CodeOutputPath / TEXT("Game.Build.json");
if (File::WriteAllBytes(outputBuildInfo, (byte*)buffer.GetString(), (int32)buffer.GetSize()))
{
LOG(Error, "Failed to save binary modules info file {0}.", outputBuildInfo);
diff --git a/Source/Editor/Cooker/Steps/CookAssetsStep.cpp b/Source/Editor/Cooker/Steps/CookAssetsStep.cpp
index 84f2ec8f3..90d5bfd55 100644
--- a/Source/Editor/Cooker/Steps/CookAssetsStep.cpp
+++ b/Source/Editor/Cooker/Steps/CookAssetsStep.cpp
@@ -453,6 +453,14 @@ bool ProcessShaderBase(CookAssetsStep::AssetCookData& data, ShaderAssetBase* ass
COMPILE_PROFILE(Vulkan_SM5, SHADER_FILE_CHUNK_INTERNAL_VULKAN_SM5_CACHE);
break;
}
+#endif
+#if PLATFORM_TOOLS_SWITCH
+ case BuildPlatform::Switch:
+ {
+ const char* platformDefineName = "PLATFORM_SWITCH";
+ COMPILE_PROFILE(Vulkan_SM5, SHADER_FILE_CHUNK_INTERNAL_VULKAN_SM5_CACHE);
+ break;
+ }
#endif
default:
{
@@ -861,7 +869,7 @@ public:
// Create package
// Note: FlaxStorage::Create overrides chunks locations in file so don't use files anymore (only readonly)
const String localPath = String::Format(TEXT("Content/Data_{0}.{1}"), _packageIndex, PACKAGE_FILES_EXTENSION);
- const String path = data.OutputPath / localPath;
+ const String path = data.DataOutputPath / localPath;
if (FlaxStorage::Create(path, assetsData, false, &CustomData))
{
data.Error(TEXT("Failed to create assets package."));
@@ -1027,7 +1035,7 @@ bool CookAssetsStep::Perform(CookingData& data)
gameFlags |= GameHeaderFlags::ShowSplashScreen;
// Open file
- auto stream = FileWriteStream::Open(data.OutputPath / TEXT("Content/head"));
+ auto stream = FileWriteStream::Open(data.DataOutputPath / TEXT("Content/head"));
if (stream == nullptr)
{
data.Error(TEXT("Failed to create game data file."));
@@ -1121,7 +1129,7 @@ bool CookAssetsStep::Perform(CookingData& data)
BUILD_STEP_CANCEL_CHECK;
// Save assets cache
- if (AssetsCache::Save(data.OutputPath / TEXT("Content/AssetsCache.dat"), AssetsRegistry, AssetPathsMapping, AssetsCacheFlags::RelativePaths))
+ if (AssetsCache::Save(data.DataOutputPath / TEXT("Content/AssetsCache.dat"), AssetsRegistry, AssetPathsMapping, AssetsCacheFlags::RelativePaths))
{
data.Error(TEXT("Failed to create assets registry."));
return true;
diff --git a/Source/Editor/Cooker/Steps/DeployDataStep.cpp b/Source/Editor/Cooker/Steps/DeployDataStep.cpp
index f90658cab..ab7f3a7b2 100644
--- a/Source/Editor/Cooker/Steps/DeployDataStep.cpp
+++ b/Source/Editor/Cooker/Steps/DeployDataStep.cpp
@@ -15,7 +15,7 @@ bool DeployDataStep::Perform(CookingData& data)
const auto gameSettings = GameSettings::Get();
// Setup output folders and copy required data
- const auto contentDir = data.OutputPath / TEXT("Content");
+ const auto contentDir = data.DataOutputPath / TEXT("Content");
if (FileSystem::DirectoryExists(contentDir))
{
// Remove old content files
@@ -26,7 +26,7 @@ bool DeployDataStep::Perform(CookingData& data)
}
FileSystem::CreateDirectory(contentDir);
const auto srcMono = depsRoot / TEXT("Mono");
- const auto dstMono = data.OutputPath / TEXT("Mono");
+ const auto dstMono = data.DataOutputPath / TEXT("Mono");
if (!FileSystem::DirectoryExists(dstMono))
{
if (!FileSystem::DirectoryExists(srcMono))
diff --git a/Source/Editor/Cooker/Steps/PrecompileAssembliesStep.cpp b/Source/Editor/Cooker/Steps/PrecompileAssembliesStep.cpp
index 4c482c529..6e5fe50a7 100644
--- a/Source/Editor/Cooker/Steps/PrecompileAssembliesStep.cpp
+++ b/Source/Editor/Cooker/Steps/PrecompileAssembliesStep.cpp
@@ -24,7 +24,7 @@ bool PrecompileAssembliesStep::Perform(CookingData& data)
data.Tools->OnConfigureAOT(data, config);
// Prepare output directory
- config.AotCachePath = data.OutputPath / TEXT("Mono/lib/mono/aot-cache");
+ config.AotCachePath = data.DataOutputPath / TEXT("Mono/lib/mono/aot-cache");
switch (data.Tools->GetArchitecture())
{
case ArchitectureType::x86:
@@ -52,9 +52,9 @@ bool PrecompileAssembliesStep::Perform(CookingData& data)
FileSystem::DirectoryGetFiles(config.Assemblies, dir, TEXT("*.dll"), DirectorySearchOption::TopDirectoryOnly);
for (auto& binaryModule : data.BinaryModules)
if (binaryModule.ManagedPath.HasChars())
- config.Assemblies.Add(data.OutputPath / binaryModule.ManagedPath);
+ config.Assemblies.Add(data.CodeOutputPath / binaryModule.ManagedPath);
// TODO: move AOT to Flax.Build and perform it on all C# assemblies used in target build
- config.Assemblies.Add(data.OutputPath / TEXT("Newtonsoft.Json.dll"));
+ config.Assemblies.Add(data.CodeOutputPath / TEXT("Newtonsoft.Json.dll"));
// Perform AOT for the assemblies
for (int32 i = 0; i < config.Assemblies.Count(); i++)
diff --git a/Source/Editor/Cooker/Steps/ValidateStep.cpp b/Source/Editor/Cooker/Steps/ValidateStep.cpp
index 915f7839d..a64317496 100644
--- a/Source/Editor/Cooker/Steps/ValidateStep.cpp
+++ b/Source/Editor/Cooker/Steps/ValidateStep.cpp
@@ -11,9 +11,17 @@ bool ValidateStep::Perform(CookingData& data)
data.StepProgress(TEXT("Performing validation"), 0);
// Ensure output and cache directories exist
- if (!FileSystem::DirectoryExists(data.OutputPath))
+ if (!FileSystem::DirectoryExists(data.CodeOutputPath))
{
- if (FileSystem::CreateDirectory(data.OutputPath))
+ if (FileSystem::CreateDirectory(data.CodeOutputPath))
+ {
+ data.Error(TEXT("Failed to create build output directory."));
+ return true;
+ }
+ }
+ if (!FileSystem::DirectoryExists(data.DataOutputPath))
+ {
+ if (FileSystem::CreateDirectory(data.DataOutputPath))
{
data.Error(TEXT("Failed to create build output directory."));
return true;
diff --git a/Source/Editor/CustomEditors/CustomEditor.cs b/Source/Editor/CustomEditors/CustomEditor.cs
index c5c628755..ca45652b9 100644
--- a/Source/Editor/CustomEditors/CustomEditor.cs
+++ b/Source/Editor/CustomEditors/CustomEditor.cs
@@ -250,6 +250,15 @@ namespace FlaxEditor.CustomEditors
_children[i].RefreshInternal();
}
+ ///
+ /// Synchronizes the value of the container. Called during Refresh to flush property after editing it in UI.
+ ///
+ /// The value to set.
+ protected virtual void SynchronizeValue(object value)
+ {
+ _values.Set(_parent.Values, value);
+ }
+
internal virtual void RefreshInternal()
{
if (_values == null)
@@ -264,7 +273,7 @@ namespace FlaxEditor.CustomEditors
_valueToSet = null;
// Assign value
- _values.Set(_parent.Values, val);
+ SynchronizeValue(val);
// Propagate values up (eg. when member of structure gets modified, also structure should be updated as a part of the other object)
var obj = _parent;
diff --git a/Source/Editor/CustomEditors/CustomEditorPresenter.cs b/Source/Editor/CustomEditors/CustomEditorPresenter.cs
index 7f19de195..be7b4de5c 100644
--- a/Source/Editor/CustomEditors/CustomEditorPresenter.cs
+++ b/Source/Editor/CustomEditors/CustomEditorPresenter.cs
@@ -139,7 +139,7 @@ namespace FlaxEditor.CustomEditors
///
protected override void OnModified()
{
- Presenter.Modified?.Invoke();
+ Presenter.OnModified();
base.OnModified();
}
@@ -354,6 +354,14 @@ namespace FlaxEditor.CustomEditors
ExpandGroups(this, false);
}
+ ///
+ /// Invokes event.
+ ///
+ public void OnModified()
+ {
+ Modified?.Invoke();
+ }
+
///
/// Called when selection gets changed.
///
diff --git a/Source/Editor/CustomEditors/Dedicated/LocalizationSettingsEditor.cs b/Source/Editor/CustomEditors/Dedicated/LocalizationSettingsEditor.cs
new file mode 100644
index 000000000..521b844ec
--- /dev/null
+++ b/Source/Editor/CustomEditors/Dedicated/LocalizationSettingsEditor.cs
@@ -0,0 +1,429 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using FlaxEditor.Content.Settings;
+using FlaxEditor.CustomEditors.Editors;
+using FlaxEditor.Scripting;
+using FlaxEngine;
+using FlaxEngine.GUI;
+using FlaxEngine.Utilities;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Object = FlaxEngine.Object;
+
+namespace FlaxEditor.CustomEditors.Dedicated
+{
+ [CustomEditor(typeof(LocalizationSettings))]
+ sealed class LocalizationSettingsEditor : GenericEditor
+ {
+ private CultureInfo _theMostTranslatedCulture;
+ private int _theMostTranslatedCultureCount;
+
+ ///
+ public override void Initialize(LayoutElementsContainer layout)
+ {
+ Profiler.BeginEvent("LocalizationSettingsEditor.Initialize");
+ var settings = (LocalizationSettings)Values[0];
+ var tablesLength = settings.LocalizedStringTables?.Length ?? 0;
+ var tables = new List(tablesLength);
+ for (int i = 0; i < tablesLength; i++)
+ {
+ var table = settings.LocalizedStringTables[i];
+ if (table && !table.WaitForLoaded())
+ tables.Add(table);
+ }
+ var locales = tables.GroupBy(x => x.Locale);
+ var tableEntries = new Dictionary>();
+ var allKeys = new HashSet();
+ foreach (var e in locales)
+ {
+ foreach (var table in e)
+ {
+ var entries = table.Entries;
+ tableEntries[table] = entries;
+ allKeys.AddRange(entries.Keys);
+ }
+ }
+
+ {
+ var group = layout.Group("Preview");
+
+ // Current language and culture preview management
+ group.Object("Current Language", new CustomValueContainer(new ScriptType(typeof(CultureInfo)), Localization.CurrentLanguage, (instance, index) => Localization.CurrentLanguage, (instance, index, value) => Localization.CurrentLanguage = value as CultureInfo), null, "Current UI display language for the game preview.");
+ group.Object("Current Culture", new CustomValueContainer(new ScriptType(typeof(CultureInfo)), Localization.CurrentCulture, (instance, index) => Localization.CurrentCulture, (instance, index, value) => Localization.CurrentCulture = value as CultureInfo), null, "Current values formatting culture for the game preview.");
+ }
+
+ {
+ var group = layout.Group("Locales");
+
+ // Show all existing locales
+ _theMostTranslatedCulture = null;
+ _theMostTranslatedCultureCount = -1;
+ foreach (var e in locales)
+ {
+ var culture = new CultureInfo(e.Key);
+ var prop = group.AddPropertyItem(CultureInfoEditor.GetName(culture), culture.NativeName);
+ int count = e.Sum(x => tableEntries[x].Count);
+ int validCount = e.Sum(x => tableEntries[x].Values.Count(y => y != null && y.Length != 0 && !string.IsNullOrEmpty(y[0])));
+ if (count > _theMostTranslatedCultureCount)
+ {
+ _theMostTranslatedCulture = culture;
+ _theMostTranslatedCultureCount = count;
+ }
+ prop.Label(string.Format("Progress: {0}% ({1}/{2})", (int)(((float)validCount / allKeys.Count * 100.0f)), validCount, allKeys.Count));
+ prop.Label("Tables:");
+ foreach (var table in e)
+ {
+ var namePath = table.Path;
+ if (namePath.StartsWith(Globals.ProjectFolder))
+ namePath = namePath.Substring(Globals.ProjectFolder.Length + 1);
+ var tableLabel = prop.ClickableLabel(namePath).CustomControl;
+ tableLabel.TextColorHighlighted = Color.Wheat;
+ tableLabel.DoubleClick += delegate { Editor.Instance.Windows.ContentWin.Select(table); };
+ }
+ group.Space(10);
+ }
+
+ // Update add button
+ var update = group.Button("Update").Button;
+ update.TooltipText = "Refreshes the dashboard statistics";
+ update.Height = 16.0f;
+ update.Clicked += RebuildLayout;
+
+ // New locale add button
+ var addLocale = group.Button("Add Locale...").Button;
+ addLocale.TooltipText = "Shows a locale picker and creates new localization for it with not translated string tables";
+ addLocale.Height = 16.0f;
+ addLocale.ButtonClicked += delegate(Button button)
+ {
+ var menu = CultureInfoEditor.CreatePicker(null, culture =>
+ {
+ var displayName = CultureInfoEditor.GetName(culture);
+ if (locales.Any(x => x.Key == culture.Name))
+ {
+ MessageBox.Show($"Culture '{displayName}' is already added.");
+ return;
+ }
+ Profiler.BeginEvent("LocalizationSettingsEditor.AddLocale");
+ Editor.Log($"Adding culture '{displayName}' to localization settings");
+ var newTables = settings.LocalizedStringTables.ToList();
+ if (_theMostTranslatedCulture != null)
+ {
+ // Duplicate localization for culture with the highest amount of keys
+ var g = locales.First(x => x.Key == _theMostTranslatedCulture.Name);
+ foreach (var e in g)
+ {
+ var path = e.Path;
+ var filename = Path.GetFileNameWithoutExtension(path);
+ if (filename.EndsWith(_theMostTranslatedCulture.Name))
+ filename = filename.Substring(0, filename.Length - _theMostTranslatedCulture.Name.Length);
+ path = Path.Combine(Path.GetDirectoryName(path), filename + culture.Name + ".json");
+ var table = FlaxEngine.Content.CreateVirtualAsset();
+ table.Locale = culture.Name;
+ var entries = new Dictionary();
+ foreach (var ee in tableEntries[e])
+ {
+ var vv = (string[])ee.Value.Clone();
+ for (var i = 0; i < vv.Length; i++)
+ vv[i] = string.Empty;
+ entries.Add(ee.Key, vv);
+ }
+ table.Entries = entries;
+ if (!table.Save(path))
+ {
+ Object.Destroy(table);
+ newTables.Add(FlaxEngine.Content.LoadAsync(path));
+ }
+ }
+ }
+ else
+ {
+ // No localization so initialize with empty table
+ var path = Path.Combine(Path.Combine(Path.GetDirectoryName(GameSettings.Load().Localization.Path), "Localization", culture.Name + ".json"));
+ var table = FlaxEngine.Content.CreateVirtualAsset();
+ table.Locale = culture.Name;
+ if (!table.Save(path))
+ {
+ Object.Destroy(table);
+ newTables.Add(FlaxEngine.Content.LoadAsync(path));
+ }
+ }
+ settings.LocalizedStringTables = newTables.ToArray();
+ Presenter.OnModified();
+ RebuildLayout();
+ Profiler.EndEvent();
+ });
+ menu.Show(button, new Vector2(0, button.Height));
+ };
+
+ // Export button
+ var exportLocalization = group.Button("Export...").Button;
+ exportLocalization.TooltipText = "Exports the localization strings into .pot file for translation";
+ exportLocalization.Height = 16.0f;
+ exportLocalization.Clicked += delegate
+ {
+ if (FileSystem.ShowSaveFileDialog(null, null, "*.pot", false, "Export localization for translation to .pot file", out var filenames))
+ return;
+ Profiler.BeginEvent("LocalizationSettingsEditor.Export");
+ if (!filenames[0].EndsWith(".pot"))
+ filenames[0] += ".pot";
+ var nplurals = 1;
+ foreach (var e in tableEntries)
+ {
+ foreach (var value in e.Value.Values)
+ {
+ if (value != null && value.Length > nplurals)
+ nplurals = value.Length;
+ }
+ }
+ using (var writer = new StreamWriter(filenames[0], false, Encoding.UTF8))
+ {
+ writer.WriteLine("msgid \"\"");
+ writer.WriteLine("msgstr \"\"");
+ writer.WriteLine("\"Language: English\\n\"");
+ writer.WriteLine("\"MIME-Version: 1.0\\n\"");
+ writer.WriteLine("\"Content-Type: text/plain; charset=UTF-8\\n\"");
+ writer.WriteLine("\"Content-Transfer-Encoding: 8bit\\n\"");
+ writer.WriteLine($"\"Plural-Forms: nplurals={nplurals}; plural=(n != 1);\\n\"");
+ writer.WriteLine("\"X-Generator: FlaxEngine\\n\"");
+ var written = new HashSet();
+ foreach (var e in tableEntries)
+ {
+ foreach (var pair in e.Value)
+ {
+ if (written.Contains(pair.Key))
+ continue;
+ written.Add(pair.Key);
+
+ writer.WriteLine("");
+ writer.WriteLine($"msgid \"{pair.Key}\"");
+ if (pair.Value == null || pair.Value.Length < 2)
+ {
+ writer.WriteLine("msgstr \"\"");
+ }
+ else
+ {
+ writer.WriteLine("msgid_plural \"\"");
+ for (int i = 0; i < pair.Value.Length; i++)
+ writer.WriteLine($"msgstr[{i}] \"\"");
+ }
+ }
+ if (written.Count == allKeys.Count)
+ break;
+ }
+ }
+ Profiler.EndEvent();
+ };
+
+ // Find localized strings in code button
+ var findStringsCode = group.Button("Find localized strings in code").Button;
+ findStringsCode.TooltipText = "Searches for localized string usage in inside a project source files";
+ findStringsCode.Height = 16.0f;
+ findStringsCode.Clicked += delegate
+ {
+ var newKeys = new Dictionary();
+ Profiler.BeginEvent("LocalizationSettingsEditor.FindLocalizedStringsInSource");
+
+ // C#
+ var files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.cs", SearchOption.AllDirectories);
+ var filesCount = files.Length;
+ foreach (var file in files)
+ FindNewKeysCSharp(file, newKeys, allKeys);
+
+ // C++
+ files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.cpp", SearchOption.AllDirectories);
+ filesCount += files.Length;
+ foreach (var file in files)
+ FindNewKeysCpp(file, newKeys, allKeys);
+ files = Directory.GetFiles(Globals.ProjectSourceFolder, "*.h", SearchOption.AllDirectories);
+ filesCount += files.Length;
+ foreach (var file in files)
+ FindNewKeysCpp(file, newKeys, allKeys);
+
+ AddNewKeys(newKeys, filesCount, locales, tableEntries);
+ Profiler.EndEvent();
+ };
+
+ // Find localized strings in content button
+ var findStringsContent = group.Button("Find localized strings in content").Button;
+ findStringsContent.TooltipText = "Searches for localized string usage in inside a project content files (scenes, prefabs)";
+ findStringsContent.Height = 16.0f;
+ findStringsContent.Clicked += delegate
+ {
+ var newKeys = new Dictionary();
+ Profiler.BeginEvent("LocalizationSettingsEditor.FindLocalizedStringsInContent");
+
+ // Scenes
+ var files = Directory.GetFiles(Globals.ProjectContentFolder, "*.scene", SearchOption.AllDirectories);
+ var filesCount = files.Length;
+ foreach (var file in files)
+ FindNewKeysJson(file, newKeys, allKeys);
+
+ // Prefabs
+ files = Directory.GetFiles(Globals.ProjectContentFolder, "*.prefab", SearchOption.AllDirectories);
+ filesCount += files.Length;
+ foreach (var file in files)
+ FindNewKeysJson(file, newKeys, allKeys);
+
+ AddNewKeys(newKeys, filesCount, locales, tableEntries);
+ Profiler.EndEvent();
+ };
+ }
+
+ {
+ // Raw asset data editing
+ var group = layout.Group("Data");
+ base.Initialize(group);
+ }
+
+ Profiler.EndEvent();
+ }
+
+ private static void FindNewKeysCSharp(string file, Dictionary newKeys, HashSet allKeys)
+ {
+ var startToken = "Localization.GetString";
+ var textToken = "\"";
+ FindNewKeys(file, newKeys, allKeys, startToken, textToken);
+ }
+
+ private static void FindNewKeysCpp(string file, Dictionary newKeys, HashSet allKeys)
+ {
+ var startToken = "Localization::GetString";
+ var textToken = "TEXT(\"";
+ FindNewKeys(file, newKeys, allKeys, startToken, textToken);
+ }
+
+ private static void FindNewKeys(string file, Dictionary newKeys, HashSet allKeys, string startToken, string textToken)
+ {
+ var contents = File.ReadAllText(file);
+ var idx = contents.IndexOf(startToken);
+ while (idx != -1)
+ {
+ idx += startToken.Length + 1;
+ int braces = 1;
+ int start = idx;
+ while (idx < contents.Length && braces != 0)
+ {
+ if (contents[idx] == '(')
+ braces++;
+ if (contents[idx] == ')')
+ braces--;
+ idx++;
+ }
+ if (idx == contents.Length)
+ break;
+ var inside = contents.Substring(start, idx - start - 1);
+ var textStart = inside.IndexOf(textToken);
+ if (textStart != -1)
+ {
+ textStart += textToken.Length;
+ var textEnd = textStart;
+ while (textEnd < inside.Length && inside[textEnd] != '\"')
+ {
+ if (inside[textEnd] == '\\')
+ textEnd++;
+ textEnd++;
+ }
+ var id = inside.Substring(textStart, textEnd - textStart);
+ textStart = inside.Length > textEnd + 2 ? inside.IndexOf(textToken, textEnd + 2) : -1;
+ string value = null;
+ if (textStart != -1)
+ {
+ textStart += textToken.Length;
+ textEnd = textStart;
+ while (textEnd < inside.Length && inside[textEnd] != '\"')
+ {
+ if (inside[textEnd] == '\\')
+ textEnd++;
+ textEnd++;
+ }
+ value = inside.Substring(textStart, textEnd - textStart);
+ }
+
+ if (!allKeys.Contains(id))
+ newKeys[id] = value;
+ }
+
+ idx = contents.IndexOf(startToken, idx);
+ }
+ }
+
+ private static void FindNewKeysJson(Dictionary newKeys, HashSet allKeys, JToken token)
+ {
+ if (token is JObject o)
+ {
+ foreach (var p in o)
+ {
+ if (string.Equals(p.Key, "Id", StringComparison.Ordinal) && p.Value is JValue i && i.Value is string id && !allKeys.Contains(id))
+ {
+ var count = o.Properties().Count();
+ if (count == 1)
+ {
+ newKeys[id] = null;
+ return;
+ }
+ if (count == 2)
+ {
+ var v = o.Property("Value")?.Value as JValue;
+ if (v?.Value is string value)
+ {
+ newKeys[id] = value;
+ return;
+ }
+ }
+ }
+ FindNewKeysJson(newKeys, allKeys, p.Value);
+ }
+ }
+ else if (token is JArray a)
+ {
+ foreach (var p in a)
+ {
+ FindNewKeysJson(newKeys, allKeys, p);
+ }
+ }
+ }
+
+ private static void FindNewKeysJson(string file, Dictionary newKeys, HashSet allKeys)
+ {
+ using (var reader = new StreamReader(file))
+ using (var jsonReader = new JsonTextReader(reader))
+ {
+ var token = JToken.ReadFrom(jsonReader);
+ FindNewKeysJson(newKeys, allKeys, token);
+ }
+ }
+
+ private void AddNewKeys(Dictionary newKeys, int filesCount, IEnumerable> locales, Dictionary> tableEntries)
+ {
+ Editor.Log($"Found {newKeys.Count} new localized strings in {filesCount} files");
+ if (newKeys.Count == 0)
+ return;
+ foreach (var e in newKeys)
+ Editor.Log(e.Key + (e.Value != null ? " = " + e.Value : string.Empty));
+ foreach (var locale in locales)
+ {
+ var table = locale.First();
+ var entries = tableEntries[table];
+ if (table.Locale == "en")
+ {
+ foreach (var e in newKeys)
+ entries[e.Key] = new[] { e.Value };
+ }
+ else
+ {
+ foreach (var e in newKeys)
+ entries[e.Key] = new[] { string.Empty };
+ }
+ table.Entries = entries;
+ table.Save();
+ }
+ RebuildLayout();
+ }
+ }
+}
diff --git a/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs b/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
index e176f2b70..dcd70a340 100644
--- a/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
@@ -32,17 +32,13 @@ namespace FlaxEditor.CustomEditors.Dedicated
if (_presets != value)
{
_presets = value;
- OnPresetsChanged();
+ TooltipText = CustomEditorsUtil.GetPropertyNameUI(_presets.ToString());
}
}
}
public bool IsSelected;
-
- private void OnPresetsChanged()
- {
- TooltipText = CustomEditorsUtil.GetPropertyNameUI(_presets.ToString());
- }
+ public bool SupportsShiftModulation;
///
public override void Draw()
@@ -79,6 +75,11 @@ namespace FlaxEditor.CustomEditors.Dedicated
borderColor = BorderColorHighlighted;
}
+ if (SupportsShiftModulation && Input.GetKey(KeyboardKeys.Shift))
+ {
+ backgroundColor = BackgroundColorSelected;
+ }
+
// Calculate fill area
float fillSize = rect.Width / 3;
Rectangle fillArea;
@@ -154,24 +155,83 @@ namespace FlaxEditor.CustomEditors.Dedicated
{
Render2D.DrawRectangle(rect, style.BackgroundSelected.AlphaMultiplied(0.8f), 1.1f);
}
+
+ // Draw pivot point
+ if (SupportsShiftModulation && Input.GetKey(KeyboardKeys.Control))
+ {
+ Vector2 pivotPoint;
+ switch (_presets)
+ {
+ case AnchorPresets.Custom:
+ pivotPoint = Vector2.Minimum;
+ break;
+ case AnchorPresets.TopLeft:
+ pivotPoint = new Vector2(0, 0);
+ break;
+ case AnchorPresets.TopCenter:
+ case AnchorPresets.HorizontalStretchTop:
+ pivotPoint = new Vector2(rect.Width / 2, 0);
+ break;
+ case AnchorPresets.TopRight:
+ pivotPoint = new Vector2(rect.Width, 0);
+ break;
+ case AnchorPresets.MiddleLeft:
+ case AnchorPresets.VerticalStretchLeft:
+ pivotPoint = new Vector2(0, rect.Height / 2);
+ break;
+ case AnchorPresets.MiddleCenter:
+ case AnchorPresets.VerticalStretchCenter:
+ case AnchorPresets.HorizontalStretchMiddle:
+ case AnchorPresets.StretchAll:
+ pivotPoint = new Vector2(rect.Width / 2, rect.Height / 2);
+ break;
+ case AnchorPresets.MiddleRight:
+ case AnchorPresets.VerticalStretchRight:
+ pivotPoint = new Vector2(rect.Width, rect.Height / 2);
+ break;
+ case AnchorPresets.BottomLeft:
+ pivotPoint = new Vector2(0, rect.Height);
+ break;
+ case AnchorPresets.BottomCenter:
+ case AnchorPresets.HorizontalStretchBottom:
+ pivotPoint = new Vector2(rect.Width / 2, rect.Height);
+ break;
+ case AnchorPresets.BottomRight:
+ pivotPoint = new Vector2(rect.Width, rect.Height);
+ break;
+ default: throw new ArgumentOutOfRangeException();
+ }
+ var pivotPointSize = new Vector2(3.0f);
+ Render2D.DrawRectangle(new Rectangle(pivotPoint - pivotPointSize * 0.5f, pivotPointSize), style.ProgressNormal, 1.1f);
+ }
}
}
- class AnchorPresetsEditorPopup : ContextMenuBase
+ ///
+ /// Context menu for anchors presets editing.
+ ///
+ ///
+ public sealed class AnchorPresetsEditorPopup : ContextMenuBase
{
const float ButtonsMargin = 10.0f;
const float ButtonsMarginStretch = 8.0f;
const float ButtonsSize = 32.0f;
const float TitleHeight = 23.0f;
+ const float InfoHeight = 23.0f;
const float DialogWidth = ButtonsSize * 4 + ButtonsMargin * 5 + ButtonsMarginStretch;
- const float DialogHeight = TitleHeight + ButtonsSize * 4 + ButtonsMargin * 5 + ButtonsMarginStretch;
+ const float DialogHeight = TitleHeight + InfoHeight + ButtonsSize * 4 + ButtonsMargin * 5 + ButtonsMarginStretch;
+
+ private readonly bool _supportsShiftModulation;
///
/// Initializes a new instance of the class.
///
/// The initial value.
- public AnchorPresetsEditorPopup(AnchorPresets presets)
+ /// If the popup should react to shift
+ public AnchorPresetsEditorPopup(AnchorPresets presets, bool supportsShiftModulation = true)
{
+ _supportsShiftModulation = supportsShiftModulation;
+
var style = FlaxEngine.GUI.Style.Current;
Tag = presets;
Size = new Vector2(DialogWidth, DialogHeight);
@@ -184,9 +244,17 @@ namespace FlaxEditor.CustomEditors.Dedicated
Parent = this
};
+ // Info
+ var info = new Label(0, title.Bottom, DialogWidth, InfoHeight)
+ {
+ Font = new FontReference(style.FontSmall),
+ Text = "Shift: also set bounds\nControl: also set pivot",
+ Parent = this
+ };
+
// Buttons
var buttonsX = ButtonsMargin;
- var buttonsY = title.Bottom + ButtonsMargin;
+ var buttonsY = info.Bottom + ButtonsMargin;
var buttonsSpacingX = ButtonsSize + ButtonsMargin;
var buttonsSpacingY = ButtonsSize + ButtonsMargin;
//
@@ -219,6 +287,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
Parent = this,
Presets = presets,
IsSelected = presets == (AnchorPresets)Tag,
+ SupportsShiftModulation = _supportsShiftModulation,
Tag = presets,
};
button.ButtonClicked += OnButtonClicked;
@@ -278,7 +347,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
private void OnButtonClicked()
{
var location = _button.Center + new Vector2(3.0f);
- var editor = new AnchorPresetsEditorPopup(_button.Presets);
+ var editor = new AnchorPresetsEditorPopup(_button.Presets, true);
editor.VisibleChanged += OnEditorVisibleChanged;
editor.Show(_button.Parent, location);
}
@@ -290,6 +359,30 @@ namespace FlaxEditor.CustomEditors.Dedicated
SetValue(control.Tag);
}
+ ///
+ protected override void SynchronizeValue(object value)
+ {
+ // Custom anchors editing for Control to handle bounds preservation via key modifiers
+ if (ParentEditor != null)
+ {
+ var centerToPosition = Input.GetKey(KeyboardKeys.Shift);
+ var setPivot = Input.GetKey(KeyboardKeys.Control);
+ var editedAny = false;
+ foreach (var parentValue in ParentEditor.Values)
+ {
+ if (parentValue is Control parentControl)
+ {
+ parentControl.SetAnchorPreset((AnchorPresets)value, !centerToPosition, setPivot);
+ editedAny = true;
+ }
+ }
+ if (editedAny)
+ return;
+ }
+
+ base.SynchronizeValue(value);
+ }
+
///
public override void Refresh()
{
@@ -311,7 +404,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
/// Dedicated custom editor for object.
///
///
- public sealed class UIControlControlEditor : GenericEditor
+ public class UIControlControlEditor : GenericEditor
{
private Type _cachedType;
@@ -423,9 +516,9 @@ namespace FlaxEditor.CustomEditors.Dedicated
private void BuildLocationSizeOffsets(LayoutElementsContainer horUp, LayoutElementsContainer horDown, bool xEq, bool yEq, ScriptType[] valueTypes)
{
- ScriptMemberInfo xInfo = valueTypes[0].GetProperty("X");
+ ScriptMemberInfo xInfo = valueTypes[0].GetProperty("LocalX");
ItemInfo xItem = new ItemInfo(xInfo);
- ScriptMemberInfo yInfo = valueTypes[0].GetProperty("Y");
+ ScriptMemberInfo yInfo = valueTypes[0].GetProperty("LocalY");
ItemInfo yItem = new ItemInfo(yInfo);
ScriptMemberInfo widthInfo = valueTypes[0].GetProperty("Width");
ItemInfo widthItem = new ItemInfo(widthInfo);
diff --git a/Source/Editor/CustomEditors/Editors/CollectionEditor.cs b/Source/Editor/CustomEditors/Editors/CollectionEditor.cs
index 2e5aeade7..141330aea 100644
--- a/Source/Editor/CustomEditors/Editors/CollectionEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/CollectionEditor.cs
@@ -154,9 +154,20 @@ namespace FlaxEditor.CustomEditors.Editors
if (i != 0 && spacing > 0f)
{
if (layout.Children.Count > 0 && layout.Children[layout.Children.Count - 1] is PropertiesListElement propertiesListElement)
+ {
+ if (propertiesListElement.Labels.Count > 0)
+ {
+ var label = propertiesListElement.Labels[propertiesListElement.Labels.Count - 1];
+ var margin = label.Margin;
+ margin.Bottom += spacing;
+ label.Margin = margin;
+ }
propertiesListElement.Space(spacing);
+ }
else
+ {
layout.Space(spacing);
+ }
}
var overrideEditor = overrideEditorType != null ? (CustomEditor)Activator.CreateInstance(overrideEditorType) : null;
diff --git a/Source/Editor/CustomEditors/Editors/CultureInfoEditor.cs b/Source/Editor/CustomEditors/Editors/CultureInfoEditor.cs
new file mode 100644
index 000000000..67533ed56
--- /dev/null
+++ b/Source/Editor/CustomEditors/Editors/CultureInfoEditor.cs
@@ -0,0 +1,164 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using FlaxEditor.GUI;
+using FlaxEditor.GUI.ContextMenu;
+using FlaxEditor.GUI.Tree;
+using FlaxEditor.Utilities;
+using FlaxEngine;
+using FlaxEngine.GUI;
+
+namespace FlaxEditor.CustomEditors.Editors
+{
+ ///
+ /// Default implementation of the inspector used to edit value type properties. Supports editing property of type (as culture name).
+ ///
+ [CustomEditor(typeof(CultureInfo)), DefaultEditor]
+ internal class CultureInfoEditor : CustomEditor
+ {
+ private ClickableLabel _label;
+
+ ///
+ public override DisplayStyle Style => DisplayStyle.Inline;
+
+ ///
+ public override void Initialize(LayoutElementsContainer layout)
+ {
+ _label = layout.ClickableLabel(GetName(Culture)).CustomControl;
+ _label.RightClick += ShowPicker;
+ var button = new Button
+ {
+ Width = 16.0f,
+ Text = "...",
+ Parent = _label,
+ };
+ button.SetAnchorPreset(AnchorPresets.MiddleRight, false, true);
+ button.Clicked += ShowPicker;
+ }
+
+ ///
+ public override void Refresh()
+ {
+ base.Refresh();
+
+ _label.Text = GetName(Culture);
+ }
+
+ ///
+ protected override void Deinitialize()
+ {
+ _label = null;
+
+ base.Deinitialize();
+ }
+
+ private CultureInfo Culture
+ {
+ get
+ {
+ if (Values[0] is CultureInfo asCultureInfo)
+ return asCultureInfo;
+ if (Values[0] is string asString)
+ return new CultureInfo(asString);
+ return null;
+ }
+ set
+ {
+ if (Values[0] is CultureInfo)
+ SetValue(value);
+ else if (Values[0] is string)
+ SetValue(value.Name);
+ }
+ }
+
+ private class CultureInfoComparer : IComparer
+ {
+ public int Compare(CultureInfo a, CultureInfo b)
+ {
+ return string.Compare(a.Name, b.Name, StringComparison.Ordinal);
+ }
+ }
+
+ private static void UpdateFilter(TreeNode node, string filterText)
+ {
+ // Update children
+ bool isAnyChildVisible = false;
+ for (int i = 0; i < node.Children.Count; i++)
+ {
+ if (node.Children[i] is TreeNode child)
+ {
+ UpdateFilter(child, filterText);
+ isAnyChildVisible |= child.Visible;
+ }
+ }
+
+ // Update itself
+ bool noFilter = string.IsNullOrWhiteSpace(filterText);
+ bool isThisVisible = noFilter || QueryFilterHelper.Match(filterText, node.Text);
+ bool isExpanded = isAnyChildVisible;
+ if (isExpanded)
+ node.Expand(true);
+ else
+ node.Collapse(true);
+ node.Visible = isThisVisible | isAnyChildVisible;
+ }
+
+ private void ShowPicker()
+ {
+ var menu = CreatePicker(Culture, value => { Culture = value; });
+ menu.Show(_label, new Vector2(0, _label.Height));
+ }
+
+ internal static ContextMenuBase CreatePicker(CultureInfo value, Action changed)
+ {
+ var menu = Utilities.Utils.CreateSearchPopup(out var searchBox, out var tree);
+ tree.Margin = new Margin(-16.0f, 0.0f, -16.0f, -0.0f); // Hide root node
+ var root = tree.AddChild();
+ var cultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
+ Array.Sort(cultures, 1, cultures.Length - 2, new CultureInfoComparer()); // at 0 there is Invariant Culture
+ var lcidToNode = new Dictionary();
+ for (var i = 0; i < cultures.Length; i++)
+ {
+ var culture = cultures[i];
+ var node = new TreeNode
+ {
+ Tag = culture,
+ Text = GetName(culture),
+ };
+ if (!lcidToNode.TryGetValue(culture.Parent.LCID, out ContainerControl parent))
+ parent = root;
+ node.Parent = parent;
+ lcidToNode[culture.LCID] = node;
+ }
+ if (value != null)
+ tree.Select((TreeNode)lcidToNode[value.LCID]);
+ tree.SelectedChanged += delegate(List before, List after)
+ {
+ if (after.Count == 1)
+ {
+ menu.Hide();
+ changed((CultureInfo)after[0].Tag);
+ }
+ };
+ searchBox.TextChanged += delegate
+ {
+ if (tree.IsLayoutLocked)
+ return;
+ root.LockChildrenRecursive();
+ var query = searchBox.Text;
+ UpdateFilter(root, query);
+ root.UnlockChildrenRecursive();
+ menu.PerformLayout();
+ };
+ root.ExpandAll(true);
+ return menu;
+ }
+
+ internal static string GetName(CultureInfo value)
+ {
+ return value != null ? string.Format("{0} - {1}", value.Name, value.EnglishName) : null;
+ }
+ }
+}
diff --git a/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs b/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs
index 4e4048dba..4a94136db 100644
--- a/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs
@@ -61,7 +61,7 @@ namespace FlaxEditor.CustomEditors.Editors
var keyType = _editor.Values.Type.GetGenericArguments()[0];
if (keyType == typeof(string) || keyType.IsPrimitive)
{
- var popup = RenamePopup.Show(Parent, Bounds, Text, false);
+ var popup = RenamePopup.Show(Parent, Rectangle.Margin(Bounds, Margin), Text, false);
popup.Validate += (renamePopup, value) =>
{
object newKey;
@@ -86,7 +86,7 @@ namespace FlaxEditor.CustomEditors.Editors
}
else if (keyType.IsEnum)
{
- var popup = RenamePopup.Show(Parent, Bounds, Text, false);
+ var popup = RenamePopup.Show(Parent, Rectangle.Margin(Bounds, Margin), Text, false);
var picker = new EnumComboBox(keyType)
{
AnchorPreset = AnchorPresets.StretchAll,
@@ -220,9 +220,20 @@ namespace FlaxEditor.CustomEditors.Editors
if (i != 0 && spacing > 0f)
{
if (layout.Children.Count > 0 && layout.Children[layout.Children.Count - 1] is PropertiesListElement propertiesListElement)
+ {
+ if (propertiesListElement.Labels.Count > 0)
+ {
+ var label = propertiesListElement.Labels[propertiesListElement.Labels.Count - 1];
+ var margin = label.Margin;
+ margin.Bottom += spacing;
+ label.Margin = margin;
+ }
propertiesListElement.Space(spacing);
+ }
else
+ {
layout.Space(spacing);
+ }
}
var key = keys.ElementAt(i);
diff --git a/Source/Editor/CustomEditors/Editors/EnumEditor.cs b/Source/Editor/CustomEditors/Editors/EnumEditor.cs
index 7954e18bf..b91c0cf95 100644
--- a/Source/Editor/CustomEditors/Editors/EnumEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/EnumEditor.cs
@@ -9,7 +9,7 @@ using FlaxEngine;
namespace FlaxEditor.CustomEditors.Editors
{
///
- /// Default implementation of the inspector used to edit float value type properties.
+ /// Default implementation of the inspector used to edit enum value type properties.
///
[CustomEditor(typeof(Enum)), DefaultEditor]
public class EnumEditor : CustomEditor
diff --git a/Source/Editor/CustomEditors/Editors/GenericEditor.cs b/Source/Editor/CustomEditors/Editors/GenericEditor.cs
index 264aaeeff..179f5b935 100644
--- a/Source/Editor/CustomEditors/Editors/GenericEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/GenericEditor.cs
@@ -214,6 +214,7 @@ namespace FlaxEditor.CustomEditors.Editors
public ScriptMemberInfo Target;
public ScriptMemberInfo Source;
public PropertiesListElement PropertiesList;
+ public GroupElement Group;
public bool Invert;
public int LabelIndex;
@@ -379,26 +380,22 @@ namespace FlaxEditor.CustomEditors.Editors
}
}
}
- if (item.VisibleIf != null)
+ if (item.VisibleIf != null && itemLayout.Children.Count > 0)
{
- PropertiesListElement list;
- if (itemLayout.Children.Count > 0 && itemLayout.Children[itemLayout.Children.Count - 1] is PropertiesListElement list1)
- {
+ PropertiesListElement list = null;
+ GroupElement group = null;
+ if (itemLayout.Children[itemLayout.Children.Count - 1] is PropertiesListElement list1)
list = list1;
- }
+ else if (itemLayout.Children[itemLayout.Children.Count - 1] is GroupElement group1)
+ group = group1;
else
- {
- // TODO: support inlined objects hiding?
return;
- }
// Get source member used to check rule
var sourceMember = GetVisibleIfSource(item.Info.DeclaringType, item.VisibleIf);
if (sourceMember == ScriptType.Null)
return;
- // Find the target control to show/hide
-
// Resize cache
if (_visibleIfCaches == null)
_visibleIfCaches = new VisibleIfCache[8];
@@ -414,6 +411,7 @@ namespace FlaxEditor.CustomEditors.Editors
Target = item.Info,
Source = sourceMember,
PropertiesList = list,
+ Group = group,
LabelIndex = labelIndex,
Invert = item.VisibleIf.Invert,
};
@@ -569,8 +567,7 @@ namespace FlaxEditor.CustomEditors.Editors
{
for (int i = 0; i < _visibleIfCaches.Length; i++)
{
- var c = _visibleIfCaches[i];
-
+ ref var c = ref _visibleIfCaches[i];
if (c.Target == ScriptMemberInfo.Null)
break;
@@ -586,7 +583,7 @@ namespace FlaxEditor.CustomEditors.Editors
}
// Apply the visibility (note: there may be no label)
- if (c.LabelIndex != -1 && c.PropertiesList.Labels.Count > c.LabelIndex)
+ if (c.LabelIndex != -1 && c.PropertiesList != null && c.PropertiesList.Labels.Count > c.LabelIndex)
{
var label = c.PropertiesList.Labels[c.LabelIndex];
label.Visible = visible;
@@ -599,6 +596,10 @@ namespace FlaxEditor.CustomEditors.Editors
child.Visible = visible;
}
}
+ if (c.Group != null)
+ {
+ c.Group.Panel.Visible = visible;
+ }
}
}
catch (Exception ex)
diff --git a/Source/Editor/CustomEditors/Editors/LocalizedStringEditor.cs b/Source/Editor/CustomEditors/Editors/LocalizedStringEditor.cs
new file mode 100644
index 000000000..82503d9bc
--- /dev/null
+++ b/Source/Editor/CustomEditors/Editors/LocalizedStringEditor.cs
@@ -0,0 +1,234 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using FlaxEditor.Content.Settings;
+using FlaxEditor.CustomEditors.Elements;
+using FlaxEditor.GUI.Tree;
+using FlaxEditor.Scripting;
+using FlaxEditor.Utilities;
+using FlaxEngine;
+using FlaxEngine.GUI;
+using Utils = FlaxEditor.Utilities.Utils;
+
+namespace FlaxEditor.CustomEditors.Editors
+{
+ ///
+ /// Default implementation of the inspector used to edit localized string properties.
+ ///
+ [CustomEditor(typeof(LocalizedString)), DefaultEditor]
+ public sealed class LocalizedStringEditor : GenericEditor
+ {
+ private TextBoxElement _idElement, _valueElement;
+
+ ///
+ public override DisplayStyle Style => DisplayStyle.Inline;
+
+ ///
+ public override void Initialize(LayoutElementsContainer layout)
+ {
+ base.Initialize(layout);
+
+ if (layout.Children.Count == 0)
+ return;
+ var propList = layout.Children[layout.Children.Count - 1] as PropertiesListElement;
+ if (propList == null || propList.Children.Count != 2)
+ return;
+ var idElement = propList.Children[0] as TextBoxElement;
+ var valueElement = propList.Children[1] as TextBoxElement;
+ if (idElement == null || valueElement == null)
+ return;
+ _idElement = idElement;
+ _valueElement = valueElement;
+
+ var attributes = Values.GetAttributes();
+ var multiLine = attributes?.FirstOrDefault(x => x is MultilineTextAttribute);
+ if (multiLine != null)
+ {
+ valueElement.TextBox.IsMultiline = true;
+ valueElement.TextBox.Height *= 3;
+ }
+
+ var selectString = new Button
+ {
+ Width = 16.0f,
+ Text = "...",
+ TooltipText = "Select localized text from Localization Settings...",
+ Parent = idElement.TextBox,
+ };
+ selectString.SetAnchorPreset(AnchorPresets.MiddleRight, false, true);
+ selectString.ButtonClicked += OnSelectStringClicked;
+
+ var addString = new Button
+ {
+ Width = 16.0f,
+ Text = "+",
+ TooltipText = "Add new localized text to Localization Settings (all used locales)",
+ Parent = _valueElement.TextBox,
+ Enabled = IsSingleObject,
+ };
+ addString.SetAnchorPreset(AnchorPresets.MiddleRight, false, true);
+ addString.ButtonClicked += OnAddStringClicked;
+ }
+
+ ///
+ internal override void RefreshInternal()
+ {
+ base.RefreshInternal();
+
+ if (_valueElement != null)
+ {
+ _valueElement.TextBox.WatermarkText = Localization.GetString(_idElement.Text);
+ }
+ }
+
+ ///
+ protected override void Deinitialize()
+ {
+ base.Deinitialize();
+
+ _idElement = null;
+ _valueElement = null;
+ }
+
+ private void OnSelectStringClicked(Button button)
+ {
+ var settings = GameSettings.Load();
+ if (settings?.LocalizedStringTables == null || settings.LocalizedStringTables.Length == 0)
+ {
+ MessageBox.Show("No valid localization settings setup.");
+ return;
+ }
+ Profiler.BeginEvent("LocalizedStringEditor.OnSelectStringClicked");
+ var allKeys = new HashSet();
+ for (int i = 0; i < settings.LocalizedStringTables.Length; i++)
+ {
+ var table = settings.LocalizedStringTables[i];
+ if (table && !table.WaitForLoaded())
+ {
+ var entries = table.Entries;
+ foreach (var e in entries)
+ allKeys.Add(e.Key);
+ }
+ }
+ var allKeysSorted = allKeys.ToList();
+ allKeysSorted.Sort();
+ var value = _idElement?.TextBox.Text;
+ var menu = Utils.CreateSearchPopup(out var searchBox, out var tree);
+ var idToNode = new TreeNode[allKeysSorted.Count];
+ for (var i = 0; i < allKeysSorted.Count; i++)
+ {
+ var key = allKeysSorted[i];
+ var node = new TreeNode
+ {
+ Text = key,
+ TooltipText = Localization.GetString(key),
+ Parent = tree,
+ };
+ if (key == value)
+ tree.Select(node);
+ idToNode[i] = node;
+ }
+ tree.SelectedChanged += delegate(List before, List after)
+ {
+ if (after.Count == 1)
+ {
+ menu.Hide();
+ _idElement.TextBox.SetTextAsUser(after[0].Text);
+ }
+ };
+ searchBox.TextChanged += delegate
+ {
+ if (tree.IsLayoutLocked)
+ return;
+ tree.LockChildrenRecursive();
+ var query = searchBox.Text;
+ for (int i = 0; i < idToNode.Length; i++)
+ {
+ var node = idToNode[i];
+ node.Visible = string.IsNullOrWhiteSpace(query) || QueryFilterHelper.Match(query, node.Text);
+ }
+ tree.UnlockChildrenRecursive();
+ menu.PerformLayout();
+ };
+ menu.Show(button, new Vector2(0, button.Height));
+ Profiler.EndEvent();
+ }
+
+ private void OnAddStringClicked(Button button)
+ {
+ var settings = GameSettings.Load();
+ if (settings?.LocalizedStringTables == null || settings.LocalizedStringTables.Length == 0)
+ {
+ MessageBox.Show("No valid localization settings setup.");
+ return;
+ }
+ Profiler.BeginEvent("LocalizedStringEditor.OnAddStringClicked");
+ var allKeys = new HashSet();
+ for (int i = 0; i < settings.LocalizedStringTables.Length; i++)
+ {
+ var table = settings.LocalizedStringTables[i];
+ if (table && !table.WaitForLoaded())
+ {
+ var entries = table.Entries;
+ foreach (var e in entries)
+ allKeys.Add(e.Key);
+ }
+ }
+ _valueElement.TextBox.SetTextAsUser(null);
+ string newKey = null;
+ if (string.IsNullOrEmpty(_idElement.Text))
+ {
+ CustomEditor customEditor = this;
+ while (customEditor?.Values != null)
+ {
+ if (customEditor.Values.Info != ScriptMemberInfo.Null)
+ if (newKey == null)
+ newKey = customEditor.Values.Info.Name;
+ else
+ newKey = customEditor.Values.Info.Name + '.' + newKey;
+ else if (customEditor.Values[0] is SceneObject sceneObject)
+ if (newKey == null)
+ newKey = sceneObject.GetNamePath('.');
+ else
+ newKey = sceneObject.GetNamePath('.') + '.' + newKey;
+ else
+ break;
+ customEditor = customEditor.ParentEditor;
+ }
+ if (string.IsNullOrWhiteSpace(newKey))
+ newKey = Guid.NewGuid().ToString("N");
+ }
+ else
+ {
+ newKey = _idElement.Text;
+ }
+ if (allKeys.Contains(newKey))
+ {
+ Profiler.EndEvent();
+ if (_idElement.Text != newKey)
+ _idElement.TextBox.SetTextAsUser(newKey);
+ else
+ MessageBox.Show("Already added.");
+ return;
+ }
+ var newValue = _valueElement.Text;
+ Editor.Log(newKey + (newValue != null ? " = " + newValue : string.Empty));
+ var locales = settings.LocalizedStringTables.GroupBy(x => x.Locale);
+ foreach (var locale in locales)
+ {
+ var table = locale.First();
+ var entries = table.Entries;
+ if (table.Locale == "en")
+ entries[newKey] = new[] { newValue };
+ else
+ entries[newKey] = new[] { string.Empty };
+ table.Entries = entries;
+ table.Save();
+ }
+ _idElement.TextBox.SetTextAsUser(newKey);
+ Profiler.EndEvent();
+ }
+ }
+}
diff --git a/Source/Editor/CustomEditors/Editors/ObjectSwitcherEditor.cs b/Source/Editor/CustomEditors/Editors/ObjectSwitcherEditor.cs
index 7724acf18..dcdf3114b 100644
--- a/Source/Editor/CustomEditors/Editors/ObjectSwitcherEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/ObjectSwitcherEditor.cs
@@ -3,7 +3,6 @@
using System;
using FlaxEditor.GUI;
using FlaxEditor.Scripting;
-using FlaxEngine;
namespace FlaxEditor.CustomEditors.Editors
{
diff --git a/Source/Editor/CustomEditors/Editors/QuaternionEditor.cs b/Source/Editor/CustomEditors/Editors/QuaternionEditor.cs
index 338c8eca6..f80c81e27 100644
--- a/Source/Editor/CustomEditors/Editors/QuaternionEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/QuaternionEditor.cs
@@ -12,6 +12,9 @@ namespace FlaxEditor.CustomEditors.Editors
[CustomEditor(typeof(Quaternion)), DefaultEditor]
public class QuaternionEditor : CustomEditor
{
+ private Vector3 _cachedAngles = Vector3.Zero;
+ private object _cachedToken;
+
///
/// The X component element
///
@@ -58,15 +61,36 @@ namespace FlaxEditor.CustomEditors.Editors
if (IsSetBlocked)
return;
- float x = XElement.FloatValue.Value;
- float y = YElement.FloatValue.Value;
- float z = ZElement.FloatValue.Value;
var isSliding = XElement.IsSliding || YElement.IsSliding || ZElement.IsSliding;
var token = isSliding ? this : null;
+ var useCachedAngles = isSliding && token == _cachedToken;
+
+ float x = (useCachedAngles && !XElement.IsSliding) ? _cachedAngles.X : XElement.FloatValue.Value;
+ float y = (useCachedAngles && !YElement.IsSliding) ? _cachedAngles.Y : YElement.FloatValue.Value;
+ float z = (useCachedAngles && !ZElement.IsSliding) ? _cachedAngles.Z : ZElement.FloatValue.Value;
+
+ x = Mathf.UnwindDegrees(x);
+ y = Mathf.UnwindDegrees(y);
+ z = Mathf.UnwindDegrees(z);
+
+ if (!useCachedAngles)
+ {
+ _cachedAngles = new Vector3(x, y, z);
+ }
+
+ _cachedToken = token;
+
Quaternion.Euler(x, y, z, out Quaternion value);
SetValue(value, token);
}
+ ///
+ protected override void ClearToken()
+ {
+ _cachedToken = null;
+ base.ClearToken();
+ }
+
///
public override void Refresh()
{
diff --git a/Source/Editor/CustomEditors/Elements/Container/HorizontalPanelElement.cs b/Source/Editor/CustomEditors/Elements/Container/HorizontalPanelElement.cs
index 2958cd337..de015a371 100644
--- a/Source/Editor/CustomEditors/Elements/Container/HorizontalPanelElement.cs
+++ b/Source/Editor/CustomEditors/Elements/Container/HorizontalPanelElement.cs
@@ -5,15 +5,15 @@ using FlaxEngine.GUI;
namespace FlaxEditor.CustomEditors.Elements
{
///
- /// The vertical panel element.
+ /// The horizontal panel element.
///
///
- public class VerticalPanelElement : LayoutElementsContainer
+ public class HorizontalPanelElement : LayoutElementsContainer
{
///
/// The panel.
///
- public readonly VerticalPanel Panel = new VerticalPanel();
+ public readonly HorizontalPanel Panel = new HorizontalPanel();
///
public override ContainerControl ContainerControl => Panel;
diff --git a/Source/Editor/CustomEditors/Elements/Container/VerticalPanelElement.cs b/Source/Editor/CustomEditors/Elements/Container/VerticalPanelElement.cs
index de015a371..2958cd337 100644
--- a/Source/Editor/CustomEditors/Elements/Container/VerticalPanelElement.cs
+++ b/Source/Editor/CustomEditors/Elements/Container/VerticalPanelElement.cs
@@ -5,15 +5,15 @@ using FlaxEngine.GUI;
namespace FlaxEditor.CustomEditors.Elements
{
///
- /// The horizontal panel element.
+ /// The vertical panel element.
///
///
- public class HorizontalPanelElement : LayoutElementsContainer
+ public class VerticalPanelElement : LayoutElementsContainer
{
///
/// The panel.
///
- public readonly HorizontalPanel Panel = new HorizontalPanel();
+ public readonly VerticalPanel Panel = new VerticalPanel();
///
public override ContainerControl ContainerControl => Panel;
diff --git a/Source/Editor/CustomEditors/LayoutElementsContainer.cs b/Source/Editor/CustomEditors/LayoutElementsContainer.cs
index ae33599c1..6f645789a 100644
--- a/Source/Editor/CustomEditors/LayoutElementsContainer.cs
+++ b/Source/Editor/CustomEditors/LayoutElementsContainer.cs
@@ -112,7 +112,7 @@ namespace FlaxEditor.CustomEditors
OnAddElement(element);
return element;
}
-
+
///
/// Adds new horizontal panel element.
///
@@ -690,6 +690,17 @@ namespace FlaxEditor.CustomEditors
return element;
}
+ ///
+ /// Adds custom element to the layout.
+ ///
+ /// The element.
+ public void AddElement(LayoutElement element)
+ {
+ if (element == null)
+ throw new ArgumentNullException();
+ OnAddElement(element);
+ }
+
///
/// Called when element is added to the layout.
///
diff --git a/Source/Editor/Editor.Build.cs b/Source/Editor/Editor.Build.cs
index 9808b427e..69c842820 100644
--- a/Source/Editor/Editor.Build.cs
+++ b/Source/Editor/Editor.Build.cs
@@ -59,6 +59,7 @@ public class Editor : EditorModule
AddPlatformTools(options, platformToolsRoot, platformToolsRootExternal, "PS4", "PLATFORM_TOOLS_PS4");
AddPlatformTools(options, platformToolsRoot, platformToolsRootExternal, "XboxScarlett", "PLATFORM_TOOLS_XBOX_SCARLETT");
AddPlatformTools(options, platformToolsRoot, platformToolsRootExternal, "Android", "PLATFORM_TOOLS_ANDROID");
+ AddPlatformTools(options, platformToolsRoot, platformToolsRootExternal, "Switch", "PLATFORM_TOOLS_SWITCH");
}
AddPlatformTools(options, platformToolsRoot, platformToolsRootExternal, "Linux", "PLATFORM_TOOLS_LINUX");
diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs
index 5cada5d87..9a9500b7b 100644
--- a/Source/Editor/Editor.cs
+++ b/Source/Editor/Editor.cs
@@ -752,10 +752,11 @@ namespace FlaxEditor
/// The collision data type.
/// The source model.
/// The source model LOD index.
+ /// The source model material slots mask. One bit per-slot. Can be sued to exclude particular material slots from collision cooking.
/// The convex mesh generation flags.
/// The convex mesh vertex limit. Use values in range [8;255]
/// True if failed, otherwise false.
- public static bool CookMeshCollision(string path, CollisionDataType type, Model model, int modelLodIndex = 0, ConvexMeshGenerationFlags convexFlags = ConvexMeshGenerationFlags.None, int convexVertexLimit = 255)
+ public static bool CookMeshCollision(string path, CollisionDataType type, ModelBase model, int modelLodIndex = 0, uint materialSlotsMask = uint.MaxValue, ConvexMeshGenerationFlags convexFlags = ConvexMeshGenerationFlags.None, int convexVertexLimit = 255)
{
if (string.IsNullOrEmpty(path))
throw new ArgumentNullException(nameof(path));
@@ -764,7 +765,7 @@ namespace FlaxEditor
if (type == CollisionDataType.None)
throw new ArgumentException(nameof(type));
- return Internal_CookMeshCollision(path, type, FlaxEngine.Object.GetUnmanagedPtr(model), modelLodIndex, convexFlags, convexVertexLimit);
+ return Internal_CookMeshCollision(path, type, FlaxEngine.Object.GetUnmanagedPtr(model), modelLodIndex, materialSlotsMask, convexFlags, convexVertexLimit);
}
///
@@ -877,10 +878,12 @@ namespace FlaxEditor
/// Checks if can import asset with the given extension.
///
/// The file extension.
+ /// The output file extension (flax, json, etc.).
/// True if can import files with given extension, otherwise false.
- public static bool CanImport(string extension)
+ public static bool CanImport(string extension, out string outputExtension)
{
- return Internal_CanImport(extension);
+ outputExtension = Internal_CanImport(extension);
+ return outputExtension != null;
}
///
@@ -1344,7 +1347,7 @@ namespace FlaxEditor
internal static extern string Internal_GetShaderAssetSourceCode(IntPtr obj);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern bool Internal_CookMeshCollision(string path, CollisionDataType type, IntPtr model, int modelLodIndex, ConvexMeshGenerationFlags convexFlags, int convexVertexLimit);
+ internal static extern bool Internal_CookMeshCollision(string path, CollisionDataType type, IntPtr model, int modelLodIndex, uint materialSlotsMask, ConvexMeshGenerationFlags convexFlags, int convexVertexLimit);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void Internal_GetCollisionWires(IntPtr collisionData, out Vector3[] triangles, out int[] indices);
@@ -1368,7 +1371,7 @@ namespace FlaxEditor
internal static extern bool Internal_CreateVisualScript(string outputPath, string baseTypename);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern bool Internal_CanImport(string extension);
+ internal static extern string Internal_CanImport(string extension);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern bool Internal_CanExport(string path);
diff --git a/Source/Editor/GUI/EnumComboBox.cs b/Source/Editor/GUI/EnumComboBox.cs
index 8ceae0bb0..34a2dae35 100644
--- a/Source/Editor/GUI/EnumComboBox.cs
+++ b/Source/Editor/GUI/EnumComboBox.cs
@@ -29,7 +29,7 @@ namespace FlaxEditor.GUI
///
/// The cached value from the UI.
///
- protected int _cachedValue;
+ protected ulong _cachedValue;
///
/// True if has value cached, otherwise false.
@@ -54,7 +54,7 @@ namespace FlaxEditor.GUI
///
/// The value.
///
- public int Value;
+ public ulong Value;
///
/// Initializes a new instance of the struct.
@@ -62,7 +62,7 @@ namespace FlaxEditor.GUI
/// The name.
/// The tooltip.
/// The value.
- public Entry(string name, int value, string tooltip = null)
+ public Entry(string name, ulong value, string tooltip = null)
{
Name = name;
Tooltip = tooltip;
@@ -88,13 +88,13 @@ namespace FlaxEditor.GUI
public object EnumTypeValue
{
get => Enum.ToObject(_enumType, Value);
- set => Value = Convert.ToInt32(value);
+ set => Value = Convert.ToUInt64(value);
}
///
/// Gets or sets the value.
///
- public int Value
+ public ulong Value
{
get => _cachedValue;
set
@@ -209,13 +209,13 @@ namespace FlaxEditor.GUI
///
protected void CacheValue()
{
- int value = 0;
+ ulong value = 0;
if (IsFlags)
{
var selection = Selection;
for (int i = 0; i < selection.Count; i++)
{
- int index = selection[i];
+ var index = selection[i];
value |= _entries[index].Value;
}
}
@@ -276,7 +276,7 @@ namespace FlaxEditor.GUI
tooltip = tooltipAttr.Text;
}
- entries.Add(new Entry(name, Convert.ToInt32(field.GetRawConstantValue()), tooltip));
+ entries.Add(new Entry(name, Convert.ToUInt64(field.GetRawConstantValue()), tooltip));
}
}
@@ -295,9 +295,9 @@ namespace FlaxEditor.GUI
}
// Calculate value that will be set after change
- int valueAfter = 0;
+ ulong valueAfter = 0;
bool isSelected = _selectedIndices.Contains(index);
- int selectedValue = entries[index].Value;
+ ulong selectedValue = entries[index].Value;
for (int i = 0; i < _selectedIndices.Count; i++)
{
int selectedIndex = _selectedIndices[i];
diff --git a/Source/Editor/GUI/PlatformSelector.cs b/Source/Editor/GUI/PlatformSelector.cs
index d2e8bf682..ea0773a69 100644
--- a/Source/Editor/GUI/PlatformSelector.cs
+++ b/Source/Editor/GUI/PlatformSelector.cs
@@ -89,6 +89,7 @@ namespace FlaxEditor.GUI
new PlatformData(PlatformType.PS4, icons.PS4, "PlayStation 4"),
new PlatformData(PlatformType.XboxScarlett, icons.XboxSeriesX, "Xbox Scarlett"),
new PlatformData(PlatformType.Android, icons.Android, "Android"),
+ new PlatformData(PlatformType.Switch, icons.ColorWheel, "Switch"),
};
const float IconSize = 48.0f;
diff --git a/Source/Editor/History/UndoActionObject.cs b/Source/Editor/History/UndoActionObject.cs
index cac710bff..a87637f4f 100644
--- a/Source/Editor/History/UndoActionObject.cs
+++ b/Source/Editor/History/UndoActionObject.cs
@@ -4,6 +4,8 @@ using System;
using System.Collections.Generic;
using FlaxEditor.Utilities;
using FlaxEngine;
+using Newtonsoft.Json;
+using JsonSerializer = FlaxEngine.Json.JsonSerializer;
namespace FlaxEditor.History
{
@@ -114,6 +116,8 @@ namespace FlaxEditor.History
public object TargetInstance;
}
+ internal static JsonSerializerSettings JsonSettings;
+
// For objects that cannot be referenced in undo action like: FlaxEngine.Object or SceneGraphNode we store them in DataStorage,
// otherwise here:
private readonly object TargetInstance;
@@ -177,6 +181,24 @@ namespace FlaxEditor.History
};
}
+ ///
+ public override DataStorage Data
+ {
+ protected set
+ {
+ // Inject objects typename serialization to prevent data type mismatch when loading from saved state
+ var settings = JsonSettings;
+ if (settings == null)
+ {
+ settings = JsonSerializer.CreateDefaultSettings(false);
+ settings.TypeNameHandling = TypeNameHandling.All;
+ JsonSettings = settings;
+ }
+ _data = JsonConvert.SerializeObject(value, Formatting.Indented, settings);
+ //Editor.Log(_data);
+ }
+ }
+
///
public override string ActionString { get; }
diff --git a/Source/Editor/Managed/ManagedEditor.Internal.cpp b/Source/Editor/Managed/ManagedEditor.Internal.cpp
index 7b178b956..66f5a3c67 100644
--- a/Source/Editor/Managed/ManagedEditor.Internal.cpp
+++ b/Source/Editor/Managed/ManagedEditor.Internal.cpp
@@ -521,13 +521,14 @@ public:
return AssetsImportingManager::Create(AssetsImportingManager::CreateVisualScriptTag, outputPath, &baseTypename);
}
- static bool CanImport(MonoString* extensionObj)
+ static MonoString* CanImport(MonoString* extensionObj)
{
String extension;
MUtils::ToString(extensionObj, extension);
if (extension.Length() > 0 && extension[0] == '.')
extension.Remove(0, 1);
- return AssetsImportingManager::GetImporter(extension) != nullptr;
+ const AssetImporter* importer = AssetsImportingManager::GetImporter(extension);
+ return importer ? MUtils::ToString(importer->ResultExtension) : nullptr;
}
static bool Import(MonoString* inputPathObj, MonoString* outputPathObj, void* arg)
@@ -715,7 +716,7 @@ public:
return str;
}
- static bool CookMeshCollision(MonoString* pathObj, CollisionDataType type, Model* modelObj, int32 modelLodIndex, ConvexMeshGenerationFlags convexFlags, int32 convexVertexLimit)
+ static bool CookMeshCollision(MonoString* pathObj, CollisionDataType type, ModelBase* modelObj, int32 modelLodIndex, uint32 materialSlotsMask, ConvexMeshGenerationFlags convexFlags, int32 convexVertexLimit)
{
#if COMPILE_WITH_PHYSICS_COOKING
CollisionCooking::Argument arg;
@@ -725,9 +726,9 @@ public:
arg.Type = type;
arg.Model = modelObj;
arg.ModelLodIndex = modelLodIndex;
+ arg.MaterialSlotsMask = materialSlotsMask;
arg.ConvexFlags = convexFlags;
arg.ConvexVertexLimit = convexVertexLimit;
-
return CreateCollisionData::CookMeshCollision(path, arg);
#else
LOG(Warning, "Collision cooking is disabled.");
@@ -743,8 +744,8 @@ public:
const auto& debugLines = collisionData->GetDebugLines();
const int32 linesCount = debugLines.Count() / 2;
- *triangles = mono_array_new(mono_domain_get(), StdTypesContainer::Instance()->Vector3Class->GetNative(), debugLines.Count());
- *indices = mono_array_new(mono_domain_get(), mono_get_int32_class(), linesCount * 3);
+ mono_gc_wbarrier_generic_store(triangles, (MonoObject*)mono_array_new(mono_domain_get(), StdTypesContainer::Instance()->Vector3Class->GetNative(), debugLines.Count()));
+ mono_gc_wbarrier_generic_store(indices, (MonoObject*)mono_array_new(mono_domain_get(), mono_get_int32_class(), linesCount * 3));
// Use one triangle per debug line
for (int32 i = 0; i < debugLines.Count(); i++)
diff --git a/Source/Editor/Modules/ContentDatabaseModule.cs b/Source/Editor/Modules/ContentDatabaseModule.cs
index c90a386c1..ed1f69726 100644
--- a/Source/Editor/Modules/ContentDatabaseModule.cs
+++ b/Source/Editor/Modules/ContentDatabaseModule.cs
@@ -923,6 +923,7 @@ namespace FlaxEditor.Modules
Proxy.Add(new SkeletonMaskProxy());
Proxy.Add(new GameplayGlobalsProxy());
Proxy.Add(new VisualScriptProxy());
+ Proxy.Add(new LocalizedStringTableProxy());
Proxy.Add(new FileProxy());
Proxy.Add(new SpawnableJsonAssetProxy());
@@ -933,6 +934,7 @@ namespace FlaxEditor.Modules
Proxy.Add(new SettingsProxy(typeof(PhysicsSettings)));
Proxy.Add(new SettingsProxy(typeof(GraphicsSettings)));
Proxy.Add(new SettingsProxy(typeof(NavigationSettings)));
+ Proxy.Add(new SettingsProxy(typeof(LocalizationSettings)));
Proxy.Add(new SettingsProxy(typeof(BuildSettings)));
Proxy.Add(new SettingsProxy(typeof(InputSettings)));
Proxy.Add(new SettingsProxy(typeof(WindowsPlatformSettings)));
@@ -945,6 +947,9 @@ namespace FlaxEditor.Modules
if (typeXboxScarlettPlatformSettings != null)
Proxy.Add(new SettingsProxy(typeXboxScarlettPlatformSettings));
Proxy.Add(new SettingsProxy(typeof(AndroidPlatformSettings)));
+ var typeSwitchPlatformSettings = TypeUtils.GetManagedType(GameSettings.SwitchPlatformSettingsTypename);
+ if (typeSwitchPlatformSettings != null)
+ Proxy.Add(new SettingsProxy(typeSwitchPlatformSettings));
Proxy.Add(new SettingsProxy(typeof(AudioSettings)));
// Last add generic json (won't override other json proxies)
diff --git a/Source/Editor/Modules/ContentFindingModule.cs b/Source/Editor/Modules/ContentFindingModule.cs
index 9be15e0d1..45748f7f4 100644
--- a/Source/Editor/Modules/ContentFindingModule.cs
+++ b/Source/Editor/Modules/ContentFindingModule.cs
@@ -309,6 +309,7 @@ namespace FlaxEditor.Modules
{ "FlaxEditor.Content.Settings.InputSettings", "Settings" },
{ "FlaxEditor.Content.Settings.LayersAndTagsSettings", "Settings" },
{ "FlaxEditor.Content.Settings.NavigationSettings", "Settings" },
+ { "FlaxEditor.Content.Settings.LocalizationSettings", "Settings" },
{ "FlaxEditor.Content.Settings.PhysicsSettings", "Settings" },
{ "FlaxEditor.Content.Settings.TimeSettings", "Settings" },
{ "FlaxEditor.Content.Settings.UWPPlatformSettings", "Settings" },
diff --git a/Source/Editor/Modules/ContentImportingModule.cs b/Source/Editor/Modules/ContentImportingModule.cs
index d5ec4b69f..424868fd8 100644
--- a/Source/Editor/Modules/ContentImportingModule.cs
+++ b/Source/Editor/Modules/ContentImportingModule.cs
@@ -193,12 +193,10 @@ namespace FlaxEditor.Modules
var extension = System.IO.Path.GetExtension(inputPath) ?? string.Empty;
// Check if given file extension is a binary asset (.flax files) and can be imported by the engine
- bool isBinaryAsset = Editor.CanImport(extension);
- string outputExtension;
- if (isBinaryAsset)
+ bool isBuilt = Editor.CanImport(extension, out var outputExtension);
+ if (isBuilt)
{
- // Flax it up!
- outputExtension = ".flax";
+ outputExtension = '.' + outputExtension;
if (!targetLocation.CanHaveAssets)
{
@@ -234,7 +232,7 @@ namespace FlaxEditor.Modules
var shortName = System.IO.Path.GetFileNameWithoutExtension(inputPath);
var outputPath = System.IO.Path.Combine(targetLocation.Path, shortName + outputExtension);
- Import(inputPath, outputPath, isBinaryAsset, skipSettingsDialog, settings);
+ Import(inputPath, outputPath, isBuilt, skipSettingsDialog, settings);
}
///
@@ -243,10 +241,10 @@ namespace FlaxEditor.Modules
///
/// The input path.
/// The output path.
- /// True if output file is a binary asset.
+ /// True if use in-built importer (engine backend).
/// True if skip any popup dialogs showing for import options adjusting. Can be used when importing files from code.
/// Import settings to override. Use null to skip this value.
- private void Import(string inputPath, string outputPath, bool isBinaryAsset, bool skipSettingsDialog = false, object settings = null)
+ private void Import(string inputPath, string outputPath, bool isInBuilt, bool skipSettingsDialog = false, object settings = null)
{
lock (_requests)
{
@@ -254,7 +252,7 @@ namespace FlaxEditor.Modules
{
InputPath = inputPath,
OutputPath = outputPath,
- IsBinaryAsset = isBinaryAsset,
+ IsInBuilt = isInBuilt,
SkipSettingsDialog = skipSettingsDialog,
Settings = settings,
});
diff --git a/Source/Editor/SceneGraph/ActorNode.cs b/Source/Editor/SceneGraph/ActorNode.cs
index 017cff3bf..6703c30a0 100644
--- a/Source/Editor/SceneGraph/ActorNode.cs
+++ b/Source/Editor/SceneGraph/ActorNode.cs
@@ -194,7 +194,7 @@ namespace FlaxEditor.SceneGraph
{
get
{
- var scene = _actor.Scene;
+ var scene = _actor ? _actor.Scene : null;
return scene != null ? SceneGraphFactory.FindNode(scene.ID) as SceneNode : null;
}
}
@@ -235,7 +235,6 @@ namespace FlaxEditor.SceneGraph
{
if (!(value is ActorNode))
throw new InvalidOperationException("ActorNode can have only ActorNode as a parent node.");
-
base.ParentNode = value;
}
}
@@ -289,6 +288,13 @@ namespace FlaxEditor.SceneGraph
{
}
+ ///
+ /// Action called after pasting actor in editor.
+ ///
+ public virtual void PostPaste()
+ {
+ }
+
///
protected override void OnParentChanged()
{
@@ -299,6 +305,7 @@ namespace FlaxEditor.SceneGraph
// (eg. we build new node for spawned actor and link it to the game)
if (_treeNode.Parent != null && !_treeNode.Parent.IsLayoutLocked)
{
+ _treeNode.IndexInParent = _actor.OrderInParent;
_treeNode.Parent.SortChildren();
// Update UI
diff --git a/Source/Editor/SceneGraph/Actors/UIControlNode.cs b/Source/Editor/SceneGraph/Actors/UIControlNode.cs
index b3f8f5d09..c4f7d1c17 100644
--- a/Source/Editor/SceneGraph/Actors/UIControlNode.cs
+++ b/Source/Editor/SceneGraph/Actors/UIControlNode.cs
@@ -25,5 +25,20 @@ namespace FlaxEditor.SceneGraph.Actors
if (Actor is UIControl uiControl)
DebugDraw.DrawWireBox(uiControl.Bounds, Color.BlueViolet);
}
+
+ ///
+ public override void PostPaste()
+ {
+ base.PostPaste();
+
+ var control = ((UIControl)Actor).Control;
+ if (control != null)
+ {
+ if (control.Parent != null)
+ control.Parent.PerformLayout();
+ else
+ control.PerformLayout();
+ }
+ }
}
}
diff --git a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
index 7b4b35ed1..2c050c2e3 100644
--- a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
+++ b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
@@ -86,6 +86,10 @@ namespace FlaxEditor.SceneGraph.GUI
}
parent.SortChildren();
}
+ else if (Actor)
+ {
+ _orderInParent = Actor.OrderInParent;
+ }
}
internal void OnNameChanged()
diff --git a/Source/Editor/SceneGraph/SceneGraphNode.cs b/Source/Editor/SceneGraph/SceneGraphNode.cs
index 76327918d..bc8fe84aa 100644
--- a/Source/Editor/SceneGraph/SceneGraphNode.cs
+++ b/Source/Editor/SceneGraph/SceneGraphNode.cs
@@ -112,18 +112,9 @@ namespace FlaxEditor.SceneGraph
{
if (parentNode != value)
{
- if (parentNode != null)
- {
- parentNode.ChildNodes.Remove(this);
- }
-
+ parentNode?.ChildNodes.Remove(this);
parentNode = value;
-
- if (parentNode != null)
- {
- parentNode.ChildNodes.Add(this);
- }
-
+ parentNode?.ChildNodes.Add(this);
OnParentChanged();
}
}
@@ -374,6 +365,7 @@ namespace FlaxEditor.SceneGraph
///
/// Gets or sets the node state.
///
+ [NoSerialize]
public virtual StateData State
{
get => throw new NotImplementedException();
diff --git a/Source/Editor/Surface/Archetypes/Comparisons.cs b/Source/Editor/Surface/Archetypes/Comparisons.cs
index d77fd5ff7..44c49925d 100644
--- a/Source/Editor/Surface/Archetypes/Comparisons.cs
+++ b/Source/Editor/Surface/Archetypes/Comparisons.cs
@@ -137,7 +137,7 @@ namespace FlaxEditor.Surface.Archetypes
{
int* dataValues = (int*)dataPtr;
for (int i = 0; i < entries.Count; i++)
- dataValues[i] = entries[i].Value;
+ dataValues[i] = (int)entries[i].Value;
}
}
else
diff --git a/Source/Editor/Surface/Archetypes/Flow.cs b/Source/Editor/Surface/Archetypes/Flow.cs
index b8c426a5a..ffcfb719a 100644
--- a/Source/Editor/Surface/Archetypes/Flow.cs
+++ b/Source/Editor/Surface/Archetypes/Flow.cs
@@ -177,7 +177,7 @@ namespace FlaxEditor.Surface.Archetypes
{
int* dataValues = (int*)dataPtr;
for (int i = 0; i < entries.Count; i++)
- dataValues[i] = entries[i].Value;
+ dataValues[i] = (int)entries[i].Value;
}
}
else
diff --git a/Source/Editor/Surface/Archetypes/Tools.cs b/Source/Editor/Surface/Archetypes/Tools.cs
index e5513b598..15f2b15b8 100644
--- a/Source/Editor/Surface/Archetypes/Tools.cs
+++ b/Source/Editor/Surface/Archetypes/Tools.cs
@@ -672,6 +672,24 @@ namespace FlaxEditor.Surface.Archetypes
}
}
+ private class ThisNode : SurfaceNode
+ {
+ ///
+ public ThisNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch)
+ : base(id, context, nodeArch, groupArch)
+ {}
+
+ ///
+ public override void OnLoaded()
+ {
+ base.OnLoaded();
+ var vss = (VisualScriptSurface)this.Context.Surface;
+ var type = TypeUtils.GetType(vss.Script.ScriptTypeName);
+ var box = (OutputBox)GetBox(0);
+ box.CurrentType = type ? type : new ScriptType(typeof(VisualScript));
+ }
+ }
+
private class AssetReferenceNode : SurfaceNode
{
///
@@ -1326,9 +1344,9 @@ namespace FlaxEditor.Surface.Archetypes
Title = "Platform Switch",
Description = "Gets the input value based on the runtime-platform type",
Flags = NodeFlags.AllGraphs,
- Size = new Vector2(220, 160),
+ Size = new Vector2(220, 180),
ConnectionsHints = ConnectionsHint.Value,
- IndependentBoxes = new[] { 1, 2, 3, 4, 5, 6, 7, 8 },
+ IndependentBoxes = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
DependentBoxes = new[] { 0 },
Elements = new[]
{
@@ -1341,6 +1359,7 @@ namespace FlaxEditor.Surface.Archetypes
NodeElementArchetype.Factory.Input(5, "PlayStation 4", true, null, 6),
NodeElementArchetype.Factory.Input(6, "Xbox Scarlett", true, null, 7),
NodeElementArchetype.Factory.Input(7, "Android", true, null, 8),
+ NodeElementArchetype.Factory.Input(8, "Switch", true, null, 9),
}
},
new NodeArchetype
@@ -1365,6 +1384,7 @@ namespace FlaxEditor.Surface.Archetypes
{
TypeID = 19,
Title = "This Instance",
+ Create = (id, context, arch, groupArch) => new ThisNode(id, context, arch, groupArch),
Description = "Gets the reference to this script object instance (self).",
Flags = NodeFlags.VisualScriptGraph,
Size = new Vector2(140, 20),
diff --git a/Source/Editor/Surface/Elements/EnumValue.cs b/Source/Editor/Surface/Elements/EnumValue.cs
index 9513abd78..a66031f35 100644
--- a/Source/Editor/Surface/Elements/EnumValue.cs
+++ b/Source/Editor/Surface/Elements/EnumValue.cs
@@ -32,13 +32,13 @@ namespace FlaxEditor.Surface.Elements
Width = archetype.Size.X;
ParentNode = parentNode;
Archetype = archetype;
- Value = (int)ParentNode.Values[Archetype.ValueIndex];
+ Value = (ulong)(int)ParentNode.Values[Archetype.ValueIndex];
}
///
protected override void OnValueChanged()
{
- if ((int)ParentNode.Values[Archetype.ValueIndex] != Value)
+ if ((int)ParentNode.Values[Archetype.ValueIndex] != (int)Value)
{
// Edit value
ParentNode.SetValue(Archetype.ValueIndex, Value);
diff --git a/Source/Editor/Undo/Actions/PasteActorsAction.cs b/Source/Editor/Undo/Actions/PasteActorsAction.cs
index c65aa6bf0..c77feb71d 100644
--- a/Source/Editor/Undo/Actions/PasteActorsAction.cs
+++ b/Source/Editor/Undo/Actions/PasteActorsAction.cs
@@ -140,22 +140,27 @@ namespace FlaxEditor.Actions
for (int i = 0; i < nodeParents.Count; i++)
{
- // Fix name collisions (only for parents)
var node = nodeParents[i];
var parent = node.Actor?.Parent;
if (parent != null)
{
+ // Fix name collisions
string name = node.Name;
Actor[] children = parent.Children;
if (children.Any(x => x.Name == name))
{
- // Generate new name
node.Actor.Name = StringUtils.IncrementNameNumber(name, x => children.All(y => y.Name != x));
}
}
Editor.Instance.Scene.MarkSceneEdited(node.ParentScene);
}
+
+ for (int i = 0; i < nodeParents.Count; i++)
+ {
+ var node = nodeParents[i];
+ node.PostPaste();
+ }
}
///
diff --git a/Source/Editor/Undo/UndoActionBase.cs b/Source/Editor/Undo/UndoActionBase.cs
index 5de052a45..6648096c6 100644
--- a/Source/Editor/Undo/UndoActionBase.cs
+++ b/Source/Editor/Undo/UndoActionBase.cs
@@ -4,7 +4,6 @@ using System;
using FlaxEditor.SceneGraph;
using FlaxEngine;
using Newtonsoft.Json;
-using JsonSerializer = FlaxEngine.Json.JsonSerializer;
namespace FlaxEditor
{
@@ -28,7 +27,6 @@ namespace FlaxEditor
var id = Guid.Parse((string)reader.Value);
return SceneGraphFactory.FindNode(id);
}
-
return null;
}
@@ -56,19 +54,11 @@ namespace FlaxEditor
///
/// Gets or sets the serialized undo data.
///
- ///
- /// The data.
- ///
[NoSerialize]
- public TData Data
+ public virtual TData Data
{
- get => JsonConvert.DeserializeObject(_data, JsonSerializer.Settings);
- protected set => _data = JsonConvert.SerializeObject(value, Formatting.None, JsonSerializer.Settings);
- /*protected set
- {
- _data = JsonConvert.SerializeObject(value, Formatting.Indented, JsonSerializer.Settings);
- Debug.Info(_data);
- }*/
+ get => JsonConvert.DeserializeObject(_data, FlaxEngine.Json.JsonSerializer.Settings);
+ protected set => _data = JsonConvert.SerializeObject(value, Formatting.None, FlaxEngine.Json.JsonSerializer.Settings);
}
///
diff --git a/Source/Editor/Utilities/Utils.cs b/Source/Editor/Utilities/Utils.cs
index b5c835d70..ff97ef7cc 100644
--- a/Source/Editor/Utilities/Utils.cs
+++ b/Source/Editor/Utilities/Utils.cs
@@ -6,6 +6,8 @@ using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
+using FlaxEditor.GUI.ContextMenu;
+using FlaxEditor.GUI.Tree;
using FlaxEditor.SceneGraph;
using FlaxEditor.Scripting;
using FlaxEngine;
@@ -67,6 +69,10 @@ namespace FlaxEditor.Utilities
Dictionary,
ManagedObject,
Typename,
+
+ Int2,
+ Int3,
+ Int4
}
///
@@ -446,6 +452,12 @@ namespace FlaxEditor.Utilities
variantType = VariantType.Vector3;
else if (type == typeof(Vector4))
variantType = VariantType.Vector4;
+ else if (type == typeof(Int2))
+ variantType = VariantType.Int2;
+ else if (type == typeof(Int3))
+ variantType = VariantType.Int3;
+ else if (type == typeof(Int4))
+ variantType = VariantType.Int4;
else if (type == typeof(Color))
variantType = VariantType.Color;
else if (type == typeof(Guid))
@@ -682,6 +694,21 @@ namespace FlaxEditor.Utilities
new Vector3(stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle()));
break;
}
+ case 19: // CommonType::Int2
+ {
+ value = stream.ReadInt2();
+ break;
+ }
+ case 20: // CommonType::Int3
+ {
+ value = stream.ReadInt3();
+ break;
+ }
+ case 21: // CommonType::Int4
+ {
+ value = stream.ReadInt4();
+ break;
+ }
default: throw new SystemException();
}
}
@@ -733,6 +760,9 @@ namespace FlaxEditor.Utilities
case VariantType.Vector2: return new ScriptType(typeof(Vector2));
case VariantType.Vector3: return new ScriptType(typeof(Vector3));
case VariantType.Vector4: return new ScriptType(typeof(Vector4));
+ case VariantType.Int2: return new ScriptType(typeof(Int2));
+ case VariantType.Int3: return new ScriptType(typeof(Int3));
+ case VariantType.Int4: return new ScriptType(typeof(Int4));
case VariantType.Color: return new ScriptType(typeof(Color));
case VariantType.Guid: return new ScriptType(typeof(Guid));
case VariantType.BoundingBox: return new ScriptType(typeof(BoundingBox));
@@ -797,6 +827,9 @@ namespace FlaxEditor.Utilities
case VariantType.Vector2: return typeof(Vector2);
case VariantType.Vector3: return typeof(Vector3);
case VariantType.Vector4: return typeof(Vector4);
+ case VariantType.Int2: return typeof(Int2);
+ case VariantType.Int3: return typeof(Int3);
+ case VariantType.Int4: return typeof(Int4);
case VariantType.Color: return typeof(Color);
case VariantType.Guid: return typeof(Guid);
case VariantType.BoundingBox: return typeof(BoundingBox);
@@ -894,6 +927,9 @@ namespace FlaxEditor.Utilities
case VariantType.Vector2: return stream.ReadVector2();
case VariantType.Vector3: return stream.ReadVector3();
case VariantType.Vector4: return stream.ReadVector4();
+ case VariantType.Int2: return stream.ReadInt2();
+ case VariantType.Int3: return stream.ReadInt3();
+ case VariantType.Int4: return stream.ReadInt4();
case VariantType.Color: return stream.ReadColor();
case VariantType.Guid: return stream.ReadGuid();
case VariantType.BoundingBox: return stream.ReadBoundingBox();
@@ -1087,6 +1123,21 @@ namespace FlaxEditor.Utilities
stream.Write(asRay.Direction.Y);
stream.Write(asRay.Direction.Z);
}
+ else if (value is Int2 asInt2)
+ {
+ stream.Write((byte)19);
+ stream.Write(asInt2);
+ }
+ else if (value is Int3 asInt3)
+ {
+ stream.Write((byte)20);
+ stream.Write(asInt3);
+ }
+ else if (value is Int4 asInt4)
+ {
+ stream.Write((byte)21);
+ stream.Write(asInt4);
+ }
else
{
throw new NotSupportedException(string.Format("Invalid Common Value type {0}", value != null ? value.GetType().ToString() : "null"));
@@ -1194,6 +1245,15 @@ namespace FlaxEditor.Utilities
case VariantType.Vector4:
stream.Write((Vector4)value);
break;
+ case VariantType.Int2:
+ stream.Write((Int2)value);
+ break;
+ case VariantType.Int3:
+ stream.Write((Int3)value);
+ break;
+ case VariantType.Int4:
+ stream.Write((Int4)value);
+ break;
case VariantType.Color:
stream.Write((Color)value);
break;
@@ -1386,6 +1446,51 @@ namespace FlaxEditor.Utilities
stream.WriteEndObject();
break;
}
+ case VariantType.Int2:
+ {
+ var asInt2 = (Int2)value;
+ stream.WriteStartObject();
+
+ stream.WritePropertyName("X");
+ stream.WriteValue(asInt2.X);
+ stream.WritePropertyName("Y");
+ stream.WriteValue(asInt2.Y);
+
+ stream.WriteEndObject();
+ break;
+ }
+ case VariantType.Int3:
+ {
+ var asInt3 = (Int3)value;
+ stream.WriteStartObject();
+
+ stream.WritePropertyName("X");
+ stream.WriteValue(asInt3.X);
+ stream.WritePropertyName("Y");
+ stream.WriteValue(asInt3.Y);
+ stream.WritePropertyName("Z");
+ stream.WriteValue(asInt3.Z);
+
+ stream.WriteEndObject();
+ break;
+ }
+ case VariantType.Int4:
+ {
+ var asInt4 = (Int4)value;
+ stream.WriteStartObject();
+
+ stream.WritePropertyName("X");
+ stream.WriteValue(asInt4.X);
+ stream.WritePropertyName("Y");
+ stream.WriteValue(asInt4.Y);
+ stream.WritePropertyName("Z");
+ stream.WriteValue(asInt4.Z);
+ stream.WritePropertyName("W");
+ stream.WriteValue(asInt4.W);
+
+ stream.WriteEndObject();
+ break;
+ }
case VariantType.Color:
{
var asColor = (Color)value;
@@ -1777,5 +1882,41 @@ namespace FlaxEditor.Utilities
}
}
}
+
+ ///
+ /// Creates the search popup with a tree.
+ ///
+ /// The search box.
+ /// The tree control.
+ /// The created menu to setup and show.
+ public static ContextMenuBase CreateSearchPopup(out TextBox searchBox, out Tree tree)
+ {
+ var menu = new ContextMenuBase
+ {
+ Size = new Vector2(320, 220),
+ };
+ searchBox = new TextBox(false, 1, 1)
+ {
+ Width = menu.Width - 3,
+ WatermarkText = "Search...",
+ Parent = menu,
+ };
+ var panel1 = new Panel(ScrollBars.Vertical)
+ {
+ Bounds = new Rectangle(0, searchBox.Bottom + 1, menu.Width, menu.Height - searchBox.Bottom - 2),
+ Parent = menu
+ };
+ var panel2 = new VerticalPanel
+ {
+ Parent = panel1,
+ AnchorPreset = AnchorPresets.HorizontalStretchTop,
+ IsScrollable = true,
+ };
+ tree = new Tree(false)
+ {
+ Parent = panel2,
+ };
+ return menu;
+ }
}
}
diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs
index a1e2df86c..25fcbe4ce 100644
--- a/Source/Editor/Viewport/EditorViewport.cs
+++ b/Source/Editor/Viewport/EditorViewport.cs
@@ -974,7 +974,8 @@ namespace FlaxEditor.Viewport
// Get input buttons and keys (skip if viewport has no focus or mouse is over a child control)
bool useMouse = Mathf.IsInRange(_viewMousePos.X, 0, Width) && Mathf.IsInRange(_viewMousePos.Y, 0, Height);
_prevInput = _input;
- if (ContainsFocus && GetChildAt(_viewMousePos, c => c.Visible) == null)
+ var hit = GetChildAt(_viewMousePos, c => c.Visible && !(c is CanvasRootControl));
+ if (ContainsFocus && hit == null)
_input.Gather(win.Window, useMouse);
else
_input.Clear();
diff --git a/Source/Editor/Viewport/Previews/ModelBasePreview.cs b/Source/Editor/Viewport/Previews/ModelBasePreview.cs
new file mode 100644
index 000000000..59ed5f318
--- /dev/null
+++ b/Source/Editor/Viewport/Previews/ModelBasePreview.cs
@@ -0,0 +1,122 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+using FlaxEditor.GUI.Input;
+using FlaxEngine;
+using Object = FlaxEngine.Object;
+
+namespace FlaxEditor.Viewport.Previews
+{
+ ///
+ /// Model Base asset preview editor viewport.
+ ///
+ ///
+ public class ModelBasePreview : AssetPreview
+ {
+ ///
+ /// Gets or sets the model asset to preview.
+ ///
+ public ModelBase Asset
+ {
+ get => (ModelBase)StaticModel.Model ?? AnimatedModel.SkinnedModel;
+ set
+ {
+ StaticModel.Model = value as Model;
+ AnimatedModel.SkinnedModel = value as SkinnedModel;
+ }
+ }
+
+ ///
+ /// The static model for display.
+ ///
+ public StaticModel StaticModel;
+
+ ///
+ /// The animated model for display.
+ ///
+ public AnimatedModel AnimatedModel;
+
+ ///
+ /// Gets or sets a value indicating whether scale the model to the normalized bounds.
+ ///
+ public bool ScaleToFit { get; set; } = true;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// if set to true use widgets.
+ public ModelBasePreview(bool useWidgets)
+ : base(useWidgets)
+ {
+ Task.Begin += OnBegin;
+
+ // Setup preview scene
+ StaticModel = new StaticModel();
+ AnimatedModel = new AnimatedModel();
+
+ // Link actors for rendering
+ Task.AddCustomActor(StaticModel);
+ Task.AddCustomActor(AnimatedModel);
+
+ if (useWidgets)
+ {
+ // Preview LOD
+ {
+ var previewLOD = ViewWidgetButtonMenu.AddButton("Preview LOD");
+ var previewLODValue = new IntValueBox(-1, 90, 2, 70.0f, -1, 10, 0.02f)
+ {
+ Parent = previewLOD
+ };
+ previewLODValue.ValueChanged += () =>
+ {
+ StaticModel.ForcedLOD = previewLODValue.Value;
+ AnimatedModel.ForcedLOD = previewLODValue.Value;
+ };
+ ViewWidgetButtonMenu.VisibleChanged += control => previewLODValue.Value = StaticModel.ForcedLOD;
+ }
+ }
+ }
+
+ private void OnBegin(RenderTask task, GPUContext context)
+ {
+ var position = Vector3.Zero;
+ var scale = Vector3.One;
+
+ // Update preview model scale to fit the preview
+ var model = Asset;
+ if (ScaleToFit && model && model.IsLoaded)
+ {
+ float targetSize = 50.0f;
+ BoundingBox box = model is Model ? ((Model)model).GetBox() : ((SkinnedModel)model).GetBox();
+ float maxSize = Mathf.Max(0.001f, box.Size.MaxValue);
+ scale = new Vector3(targetSize / maxSize);
+ position = box.Center * (-0.5f * scale.X) + new Vector3(0, -10, 0);
+ }
+
+ StaticModel.Transform = new Transform(position, StaticModel.Orientation, scale);
+ AnimatedModel.Transform = new Transform(position, AnimatedModel.Orientation, scale);
+ }
+
+ ///
+ public override bool OnKeyDown(KeyboardKeys key)
+ {
+ switch (key)
+ {
+ case KeyboardKeys.F:
+ // Pay respect..
+ ViewportCamera.SetArcBallView(StaticModel.Model != null ? StaticModel.Box : AnimatedModel.Box);
+ break;
+ }
+ return base.OnKeyDown(key);
+ }
+
+ ///
+ public override void OnDestroy()
+ {
+ // Ensure to cleanup created actor objects
+ Object.Destroy(ref StaticModel);
+ Object.Destroy(ref AnimatedModel);
+
+ base.OnDestroy();
+ }
+ }
+}
diff --git a/Source/Editor/Windows/Assets/CollisionDataWindow.cs b/Source/Editor/Windows/Assets/CollisionDataWindow.cs
index 23f9ae5ed..0ff3f86e7 100644
--- a/Source/Editor/Windows/Assets/CollisionDataWindow.cs
+++ b/Source/Editor/Windows/Assets/CollisionDataWindow.cs
@@ -1,5 +1,6 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+using System;
using System.Xml;
using FlaxEditor.Content;
using FlaxEditor.Content.Create;
@@ -10,6 +11,7 @@ using FlaxEditor.Viewport.Cameras;
using FlaxEditor.Viewport.Previews;
using FlaxEngine;
using FlaxEngine.GUI;
+using Object = FlaxEngine.Object;
namespace FlaxEditor.Windows.Assets
{
@@ -20,6 +22,15 @@ namespace FlaxEditor.Windows.Assets
///
public sealed class CollisionDataWindow : AssetEditorWindowBase
{
+ [Flags]
+ private enum MaterialSlotsMask : uint
+ {
+ // @formatter:off
+ Slot0=1u<<0,Slot1=1u<<1,Slot2=1u<<2,Slot3=1u<<3,Slot4=1u<<4,Slot5=1u<<5,Slot6=1u<<6,Slot7=1u<<7,Slot8=1u<<8,Slot9=1u<<9,Slot10=1u<<10,Slot11=1u<<11,Slot12=1u<<12,Slot13=1u<<13,Slot14=1u<<14,Slot15=1u<<15,Slot16=1u<<16,Slot17=1u<<17,Slot18=1u<<18,Slot19=1u<<19,Slot20=1u<<20,Slot21=1u<<21,Slot22=1u<<22,Slot23=1u<<23,Slot24=1u<<24,Slot25=1u<<25,Slot26=1u<<26,Slot27=1u<<27,Slot28=1u<<28,Slot29=1u<<29,Slot30=1u<<30,Slot31=1u<<31,
+ // @formatter:on
+ All = uint.MaxValue,
+ }
+
///
/// The asset properties proxy object.
///
@@ -34,11 +45,14 @@ namespace FlaxEditor.Windows.Assets
public CollisionDataType Type;
[EditorOrder(10), EditorDisplay("General"), Tooltip("Source model asset to use for collision data generation")]
- public Model Model;
+ public ModelBase Model;
[EditorOrder(20), Limit(0, 5), EditorDisplay("General", "Model LOD Index"), Tooltip("Source model LOD index to use for collision data generation (will be clamped to the actual model LODs collection size)")]
public int ModelLodIndex;
+ [EditorOrder(30), EditorDisplay("General"), Tooltip("The source model material slots mask. One bit per-slot. Can be sued to exclude particular material slots from collision cooking.")]
+ public MaterialSlotsMask MaterialSlotsMask = MaterialSlotsMask.All;
+
[EditorOrder(100), EditorDisplay("Convex Mesh", "Convex Flags"), Tooltip("Convex mesh generation flags")]
public ConvexMeshGenerationFlags ConvexFlags;
@@ -88,28 +102,23 @@ namespace FlaxEditor.Windows.Assets
private class CookData : CreateFileEntry
{
- private PropertiesProxy Proxy;
- private CollisionDataType Type;
- private Model Model;
- private int ModelLodIndex;
- private ConvexMeshGenerationFlags ConvexFlags;
- private int ConvexVertexLimit;
+ public PropertiesProxy Proxy;
+ public CollisionDataType Type;
+ public ModelBase Model;
+ public int ModelLodIndex;
+ public uint MaterialSlotsMask;
+ public ConvexMeshGenerationFlags ConvexFlags;
+ public int ConvexVertexLimit;
- public CookData(PropertiesProxy proxy, string resultUrl, CollisionDataType type, Model model, int modelLodIndex, ConvexMeshGenerationFlags convexFlags, int convexVertexLimit)
+ public CookData(string resultUrl)
: base("Collision Data", resultUrl)
{
- Proxy = proxy;
- Type = type;
- Model = model;
- ModelLodIndex = modelLodIndex;
- ConvexFlags = convexFlags;
- ConvexVertexLimit = convexVertexLimit;
}
///
public override bool Create()
{
- bool failed = FlaxEditor.Editor.CookMeshCollision(ResultUrl, Type, Model, ModelLodIndex, ConvexFlags, ConvexVertexLimit);
+ bool failed = FlaxEditor.Editor.CookMeshCollision(ResultUrl, Type, Model, ModelLodIndex, MaterialSlotsMask, ConvexFlags, ConvexVertexLimit);
Proxy._isCooking = false;
Proxy.Window.UpdateWiresModel();
@@ -121,7 +130,16 @@ namespace FlaxEditor.Windows.Assets
public void Cook()
{
_isCooking = true;
- Window.Editor.ContentImporting.Create(new CookData(this, Asset.Path, Type, Model, ModelLodIndex, ConvexFlags, ConvexVertexLimit));
+ Window.Editor.ContentImporting.Create(new CookData(Asset.Path)
+ {
+ Proxy = this,
+ Type = Type,
+ Model = Model,
+ ModelLodIndex = ModelLodIndex,
+ MaterialSlotsMask = (uint)MaterialSlotsMask,
+ ConvexFlags = ConvexFlags,
+ ConvexVertexLimit = ConvexVertexLimit,
+ });
}
public void OnLoad(CollisionDataWindow window)
@@ -135,7 +153,7 @@ namespace FlaxEditor.Windows.Assets
Type = options.Type;
if (Type == CollisionDataType.None)
Type = CollisionDataType.ConvexMesh;
- Model = FlaxEngine.Content.LoadAsync(options.Model);
+ Model = FlaxEngine.Content.LoadAsync(options.Model);
ModelLodIndex = options.ModelLodIndex;
ConvexFlags = options.ConvexFlags;
ConvexVertexLimit = options.ConvexVertexLimit;
@@ -151,7 +169,7 @@ namespace FlaxEditor.Windows.Assets
}
private readonly SplitPanel _split;
- private readonly ModelPreview _preview;
+ private readonly ModelBasePreview _preview;
private readonly CustomEditorPresenter _propertiesPresenter;
private readonly PropertiesProxy _properties;
private Model _collisionWiresModel;
@@ -176,7 +194,7 @@ namespace FlaxEditor.Windows.Assets
};
// Model preview
- _preview = new ModelPreview(true)
+ _preview = new ModelBasePreview(true)
{
ViewportCamera = new FPSCamera(),
Parent = _split.Panel1
@@ -195,7 +213,7 @@ namespace FlaxEditor.Windows.Assets
// Sync helper actor size with actual preview model (preview scales model for better usage experience)
if (_collisionWiresShowActor && _collisionWiresShowActor.IsActive)
{
- _collisionWiresShowActor.Transform = _preview.PreviewActor.Transform;
+ _collisionWiresShowActor.Transform = _preview.StaticModel.Transform;
}
base.Update(deltaTime);
@@ -230,14 +248,14 @@ namespace FlaxEditor.Windows.Assets
}
_collisionWiresShowActor.Model = _collisionWiresModel;
_collisionWiresShowActor.SetMaterial(0, FlaxEngine.Content.LoadAsyncInternal(EditorAssets.WiresDebugMaterial));
- _preview.Model = FlaxEngine.Content.LoadAsync(_asset.Options.Model);
+ _preview.Asset = FlaxEngine.Content.LoadAsync(_asset.Options.Model);
}
///
protected override void UnlinkItem()
{
_properties.OnClean();
- _preview.Model = null;
+ _preview.Asset = null;
base.UnlinkItem();
}
@@ -245,7 +263,7 @@ namespace FlaxEditor.Windows.Assets
///
protected override void OnAssetLinked()
{
- _preview.Model = null;
+ _preview.Asset = null;
base.OnAssetLinked();
}
diff --git a/Source/Editor/Windows/Assets/JsonAssetWindow.cs b/Source/Editor/Windows/Assets/JsonAssetWindow.cs
index 779c8cc4e..b35478b8d 100644
--- a/Source/Editor/Windows/Assets/JsonAssetWindow.cs
+++ b/Source/Editor/Windows/Assets/JsonAssetWindow.cs
@@ -17,6 +17,9 @@ namespace FlaxEditor.Windows.Assets
{
private readonly CustomEditorPresenter _presenter;
private readonly ToolStripButton _saveButton;
+ private readonly ToolStripButton _undoButton;
+ private readonly ToolStripButton _redoButton;
+ private readonly Undo _undo;
private object _object;
private bool _isRegisteredForScriptsReload;
@@ -24,8 +27,16 @@ namespace FlaxEditor.Windows.Assets
public JsonAssetWindow(Editor editor, AssetItem item)
: base(editor, item)
{
+ // Undo
+ _undo = new Undo();
+ _undo.UndoDone += OnUndoRedo;
+ _undo.RedoDone += OnUndoRedo;
+
// Toolstrip
_saveButton = (ToolStripButton)_toolstrip.AddButton(editor.Icons.Save32, Save).LinkTooltip("Save");
+ _toolstrip.AddSeparator();
+ _undoButton = (ToolStripButton)_toolstrip.AddButton(Editor.Icons.Undo32, _undo.PerformUndo).LinkTooltip("Undo (Ctrl+Z)");
+ _redoButton = (ToolStripButton)_toolstrip.AddButton(Editor.Icons.Redo32, _undo.PerformRedo).LinkTooltip("Redo (Ctrl+Y)");
// Panel
var panel = new Panel(ScrollBars.Vertical)
@@ -36,9 +47,19 @@ namespace FlaxEditor.Windows.Assets
};
// Properties
- _presenter = new CustomEditorPresenter(null, "Loading...");
+ _presenter = new CustomEditorPresenter(_undo, "Loading...");
_presenter.Panel.Parent = panel;
_presenter.Modified += MarkAsEdited;
+
+ // Setup input actions
+ InputActions.Add(options => options.Undo, _undo.PerformUndo);
+ InputActions.Add(options => options.Redo, _undo.PerformRedo);
+ }
+
+ private void OnUndoRedo(IUndoAction action)
+ {
+ MarkAsEdited();
+ UpdateToolstrip();
}
private void OnScriptsReloadBegin()
@@ -64,13 +85,14 @@ namespace FlaxEditor.Windows.Assets
}
ClearEditedFlag();
- _item.RefreshThumbnail();
}
///
protected override void UpdateToolstrip()
{
_saveButton.Enabled = IsEdited;
+ _undoButton.Enabled = _undo.CanUndo;
+ _redoButton.Enabled = _undo.CanRedo;
base.UpdateToolstrip();
}
@@ -80,6 +102,7 @@ namespace FlaxEditor.Windows.Assets
{
_object = Asset.CreateInstance();
_presenter.Select(_object);
+ _undo.Clear();
ClearEditedFlag();
// Auto-close on scripting reload if json asset is from game scripts (it might be reloaded)
diff --git a/Source/Editor/Windows/Assets/LocalizedStringTableWindow.cs b/Source/Editor/Windows/Assets/LocalizedStringTableWindow.cs
new file mode 100644
index 000000000..ee48284db
--- /dev/null
+++ b/Source/Editor/Windows/Assets/LocalizedStringTableWindow.cs
@@ -0,0 +1,212 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+using System;
+using System.Collections.Generic;
+using FlaxEditor.Content;
+using FlaxEditor.CustomEditors;
+using FlaxEditor.GUI;
+using FlaxEngine;
+using FlaxEngine.GUI;
+using FlaxEngine.Utilities;
+
+namespace FlaxEditor.Windows.Assets
+{
+ ///
+ /// Editor window to view/modify asset.
+ ///
+ ///
+ ///
+ public sealed class LocalizedStringTableWindow : AssetEditorWindowBase
+ {
+ private readonly CustomEditorPresenter _presenter;
+ private readonly ToolStripButton _saveButton;
+ private readonly ToolStripButton _undoButton;
+ private readonly ToolStripButton _redoButton;
+ private readonly Undo _undo;
+ private Proxy _proxy;
+
+ private class EntryEditor : CustomEditor
+ {
+ private TextBox[] _textBoxes;
+ private bool _isRefreshing;
+
+ public override void Initialize(LayoutElementsContainer layout)
+ {
+ var values = (string[])Values[0];
+ if (values == null || values.Length == 0)
+ {
+ values = new string[1];
+ values[0] = string.Empty;
+ }
+ if (_textBoxes == null || _textBoxes.Length != values.Length)
+ _textBoxes = new TextBox[values.Length];
+ for (int i = 0; i < values.Length; i++)
+ {
+ var value = values[i];
+ var textBox = layout.TextBox(value.IsMultiline());
+ textBox.TextBox.Tag = i;
+ textBox.TextBox.Text = value;
+ textBox.TextBox.TextBoxEditEnd += OnEditEnd;
+ _textBoxes[i] = textBox.TextBox;
+ }
+ }
+
+ public override void Refresh()
+ {
+ base.Refresh();
+
+ var values = (string[])Values[0];
+ if (values != null && values.Length == _textBoxes.Length)
+ {
+ _isRefreshing = true;
+ var style = FlaxEngine.GUI.Style.Current;
+ var wrongColor = new Color(1.0f, 0.0f, 0.02745f, 1.0f);
+ var wrongColorBorder = Color.Lerp(wrongColor, style.TextBoxBackground, 0.6f);
+ for (int i = 0; i < _textBoxes.Length; i++)
+ {
+ var textBox = _textBoxes[i];
+ if (!textBox.IsEditing)
+ {
+ textBox.Text = values[i];
+ if (string.IsNullOrEmpty(textBox.Text))
+ {
+ textBox.BorderColor = wrongColorBorder;
+ textBox.BorderSelectedColor = wrongColor;
+ }
+ else
+ {
+ textBox.BorderColor = Color.Transparent;
+ textBox.BorderSelectedColor = style.BackgroundSelected;
+ }
+ }
+ }
+ _isRefreshing = false;
+ }
+ }
+
+ protected override void Deinitialize()
+ {
+ base.Deinitialize();
+
+ _textBoxes = null;
+ _isRefreshing = false;
+ }
+
+ private void OnEditEnd(TextBoxBase textBox)
+ {
+ if (_isRefreshing)
+ return;
+ var values = (string[])Values[0];
+ var length = Mathf.Max(values?.Length ?? 0, 1);
+ var toSet = new string[length];
+ if (values != null && values.Length == length)
+ Array.Copy(values, toSet, length);
+ var index = (int)textBox.Tag;
+ toSet[index] = textBox.Text;
+ SetValue(toSet);
+ }
+ }
+
+ private class Proxy
+ {
+ [EditorOrder(0), EditorDisplay("General"), Tooltip("The locale of the localized string table (eg. pl-PL)."),]
+ [CustomEditor(typeof(FlaxEditor.CustomEditors.Editors.CultureInfoEditor))]
+ public string Locale;
+
+ [EditorOrder(10), EditorDisplay("Entries", EditorDisplayAttribute.InlineStyle), Tooltip("The string table. Maps the message id into the localized text. For plural messages the list contains separate items for value numbers.")]
+ [Collection(Spacing = 10, OverrideEditorTypeName = "FlaxEditor.Windows.Assets.LocalizedStringTableWindow+EntryEditor")]
+ public Dictionary Entries;
+ }
+
+ ///
+ public LocalizedStringTableWindow(Editor editor, AssetItem item)
+ : base(editor, item)
+ {
+ // Undo
+ _undo = new Undo();
+ _undo.UndoDone += OnUndoRedo;
+ _undo.RedoDone += OnUndoRedo;
+
+ // Toolstrip
+ _saveButton = (ToolStripButton)_toolstrip.AddButton(editor.Icons.Save32, Save).LinkTooltip("Save");
+ _toolstrip.AddSeparator();
+ _undoButton = (ToolStripButton)_toolstrip.AddButton(Editor.Icons.Undo32, _undo.PerformUndo).LinkTooltip("Undo (Ctrl+Z)");
+ _redoButton = (ToolStripButton)_toolstrip.AddButton(Editor.Icons.Redo32, _undo.PerformRedo).LinkTooltip("Redo (Ctrl+Y)");
+
+ // Panel
+ var panel = new Panel(ScrollBars.Vertical)
+ {
+ AnchorPreset = AnchorPresets.StretchAll,
+ Offsets = new Margin(0, 0, _toolstrip.Bottom, 0),
+ Parent = this
+ };
+
+ // Properties
+ _presenter = new CustomEditorPresenter(_undo, "Loading...");
+ _presenter.Panel.Parent = panel;
+ _presenter.Modified += MarkAsEdited;
+
+ // Setup input actions
+ InputActions.Add(options => options.Undo, _undo.PerformUndo);
+ InputActions.Add(options => options.Redo, _undo.PerformRedo);
+ }
+
+ private void OnUndoRedo(IUndoAction action)
+ {
+ MarkAsEdited();
+ UpdateToolstrip();
+ }
+
+ ///
+ public override void Save()
+ {
+ if (!IsEdited)
+ return;
+
+ _asset.Locale = _proxy.Locale;
+ _asset.Entries = _proxy.Entries;
+ if (_asset.Save(_item.Path))
+ {
+ Editor.LogError("Cannot save asset.");
+ return;
+ }
+
+ ClearEditedFlag();
+ }
+
+ ///
+ protected override void UpdateToolstrip()
+ {
+ _saveButton.Enabled = IsEdited;
+ _undoButton.Enabled = _undo.CanUndo;
+ _redoButton.Enabled = _undo.CanRedo;
+
+ base.UpdateToolstrip();
+ }
+
+ ///
+ protected override void OnAssetLoaded()
+ {
+ _proxy = new Proxy
+ {
+ Locale = _asset.Locale,
+ Entries = _asset.Entries,
+ };
+ _presenter.Select(_proxy);
+ _undo.Clear();
+ ClearEditedFlag();
+
+ base.OnAssetLoaded();
+ }
+
+ ///
+ public override void OnItemReimported(ContentItem item)
+ {
+ // Refresh the properties (will get new data in OnAssetLoaded)
+ _presenter.Deselect();
+ ClearEditedFlag();
+
+ base.OnItemReimported(item);
+ }
+ }
+}
diff --git a/Source/Editor/Windows/Assets/ModelWindow.cs b/Source/Editor/Windows/Assets/ModelWindow.cs
index b16a01a73..9032f256b 100644
--- a/Source/Editor/Windows/Assets/ModelWindow.cs
+++ b/Source/Editor/Windows/Assets/ModelWindow.cs
@@ -565,7 +565,6 @@ namespace FlaxEditor.Windows.Assets
public UVsLayoutPreviewControl()
{
Offsets = new Margin(4);
- AnchorPreset = AnchorPresets.HorizontalStretchMiddle;
AutomaticInvalidate = false;
}
@@ -619,9 +618,9 @@ namespace FlaxEditor.Windows.Assets
}
///
- protected override void DrawChildren()
+ public override void DrawSelf()
{
- base.DrawChildren();
+ base.DrawSelf();
var size = Size;
if (_channel == UVChannel.None || size.MaxValue < 5.0f)
diff --git a/Source/Editor/Windows/Assets/SkinnedModelWindow.cs b/Source/Editor/Windows/Assets/SkinnedModelWindow.cs
index f3d228f45..37318c49b 100644
--- a/Source/Editor/Windows/Assets/SkinnedModelWindow.cs
+++ b/Source/Editor/Windows/Assets/SkinnedModelWindow.cs
@@ -114,9 +114,9 @@ namespace FlaxEditor.Windows.Assets
}
///
- public override void Draw()
+ public override void DrawSelf()
{
- base.Draw();
+ base.DrawSelf();
var style = Style.Current;
var asset = _window.Asset;
@@ -676,7 +676,6 @@ namespace FlaxEditor.Windows.Assets
public UVsLayoutPreviewControl()
{
Offsets = new Margin(4);
- AnchorPreset = AnchorPresets.HorizontalStretchMiddle;
AutomaticInvalidate = false;
}
diff --git a/Source/Editor/Windows/GameCookerWindow.cs b/Source/Editor/Windows/GameCookerWindow.cs
index 2562f3db8..855a0d661 100644
--- a/Source/Editor/Windows/GameCookerWindow.cs
+++ b/Source/Editor/Windows/GameCookerWindow.cs
@@ -43,6 +43,7 @@ namespace FlaxEditor.Windows
{ PlatformType.PS4, new PS4() },
{ PlatformType.XboxScarlett, new XboxScarlett() },
{ PlatformType.Android, new Android() },
+ { PlatformType.Switch, new Switch() },
};
public BuildTabProxy(GameCookerWindow win, PlatformSelector platformSelector)
@@ -57,6 +58,7 @@ namespace FlaxEditor.Windows
PerPlatformOptions[PlatformType.PS4].Init("Output/PS4", "PS4");
PerPlatformOptions[PlatformType.XboxScarlett].Init("Output/XboxScarlett", "XboxScarlett");
PerPlatformOptions[PlatformType.Android].Init("Output/Android", "Android");
+ PerPlatformOptions[PlatformType.Switch].Init("Output/Switch", "Switch");
}
public abstract class Platform
@@ -188,6 +190,11 @@ namespace FlaxEditor.Windows
protected override BuildPlatform BuildPlatform => BuildPlatform.AndroidARM64;
}
+ public class Switch : Platform
+ {
+ protected override BuildPlatform BuildPlatform => BuildPlatform.Switch;
+ }
+
public class Editor : CustomEditor
{
private PlatformType _platform;
@@ -229,6 +236,9 @@ namespace FlaxEditor.Windows
case PlatformType.Android:
name = "Android";
break;
+ case PlatformType.Switch:
+ name = "Switch";
+ break;
default:
name = CustomEditorsUtil.GetPropertyNameUI(_platform.ToString());
break;
diff --git a/Source/Editor/Windows/SplashScreen.cpp b/Source/Editor/Windows/SplashScreen.cpp
index 2d2d26ead..cd0c70f02 100644
--- a/Source/Editor/Windows/SplashScreen.cpp
+++ b/Source/Editor/Windows/SplashScreen.cpp
@@ -120,6 +120,17 @@ const Char* SplashScreenQuotes[] =
TEXT("All we had to do was follow the damn train, CJ"),
TEXT("28 stab wounds"),
TEXT("Here we go again"),
+ TEXT("@everyone"),
+ TEXT("uwu some spiders on the ceiling"),
+ TEXT("There you are you little shit"),
+ TEXT("potato"),
+ TEXT("python is a programming snek"),
+ TEXT("Flax will start when pigs will fly"),
+ TEXT("I'm the android sent by CyberLife"),
+ TEXT("fancy-ass ray tracing rtx on lighting"),
+ TEXT("ZOINKS"),
+ TEXT("Scooby dooby doo"),
+ TEXT("You shall not load"),
};
SplashScreen::~SplashScreen()
diff --git a/Source/Engine/Animations/AnimationData.h b/Source/Engine/Animations/AnimationData.h
index 139c06aa9..6a782d8d6 100644
--- a/Source/Engine/Animations/AnimationData.h
+++ b/Source/Engine/Animations/AnimationData.h
@@ -2,7 +2,8 @@
#pragma once
-#include "Curve.h"
+#include "Engine/Core/Types/String.h"
+#include "Engine/Animations/Curve.h"
#include "Engine/Core/Math/Transform.h"
///
diff --git a/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp b/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp
index 2497dfe3e..e13714f2c 100644
--- a/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp
+++ b/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp
@@ -636,7 +636,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
transform.Scale = (Vector3)tryGetValue(node->GetBox(4), Vector3::One);
// Skip if no change will be performed
- if (boneIndex < 0 || boneIndex >= _skeletonBonesCount || transformMode == BoneTransformMode::None || transform.IsIdentity())
+ if (boneIndex < 0 || boneIndex >= _skeletonBonesCount || transformMode == BoneTransformMode::None || (transformMode == BoneTransformMode::Add && transform.IsIdentity()))
{
// Pass through the input
value = Value::Null;
@@ -1628,7 +1628,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
transform.Scale = (Vector3)tryGetValue(node->GetBox(4), Vector3::One);
// Skip if no change will be performed
- if (nodeIndex < 0 || nodeIndex >= _skeletonNodesCount || transformMode == BoneTransformMode::None || transform.IsIdentity())
+ if (nodeIndex < 0 || nodeIndex >= _skeletonNodesCount || transformMode == BoneTransformMode::None || (transformMode == BoneTransformMode::Add && transform.IsIdentity()))
{
// Pass through the input
value = Value::Null;
diff --git a/Source/Engine/Audio/Audio.Build.cs b/Source/Engine/Audio/Audio.Build.cs
index d4b63e82b..6a99a11c2 100644
--- a/Source/Engine/Audio/Audio.Build.cs
+++ b/Source/Engine/Audio/Audio.Build.cs
@@ -46,6 +46,10 @@ public class Audio : EngineModule
case TargetPlatform.Android:
useOpenAL = true;
break;
+ case TargetPlatform.Switch:
+ options.SourcePaths.Add(Path.Combine(Globals.EngineRoot, "Source", "Platforms", "Switch", "Engine", "Audio"));
+ options.CompileEnv.PreprocessorDefinitions.Add("AUDIO_API_SWITCH");
+ break;
default: throw new InvalidPlatformException(options.Platform.Target);
}
diff --git a/Source/Engine/CSG/HalfEdge.h b/Source/Engine/CSG/HalfEdge.h
index 3a054aff0..e9bd38a34 100644
--- a/Source/Engine/CSG/HalfEdge.h
+++ b/Source/Engine/CSG/HalfEdge.h
@@ -2,6 +2,8 @@
#pragma once
+#include "Engine/Core/Types/BaseTypes.h"
+
namespace CSG
{
///
diff --git a/Source/Engine/Content/Asset.cpp b/Source/Engine/Content/Asset.cpp
index 5f11cfb54..9bad11533 100644
--- a/Source/Engine/Content/Asset.cpp
+++ b/Source/Engine/Content/Asset.cpp
@@ -225,7 +225,7 @@ bool Asset::WaitForLoaded(double timeoutInMilliseconds)
while (!Engine::ShouldExit())
{
// Try to execute content tasks
- while (task->IsQueued())
+ while (task->IsQueued() && !Engine::ShouldExit())
{
// Pick this task from the queue
ContentLoadTask* tmp;
diff --git a/Source/Engine/Content/AssetReference.h b/Source/Engine/Content/AssetReference.h
index 40f57337d..0956e82be 100644
--- a/Source/Engine/Content/AssetReference.h
+++ b/Source/Engine/Content/AssetReference.h
@@ -274,3 +274,9 @@ public:
OnSet(asset);
}
};
+
+template
+uint32 GetHash(const AssetReference& key)
+{
+ return GetHash(key.GetID());
+}
diff --git a/Source/Engine/Content/Assets/Model.cpp b/Source/Engine/Content/Assets/Model.cpp
index 8cdd0601e..d6e8f1809 100644
--- a/Source/Engine/Content/Assets/Model.cpp
+++ b/Source/Engine/Content/Assets/Model.cpp
@@ -396,21 +396,21 @@ bool Model::Save(bool withMeshDataFromGpu, const StringView& path)
auto& meshData = meshesData[meshIndex];
// Vertex Buffer 0 (required)
- auto task = mesh.ExtractDataAsync(MeshBufferType::Vertex0, meshData.VB0);
+ auto task = mesh.DownloadDataGPUAsync(MeshBufferType::Vertex0, meshData.VB0);
if (task == nullptr)
return true;
task->Start();
tasks.Add(task);
// Vertex Buffer 1 (required)
- task = mesh.ExtractDataAsync(MeshBufferType::Vertex1, meshData.VB1);
+ task = mesh.DownloadDataGPUAsync(MeshBufferType::Vertex1, meshData.VB1);
if (task == nullptr)
return true;
task->Start();
tasks.Add(task);
// Vertex Buffer 2 (optional)
- task = mesh.ExtractDataAsync(MeshBufferType::Vertex2, meshData.VB2);
+ task = mesh.DownloadDataGPUAsync(MeshBufferType::Vertex2, meshData.VB2);
if (task)
{
task->Start();
@@ -418,7 +418,7 @@ bool Model::Save(bool withMeshDataFromGpu, const StringView& path)
}
// Index Buffer (required)
- task = mesh.ExtractDataAsync(MeshBufferType::Index, meshData.IB);
+ task = mesh.DownloadDataGPUAsync(MeshBufferType::Index, meshData.IB);
if (task == nullptr)
return true;
task->Start();
@@ -618,6 +618,19 @@ void Model::SetupMaterialSlots(int32 slotsCount)
}
}
+int32 Model::GetLODsCount() const
+{
+ return LODs.Count();
+}
+
+void Model::GetMeshes(Array& meshes, int32 lodIndex)
+{
+ auto& lod = LODs[lodIndex];
+ meshes.Resize(lod.Meshes.Count());
+ for (int32 meshIndex = 0; meshIndex < lod.Meshes.Count(); meshIndex++)
+ meshes[meshIndex] = &lod.Meshes[meshIndex];
+}
+
void Model::InitAsVirtual()
{
// Init with a single LOD and one mesh
@@ -628,6 +641,21 @@ void Model::InitAsVirtual()
BinaryAsset::InitAsVirtual();
}
+#if USE_EDITOR
+
+void Model::GetReferences(Array& output) const
+{
+ // Base
+ BinaryAsset::GetReferences(output);
+
+ for (int32 i = 0; i < MaterialSlots.Count(); i++)
+ {
+ output.Add(MaterialSlots[i].Material.GetID());
+ }
+}
+
+#endif
+
int32 Model::GetMaxResidency() const
{
return LODs.Count();
@@ -837,3 +865,33 @@ AssetChunksFlag Model::getChunksToPreload() const
// Note: we don't preload any LODs here because it's done by the Streaming Manager
return GET_CHUNK_FLAG(0);
}
+
+void ModelBase::SetupMaterialSlots(int32 slotsCount)
+{
+ CHECK(slotsCount >= 0 && slotsCount < 4096);
+ if (!IsVirtual() && WaitForLoaded())
+ return;
+
+ ScopeLock lock(Locker);
+
+ const int32 prevCount = MaterialSlots.Count();
+ MaterialSlots.Resize(slotsCount, false);
+
+ // Initialize slot names
+ for (int32 i = prevCount; i < slotsCount; i++)
+ MaterialSlots[i].Name = String::Format(TEXT("Material {0}"), i + 1);
+}
+
+MaterialSlot* ModelBase::GetSlot(const StringView& name)
+{
+ MaterialSlot* result = nullptr;
+ for (auto& slot : MaterialSlots)
+ {
+ if (slot.Name == name)
+ {
+ result = &slot;
+ break;
+ }
+ }
+ return result;
+}
diff --git a/Source/Engine/Content/Assets/Model.h b/Source/Engine/Content/Assets/Model.h
index e96b47d90..62a2dc6a4 100644
--- a/Source/Engine/Content/Assets/Model.h
+++ b/Source/Engine/Content/Assets/Model.h
@@ -55,15 +55,6 @@ public:
return LODs.HasItems();
}
- ///
- /// Gets amount of the level of details in the model
- ///
- /// Amount of the level of details in the model
- FORCE_INLINE int32 GetLODsCount() const
- {
- return LODs.Count();
- }
-
///
/// Gets the amount of loaded model LODs.
///
@@ -237,18 +228,11 @@ public:
// [ModelBase]
void SetupMaterialSlots(int32 slotsCount) override;
+ int32 GetLODsCount() const override;
+ void GetMeshes(Array& meshes, int32 lodIndex = 0) override;
void InitAsVirtual() override;
#if USE_EDITOR
- void GetReferences(Array& output) const override
- {
- // Base
- BinaryAsset::GetReferences(output);
-
- for (int32 i = 0; i < MaterialSlots.Count(); i++)
- {
- output.Add(MaterialSlots[i].Material.GetID());
- }
- }
+ void GetReferences(Array& output) const override;
#endif
// [StreamableResource]
diff --git a/Source/Engine/Content/Assets/ModelBase.h b/Source/Engine/Content/Assets/ModelBase.h
index 89805f3c0..527a7ac61 100644
--- a/Source/Engine/Content/Assets/ModelBase.h
+++ b/Source/Engine/Content/Assets/ModelBase.h
@@ -7,6 +7,8 @@
#include "Engine/Graphics/Models/MaterialSlot.h"
#include "Engine/Streaming/StreamableResource.h"
+class MeshBase;
+
///
/// Base class for asset types that can contain a model resource.
///
@@ -44,38 +46,23 @@ public:
///
/// Resizes the material slots collection. Updates meshes that were using removed slots.
///
- API_FUNCTION() virtual void SetupMaterialSlots(int32 slotsCount)
- {
- CHECK(slotsCount >= 0 && slotsCount < 4096);
- if (!IsVirtual() && WaitForLoaded())
- return;
-
- ScopeLock lock(Locker);
-
- const int32 prevCount = MaterialSlots.Count();
- MaterialSlots.Resize(slotsCount, false);
-
- // Initialize slot names
- for (int32 i = prevCount; i < slotsCount; i++)
- MaterialSlots[i].Name = String::Format(TEXT("Material {0}"), i + 1);
- }
+ API_FUNCTION() virtual void SetupMaterialSlots(int32 slotsCount);
///
/// Gets the material slot by the name.
///
/// The slot name.
/// The material slot with the given name or null if cannot find it (asset may be not loaded yet).
- API_FUNCTION() MaterialSlot* GetSlot(const StringView& name)
- {
- MaterialSlot* result = nullptr;
- for (auto& slot : MaterialSlots)
- {
- if (slot.Name == name)
- {
- result = &slot;
- break;
- }
- }
- return result;
- }
+ API_FUNCTION() MaterialSlot* GetSlot(const StringView& name);
+
+ ///
+ /// Gets amount of the level of details in the model.
+ ///
+ /// Amount of the level of details in the model.
+ virtual int32 GetLODsCount() const = 0;
+
+ ///
+ /// Gets the meshes for a particular LOD index.
+ ///
+ virtual void GetMeshes(Array& meshes, int32 lodIndex = 0) = 0;
};
diff --git a/Source/Engine/Content/Assets/SkinnedModel.cpp b/Source/Engine/Content/Assets/SkinnedModel.cpp
index dfccfec19..7c498b8e8 100644
--- a/Source/Engine/Content/Assets/SkinnedModel.cpp
+++ b/Source/Engine/Content/Assets/SkinnedModel.cpp
@@ -137,6 +137,18 @@ Array SkinnedModel::GetBlendShapes()
return result;
}
+ContentLoadTask* SkinnedModel::RequestLODDataAsync(int32 lodIndex)
+{
+ const int32 chunkIndex = SKINNED_MODEL_LOD_TO_CHUNK_INDEX(lodIndex);
+ return RequestChunkDataAsync(chunkIndex);
+}
+
+void SkinnedModel::GetLODData(int32 lodIndex, BytesContainer& data) const
+{
+ const int32 chunkIndex = SKINNED_MODEL_LOD_TO_CHUNK_INDEX(lodIndex);
+ GetChunkData(chunkIndex, data);
+}
+
bool SkinnedModel::Intersects(const Ray& ray, const Matrix& world, float& distance, Vector3& normal, SkinnedMesh** mesh, int32 lodIndex)
{
return LODs[lodIndex].Intersects(ray, world, distance, normal, mesh);
@@ -389,7 +401,7 @@ bool SkinnedModel::Save(bool withMeshDataFromGpu, const StringView& path)
{
auto& slot = MaterialSlots[materialSlotIndex];
- const auto id =slot.Material.GetID();
+ const auto id = slot.Material.GetID();
stream->Write(&id);
stream->WriteByte(static_cast(slot.ShadowsMode));
stream->WriteString(slot.Name, 11);
@@ -505,14 +517,14 @@ bool SkinnedModel::Save(bool withMeshDataFromGpu, const StringView& path)
auto& meshData = meshesData[meshIndex];
// Vertex Buffer 0 (required)
- auto task = mesh.DownloadDataAsyncGPU(MeshBufferType::Vertex0, meshData.VB0);
+ auto task = mesh.DownloadDataGPUAsync(MeshBufferType::Vertex0, meshData.VB0);
if (task == nullptr)
return true;
task->Start();
tasks.Add(task);
// Index Buffer (required)
- task = mesh.DownloadDataAsyncGPU(MeshBufferType::Index, meshData.IB);
+ task = mesh.DownloadDataGPUAsync(MeshBufferType::Index, meshData.IB);
if (task == nullptr)
return true;
task->Start();
@@ -701,6 +713,19 @@ void SkinnedModel::SetupMaterialSlots(int32 slotsCount)
}
}
+int32 SkinnedModel::GetLODsCount() const
+{
+ return LODs.Count();
+}
+
+void SkinnedModel::GetMeshes(Array& meshes, int32 lodIndex)
+{
+ auto& lod = LODs[lodIndex];
+ meshes.Resize(lod.Meshes.Count());
+ for (int32 meshIndex = 0; meshIndex < lod.Meshes.Count(); meshIndex++)
+ meshes[meshIndex] = &lod.Meshes[meshIndex];
+}
+
void SkinnedModel::InitAsVirtual()
{
// Init with one mesh and single bone
@@ -723,6 +748,21 @@ void SkinnedModel::InitAsVirtual()
BinaryAsset::InitAsVirtual();
}
+#if USE_EDITOR
+
+void SkinnedModel::GetReferences(Array& output) const
+{
+ // Base
+ BinaryAsset::GetReferences(output);
+
+ for (int32 i = 0; i < MaterialSlots.Count(); i++)
+ {
+ output.Add(MaterialSlots[i].Material.GetID());
+ }
+}
+
+#endif
+
int32 SkinnedModel::GetMaxResidency() const
{
return LODs.Count();
diff --git a/Source/Engine/Content/Assets/SkinnedModel.h b/Source/Engine/Content/Assets/SkinnedModel.h
index ce5f5f7ac..0dabcef05 100644
--- a/Source/Engine/Content/Assets/SkinnedModel.h
+++ b/Source/Engine/Content/Assets/SkinnedModel.h
@@ -61,15 +61,6 @@ public:
return LODs.HasItems();
}
- ///
- /// Gets amount of the level of details in the model
- ///
- /// Amount of the level of details in the model
- FORCE_INLINE int32 GetLODsCount() const
- {
- return LODs.Count();
- }
-
///
/// Gets the amount of loaded model LODs.
///
@@ -184,22 +175,14 @@ public:
///
/// Index of the LOD.
/// Task that will gather chunk data or null if already here.
- ContentLoadTask* RequestLODDataAsync(int32 lodIndex)
- {
- const int32 chunkIndex = SKINNED_MODEL_LOD_TO_CHUNK_INDEX(lodIndex);
- return RequestChunkDataAsync(chunkIndex);
- }
+ ContentLoadTask* RequestLODDataAsync(int32 lodIndex);
///
/// Gets the model LOD data (links bytes).
///
/// Index of the LOD.
/// The data (may be missing if failed to get it).
- void GetLODData(int32 lodIndex, BytesContainer& data) const
- {
- const int32 chunkIndex = SKINNED_MODEL_LOD_TO_CHUNK_INDEX(lodIndex);
- GetChunkData(chunkIndex, data);
- }
+ void GetLODData(int32 lodIndex, BytesContainer& data) const;
public:
@@ -300,18 +283,11 @@ public:
// [ModelBase]
void SetupMaterialSlots(int32 slotsCount) override;
+ int32 GetLODsCount() const override;
+ void GetMeshes(Array& meshes, int32 lodIndex = 0) override;
void InitAsVirtual() override;
#if USE_EDITOR
- void GetReferences(Array& output) const override
- {
- // Base
- BinaryAsset::GetReferences(output);
-
- for (int32 i = 0; i < MaterialSlots.Count(); i++)
- {
- output.Add(MaterialSlots[i].Material.GetID());
- }
- }
+ void GetReferences(Array& output) const override;
#endif
// [StreamableResource]
diff --git a/Source/Engine/Content/Cache/AssetsCache.cpp b/Source/Engine/Content/Cache/AssetsCache.cpp
index 71faef533..f8d3433ed 100644
--- a/Source/Engine/Content/Cache/AssetsCache.cpp
+++ b/Source/Engine/Content/Cache/AssetsCache.cpp
@@ -405,38 +405,42 @@ void AssetsCache::RegisterAssets(FlaxStorage* storage)
void AssetsCache::RegisterAsset(const Guid& id, const String& typeName, const StringView& path)
{
PROFILE_CPU();
-
ScopeLock lock(_locker);
- // Mark registry as draft
- _isDirty = true;
-
// Check if asset has been already added to the registry
bool isMissing = true;
for (auto i = _registry.Begin(); i.IsNotEnd(); ++i)
{
auto& e = i->Value;
- // Compare IDs
if (e.Info.ID == id)
{
- // Update registry entry
- e.Info.Path = path;
- e.Info.TypeName = typeName;
-
- // Back
+ if (e.Info.Path != path)
+ {
+ e.Info.Path = path;
+ _isDirty = true;
+ }
+ if (e.Info.TypeName != typeName)
+ {
+ e.Info.TypeName = typeName;
+ _isDirty = true;
+ }
isMissing = false;
break;
}
- // Compare paths
if (e.Info.Path == path)
{
- // Update registry entry
- e.Info.ID = id;
- e.Info.TypeName = typeName;
-
- // Back
+ if (e.Info.ID != id)
+ {
+ e.Info.Path = path;
+ _isDirty = true;
+ }
+ if (e.Info.TypeName != typeName)
+ {
+ e.Info.TypeName = typeName;
+ _isDirty = true;
+ }
isMissing = false;
break;
}
@@ -445,9 +449,8 @@ void AssetsCache::RegisterAsset(const Guid& id, const String& typeName, const St
if (isMissing)
{
LOG(Info, "Register asset {0}:{1} \'{2}\'", id, typeName, path);
-
- // Add new asset entry
_registry.Add(id, Entry(id, typeName, path));
+ _isDirty = true;
}
}
diff --git a/Source/Engine/Content/Factories/BinaryAssetFactory.h b/Source/Engine/Content/Factories/BinaryAssetFactory.h
index 25dd38aeb..d2af137b6 100644
--- a/Source/Engine/Content/Factories/BinaryAssetFactory.h
+++ b/Source/Engine/Content/Factories/BinaryAssetFactory.h
@@ -14,7 +14,7 @@ class FlaxStorage;
/// The binary assets factory base class.
///
///
-class BinaryAssetFactoryBase : public IAssetFactory
+class FLAXENGINE_API BinaryAssetFactoryBase : public IAssetFactory
{
public:
diff --git a/Source/Engine/Content/Factories/IAssetFactory.h b/Source/Engine/Content/Factories/IAssetFactory.h
index dbc7b1e90..b72f8e8e2 100644
--- a/Source/Engine/Content/Factories/IAssetFactory.h
+++ b/Source/Engine/Content/Factories/IAssetFactory.h
@@ -15,7 +15,7 @@ class IAssetUpgrader;
///
/// The asset objects factory.
///
-class IAssetFactory
+class FLAXENGINE_API IAssetFactory
{
public:
diff --git a/Source/Engine/Content/Factories/JsonAssetFactory.h b/Source/Engine/Content/Factories/JsonAssetFactory.h
index 0269ec596..988776186 100644
--- a/Source/Engine/Content/Factories/JsonAssetFactory.h
+++ b/Source/Engine/Content/Factories/JsonAssetFactory.h
@@ -10,7 +10,7 @@
/// The Json assets factory base class.
///
///
-class JsonAssetFactoryBase : public IAssetFactory
+class FLAXENGINE_API JsonAssetFactoryBase : public IAssetFactory
{
protected:
@@ -23,7 +23,6 @@ public:
{
return Create(info);
}
-
Asset* NewVirtual(const AssetInfo& info) override
{
return Create(info);
@@ -47,12 +46,13 @@ protected:
}
};
-#define REGISTER_JSON_ASSET(type, typeName) \
+#define REGISTER_JSON_ASSET(type, typeName, supportsVirtualAssets) \
const String type::TypeName = TEXT(typeName); \
class CONCAT_MACROS(Factory, type) : public JsonAssetFactory \
{ \
public: \
CONCAT_MACROS(Factory, type)() { IAssetFactory::Get().Add(type::TypeName, this); } \
~CONCAT_MACROS(Factory, type)() { IAssetFactory::Get().Remove(type::TypeName); } \
+ bool SupportsVirtualAssets() const override { return supportsVirtualAssets; } \
}; \
static CONCAT_MACROS(Factory, type) CONCAT_MACROS(CFactory, type)
diff --git a/Source/Engine/Content/JsonAsset.cpp b/Source/Engine/Content/JsonAsset.cpp
index 821c43f87..f84ba9f88 100644
--- a/Source/Engine/Content/JsonAsset.cpp
+++ b/Source/Engine/Content/JsonAsset.cpp
@@ -176,7 +176,7 @@ void JsonAssetBase::onRename(const StringView& newPath)
#endif
-REGISTER_JSON_ASSET(JsonAsset, "FlaxEngine.JsonAsset");
+REGISTER_JSON_ASSET(JsonAsset, "FlaxEngine.JsonAsset", true);
JsonAsset::JsonAsset(const SpawnParams& params, const AssetInfo* info)
: JsonAssetBase(params, info)
diff --git a/Source/Engine/Content/Loading/ContentLoadTask.h b/Source/Engine/Content/Loading/ContentLoadTask.h
index 94e8d5ec7..df13c8c43 100644
--- a/Source/Engine/Content/Loading/ContentLoadTask.h
+++ b/Source/Engine/Content/Loading/ContentLoadTask.h
@@ -3,6 +3,7 @@
#pragma once
#include "Engine/Threading/Task.h"
+#include "Engine/Core/Types/String.h"
class Asset;
class LoadingThread;
diff --git a/Source/Engine/Content/Upgraders/BinaryAssetUpgrader.h b/Source/Engine/Content/Upgraders/BinaryAssetUpgrader.h
index 2c2d0f03e..c97d9d53c 100644
--- a/Source/Engine/Content/Upgraders/BinaryAssetUpgrader.h
+++ b/Source/Engine/Content/Upgraders/BinaryAssetUpgrader.h
@@ -9,7 +9,7 @@
///
/// Binary asset upgrading context structure.
///
-struct AssetMigrationContext
+struct FLAXENGINE_API AssetMigrationContext
{
///
/// The input data.
@@ -63,7 +63,7 @@ typedef bool (*UpgradeHandler)(AssetMigrationContext& context);
/// Binary Assets Upgrader base class
///
///
-class BinaryAssetUpgrader : public IAssetUpgrader
+class FLAXENGINE_API BinaryAssetUpgrader : public IAssetUpgrader
{
public:
diff --git a/Source/Engine/Content/Upgraders/IAssetUpgrader.h b/Source/Engine/Content/Upgraders/IAssetUpgrader.h
index f54616a45..bc174859d 100644
--- a/Source/Engine/Content/Upgraders/IAssetUpgrader.h
+++ b/Source/Engine/Content/Upgraders/IAssetUpgrader.h
@@ -7,7 +7,7 @@
///
/// The assets upgrading objects interface.
///
-class IAssetUpgrader
+class FLAXENGINE_API IAssetUpgrader
{
public:
diff --git a/Source/Engine/Content/Upgraders/ModelAssetUpgrader.h b/Source/Engine/Content/Upgraders/ModelAssetUpgrader.h
index 17b2bda38..98bc630cb 100644
--- a/Source/Engine/Content/Upgraders/ModelAssetUpgrader.h
+++ b/Source/Engine/Content/Upgraders/ModelAssetUpgrader.h
@@ -8,6 +8,7 @@
#include "Engine/Serialization/MemoryReadStream.h"
#include "Engine/Serialization/MemoryWriteStream.h"
#include "Engine/Graphics/Models/ModelData.h"
+#include "Engine/Content/Asset.h"
///
/// Model Asset Upgrader
diff --git a/Source/Engine/Content/Upgraders/ShaderAssetUpgrader.h b/Source/Engine/Content/Upgraders/ShaderAssetUpgrader.h
index 827197009..d85079304 100644
--- a/Source/Engine/Content/Upgraders/ShaderAssetUpgrader.h
+++ b/Source/Engine/Content/Upgraders/ShaderAssetUpgrader.h
@@ -4,6 +4,7 @@
#include "BinaryAssetUpgrader.h"
#include "Engine/Platform/Platform.h"
+#include "Engine/Graphics/Shaders/Cache/ShaderStorage.h"
///
/// Material Asset and Shader Asset Upgrader
diff --git a/Source/Engine/Content/Upgraders/SkinnedModelAssetUpgrader.h b/Source/Engine/Content/Upgraders/SkinnedModelAssetUpgrader.h
index 9a5b4c5ae..ef0a21b6d 100644
--- a/Source/Engine/Content/Upgraders/SkinnedModelAssetUpgrader.h
+++ b/Source/Engine/Content/Upgraders/SkinnedModelAssetUpgrader.h
@@ -6,6 +6,11 @@
#include "Engine/Platform/Platform.h"
#include "Engine/Serialization/MemoryReadStream.h"
#include "Engine/Serialization/MemoryWriteStream.h"
+#include "Engine/Graphics/Models/Types.h"
+#include "Engine/Core/Math/BoundingBox.h"
+#include "Engine/Core/Math/BoundingSphere.h"
+#include "Engine/Core/Math/Matrix.h"
+#include "Engine/Core/Math/Transform.h"
///
/// Skinned Model Asset Upgrader
diff --git a/Source/Engine/Content/WeakAssetReference.h b/Source/Engine/Content/WeakAssetReference.h
index 4943fd0b5..49401bf25 100644
--- a/Source/Engine/Content/WeakAssetReference.h
+++ b/Source/Engine/Content/WeakAssetReference.h
@@ -229,3 +229,9 @@ public:
OnSet(asset);
}
};
+
+template
+uint32 GetHash(const WeakAssetReference& key)
+{
+ return GetHash(key.GetID());
+}
diff --git a/Source/Engine/ContentImporters/AssetsImportingManager.cpp b/Source/Engine/ContentImporters/AssetsImportingManager.cpp
index f1d048ca5..75aa4788d 100644
--- a/Source/Engine/ContentImporters/AssetsImportingManager.cpp
+++ b/Source/Engine/ContentImporters/AssetsImportingManager.cpp
@@ -31,6 +31,7 @@
#include "CreateParticleEmitterFunction.h"
#include "CreateAnimationGraphFunction.h"
#include "CreateVisualScript.h"
+#include "CreateJson.h"
// Tags used to detect asset creation mode
const String AssetsImportingManager::CreateTextureTag(TEXT("Texture"));
@@ -91,6 +92,10 @@ CreateAssetResult CreateAssetContext::Run(const CreateAssetFunction& callback)
if (result != CreateAssetResult::Ok)
return result;
+ // Skip for non-flax assets (eg. json resource or custom asset type)
+ if (!TargetAssetPath.EndsWith(ASSET_FILES_EXTENSION))
+ return CreateAssetResult::Ok;
+
// Validate assigned TypeID
if (Data.Header.TypeName.IsEmpty())
{
@@ -112,8 +117,7 @@ CreateAssetResult CreateAssetContext::Run(const CreateAssetFunction& callback)
}
// Save file
- result = Save();
-
+ result = FlaxStorage::Create(OutputPath, Data) ? CreateAssetResult::CannotSaveFile : CreateAssetResult::Ok;
if (result == CreateAssetResult::Ok)
{
_applyChangesResult = CreateAssetResult::Abort;
@@ -161,11 +165,6 @@ void CreateAssetContext::AddMeta(JsonWriter& writer) const
writer.String(Platform::GetUserName());
}
-CreateAssetResult CreateAssetContext::Save()
-{
- return FlaxStorage::Create(OutputPath, Data) ? CreateAssetResult::CannotSaveFile : CreateAssetResult::Ok;
-}
-
void CreateAssetContext::ApplyChanges()
{
// Get access
@@ -231,8 +230,6 @@ bool AssetsImportingManager::Create(const String& tag, const StringView& outputP
bool AssetsImportingManager::Import(const StringView& inputPath, const StringView& outputPath, Guid& assetId, void* arg)
{
- ASSERT(outputPath.EndsWith(StringView(ASSET_FILES_EXTENSION)));
-
LOG(Info, "Importing file '{0}' to '{1}'...", inputPath, outputPath);
// Check if input file exists
@@ -246,8 +243,7 @@ bool AssetsImportingManager::Import(const StringView& inputPath, const StringVie
const String extension = FileSystem::GetExtension(inputPath).ToLower();
// Special case for raw assets
- const String assetExtension = ASSET_FILES_EXTENSION;
- if (assetExtension.Compare(extension, StringSearchCase::IgnoreCase) == 0)
+ if (StringView(ASSET_FILES_EXTENSION).Compare(StringView(extension), StringSearchCase::IgnoreCase) == 0)
{
// Simply copy file (content layer will resolve duplicated IDs, etc.)
return FileSystem::CopyFile(outputPath, inputPath);
@@ -266,8 +262,6 @@ bool AssetsImportingManager::Import(const StringView& inputPath, const StringVie
bool AssetsImportingManager::ImportIfEdited(const StringView& inputPath, const StringView& outputPath, Guid& assetId, void* arg)
{
- ASSERT(outputPath.EndsWith(StringView(ASSET_FILES_EXTENSION)));
-
// Check if asset not exists
if (!FileSystem::FileExists(outputPath))
{
@@ -383,64 +377,67 @@ bool AssetsImportingManagerService::Init()
AssetImporter InBuildImporters[] =
{
// Textures and Cube Textures
- { TEXT("tga"), ImportTexture::Import },
- { TEXT("dds"), ImportTexture::Import },
- { TEXT("png"), ImportTexture::Import },
- { TEXT("bmp"), ImportTexture::Import },
- { TEXT("gif"), ImportTexture::Import },
- { TEXT("tiff"), ImportTexture::Import },
- { TEXT("tif"), ImportTexture::Import },
- { TEXT("jpeg"), ImportTexture::Import },
- { TEXT("jpg"), ImportTexture::Import },
- { TEXT("hdr"), ImportTexture::Import },
- { TEXT("raw"), ImportTexture::Import },
+ { TEXT("tga"), ASSET_FILES_EXTENSION, ImportTexture::Import },
+ { TEXT("dds"), ASSET_FILES_EXTENSION, ImportTexture::Import },
+ { TEXT("png"), ASSET_FILES_EXTENSION, ImportTexture::Import },
+ { TEXT("bmp"), ASSET_FILES_EXTENSION, ImportTexture::Import },
+ { TEXT("gif"), ASSET_FILES_EXTENSION, ImportTexture::Import },
+ { TEXT("tiff"), ASSET_FILES_EXTENSION, ImportTexture::Import },
+ { TEXT("tif"), ASSET_FILES_EXTENSION, ImportTexture::Import },
+ { TEXT("jpeg"), ASSET_FILES_EXTENSION, ImportTexture::Import },
+ { TEXT("jpg"), ASSET_FILES_EXTENSION, ImportTexture::Import },
+ { TEXT("hdr"), ASSET_FILES_EXTENSION, ImportTexture::Import },
+ { TEXT("raw"), ASSET_FILES_EXTENSION, ImportTexture::Import },
// IES Profiles
- { TEXT("ies"), ImportTexture::ImportIES },
+ { TEXT("ies"), ASSET_FILES_EXTENSION, ImportTexture::ImportIES },
// Shaders
- { TEXT("shader"), ImportShader::Import },
+ { TEXT("shader"), ASSET_FILES_EXTENSION, ImportShader::Import },
// Audio
- { TEXT("wav"), ImportAudio::ImportWav },
- { TEXT("mp3"), ImportAudio::ImportMp3 },
+ { TEXT("wav"), ASSET_FILES_EXTENSION, ImportAudio::ImportWav },
+ { TEXT("mp3"), ASSET_FILES_EXTENSION, ImportAudio::ImportMp3 },
#if COMPILE_WITH_OGG_VORBIS
- { TEXT("ogg"), ImportAudio::ImportOgg },
+ { TEXT("ogg"), ASSET_FILES_EXTENSION, ImportAudio::ImportOgg },
#endif
// Fonts
- { TEXT("ttf"), ImportFont::Import },
- { TEXT("otf"), ImportFont::Import },
+ { TEXT("ttf"), ASSET_FILES_EXTENSION, ImportFont::Import },
+ { TEXT("otf"), ASSET_FILES_EXTENSION, ImportFont::Import },
// Models
- { TEXT("obj"), ImportModelFile::Import },
- { TEXT("fbx"), ImportModelFile::Import },
- { TEXT("x"), ImportModelFile::Import },
- { TEXT("dae"), ImportModelFile::Import },
- { TEXT("gltf"), ImportModelFile::Import },
- { TEXT("glb"), ImportModelFile::Import },
+ { TEXT("obj"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("fbx"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("x"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("dae"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("gltf"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("glb"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+
+ // gettext PO files
+ { TEXT("po"), TEXT("json"), CreateJson::ImportPo },
// Models (untested formats - may fail :/)
- { TEXT("blend"), ImportModelFile::Import },
- { TEXT("bvh"), ImportModelFile::Import },
- { TEXT("ase"), ImportModelFile::Import },
- { TEXT("ply"), ImportModelFile::Import },
- { TEXT("dxf"), ImportModelFile::Import },
- { TEXT("ifc"), ImportModelFile::Import },
- { TEXT("nff"), ImportModelFile::Import },
- { TEXT("smd"), ImportModelFile::Import },
- { TEXT("vta"), ImportModelFile::Import },
- { TEXT("mdl"), ImportModelFile::Import },
- { TEXT("md2"), ImportModelFile::Import },
- { TEXT("md3"), ImportModelFile::Import },
- { TEXT("md5mesh"), ImportModelFile::Import },
- { TEXT("q3o"), ImportModelFile::Import },
- { TEXT("q3s"), ImportModelFile::Import },
- { TEXT("ac"), ImportModelFile::Import },
- { TEXT("stl"), ImportModelFile::Import },
- { TEXT("lwo"), ImportModelFile::Import },
- { TEXT("lws"), ImportModelFile::Import },
- { TEXT("lxo"), ImportModelFile::Import },
+ { TEXT("blend"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("bvh"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("ase"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("ply"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("dxf"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("ifc"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("nff"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("smd"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("vta"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("mdl"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("md2"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("md3"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("md5mesh"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("q3o"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("q3s"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("ac"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("stl"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("lwo"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("lws"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
+ { TEXT("lxo"), ASSET_FILES_EXTENSION, ImportModelFile::Import },
};
AssetsImportingManager::Importers.Add(InBuildImporters, ARRAY_COUNT(InBuildImporters));
diff --git a/Source/Engine/ContentImporters/CreateJson.cpp b/Source/Engine/ContentImporters/CreateJson.cpp
index fb7d3f6e7..862c5028f 100644
--- a/Source/Engine/ContentImporters/CreateJson.cpp
+++ b/Source/Engine/ContentImporters/CreateJson.cpp
@@ -9,7 +9,11 @@
#include "Engine/Platform/FileSystem.h"
#include "Engine/Content/Content.h"
#include "Engine/Content/Storage/JsonStorageProxy.h"
+#include "Engine/Content/Cache/AssetsCache.h"
+#include "Engine/Content/AssetReference.h"
#include "Engine/Serialization/JsonWriters.h"
+#include "Engine/Localization/LocalizedStringTable.h"
+#include "Engine/Utilities/TextProcessing.h"
#include "FlaxEngine.Gen.h"
bool CreateJson::Create(const StringView& path, rapidjson_flax::StringBuffer& data, const String& dataTypename)
@@ -51,7 +55,7 @@ bool CreateJson::Create(const StringView& path, StringAnsiView& data, StringAnsi
LOG(Warning, "Failed to create directory");
return true;
}
- }
+ }
}
rapidjson_flax::StringBuffer buffer;
@@ -88,8 +92,184 @@ bool CreateJson::Create(const StringView& path, StringAnsiView& data, StringAnsi
{
asset->Reload();
}
+ else
+ {
+ Content::GetRegistry()->RegisterAsset(id, String(dataTypename), path);
+ }
return false;
}
+void FormatPoValue(String& value)
+{
+ value.Replace(TEXT("\\n"), TEXT("\n"));
+ value.Replace(TEXT("%s"), TEXT("{}"));
+ value.Replace(TEXT("%d"), TEXT("{}"));
+}
+
+CreateAssetResult CreateJson::ImportPo(CreateAssetContext& context)
+{
+ // Base
+ IMPORT_SETUP(LocalizedStringTable, 1);
+
+ // Load file (UTF-16)
+ String inputData;
+ if (File::ReadAllText(context.InputPath, inputData))
+ {
+ return CreateAssetResult::InvalidPath;
+ }
+
+ // Use virtual asset for data storage and serialization
+ AssetReference asset = Content::CreateVirtualAsset();
+ if (!asset)
+ return CreateAssetResult::Error;
+
+ // Parse PO format
+ int32 pos = 0;
+ int32 pluralCount = 0;
+ int32 lineNumber = 0;
+ bool fuzzy = false, hasNewContext = false;
+ StringView msgctxt, msgid;
+ String idTmp;
+ while (pos < inputData.Length())
+ {
+ // Read line
+ const int32 startPos = pos;
+ while (pos < inputData.Length() && inputData[pos] != '\n')
+ pos++;
+ const StringView line(&inputData[startPos], pos - startPos);
+ lineNumber++;
+ pos++;
+ const int32 valueStart = line.Find('\"') + 1;
+ const int32 valueEnd = line.FindLast('\"');
+ const StringView value(line.Get() + valueStart, Math::Max(valueEnd - valueStart, 0));
+
+ if (line.StartsWith(StringView(TEXT("msgid_plural"))))
+ {
+ // Plural form
+ }
+ else if (line.StartsWith(StringView(TEXT("msgid"))))
+ {
+ // Id
+ msgid = value;
+
+ // Reset context if already used
+ if (!hasNewContext)
+ msgctxt = StringView();
+ hasNewContext = false;
+ }
+ else if (line.StartsWith(StringView(TEXT("msgstr"))))
+ {
+ // String
+ if (msgid.HasChars())
+ {
+ // Format message
+ String msgstr(value);
+ FormatPoValue(msgstr);
+
+ // Get message id
+ StringView id = msgid;
+ if (msgctxt.HasChars())
+ {
+ idTmp = String(msgctxt) + TEXT(".") + String(msgid);
+ id = idTmp;
+ }
+
+ int32 indexStart = line.Find('[');
+ if (indexStart != -1 && indexStart < valueStart)
+ {
+ indexStart++;
+ while (indexStart < line.Length() && StringUtils::IsWhitespace(line[indexStart]))
+ indexStart++;
+ int32 indexEnd = line.Find(']');
+ while (indexEnd > indexStart && StringUtils::IsWhitespace(line[indexEnd - 1]))
+ indexEnd--;
+ int32 index = -1;
+ StringUtils::Parse(line.Get() + indexStart, (uint32)(indexEnd - indexStart), &index);
+ if (pluralCount <= 0)
+ {
+ LOG(Error, "Missing 'nplurals'. Cannot use plural message at line {0}", lineNumber);
+ return CreateAssetResult::Error;
+ }
+ if (index < 0 || index > pluralCount)
+ {
+ LOG(Error, "Invalid plural message index at line {0}", lineNumber);
+ return CreateAssetResult::Error;
+ }
+
+ // Plural message
+ asset->AddPluralString(id, msgstr, index);
+ }
+ else
+ {
+ // Message
+ asset->AddString(id, msgstr);
+ }
+ }
+ }
+ else if (line.StartsWith(StringView(TEXT("msgctxt"))))
+ {
+ // Context
+ msgctxt = value;
+ hasNewContext = true;
+ }
+ else if (line.StartsWith('\"'))
+ {
+ // Config
+ const Char* pluralForms = StringUtils::Find(line.Get(), TEXT("Plural-Forms"));
+ if (pluralForms != nullptr && pluralForms < line.Get() + line.Length() - 1)
+ {
+ // Process plural forms rule
+ const Char* nplurals = StringUtils::Find(pluralForms, TEXT("nplurals"));
+ if (nplurals && nplurals < line.Get() + line.Length())
+ {
+ while (*nplurals && *nplurals != '=')
+ nplurals++;
+ while (*nplurals && (StringUtils::IsWhitespace(*nplurals) || *nplurals == '='))
+ nplurals++;
+ const Char* npluralsStart = nplurals;
+ while (*nplurals && !StringUtils::IsWhitespace(*nplurals) && *nplurals != ';')
+ nplurals++;
+ StringUtils::Parse(npluralsStart, (uint32)(nplurals - npluralsStart), &pluralCount);
+ if (pluralCount < 0 || pluralCount > 100)
+ {
+ LOG(Error, "Invalid 'nplurals' at line {0}", lineNumber);
+ return CreateAssetResult::Error;
+ }
+ }
+ // TODO: parse plural forms rule
+ }
+ const Char* language = StringUtils::Find(line.Get(), TEXT("Language"));
+ if (language != nullptr && language < line.Get() + line.Length() - 1)
+ {
+ // Process language locale
+ while (*language && *language != ':')
+ language++;
+ language++;
+ while (*language && StringUtils::IsWhitespace(*language))
+ language++;
+ const Char* languageStart = language;
+ while (*language && !StringUtils::IsWhitespace(*language) && *language != '\\' && *language != '\"')
+ language++;
+ asset->Locale.Set(languageStart, (int32)(language - languageStart));
+ if (asset->Locale == TEXT("English"))
+ asset->Locale = TEXT("en");
+ if (asset->Locale.Length() > 5)
+ LOG(Warning, "Imported .po file uses invalid locale '{0}'", asset->Locale);
+ }
+ }
+ else if (line.StartsWith('#') || line.IsEmpty())
+ {
+ // Comment
+ const Char* fuzzyPos = StringUtils::Find(line.Get(), TEXT("fuzzy"));
+ fuzzy |= fuzzyPos != nullptr && fuzzyPos < line.Get() + line.Length() - 1;
+ }
+ }
+ if (asset->Locale.IsEmpty())
+ LOG(Warning, "Imported .po file has missing locale");
+
+ // Save asset
+ return asset->Save(context.TargetAssetPath) ? CreateAssetResult::CannotSaveFile : CreateAssetResult::Ok;
+}
+
#endif
diff --git a/Source/Engine/ContentImporters/CreateJson.h b/Source/Engine/ContentImporters/CreateJson.h
index ccc15a792..38ca4b187 100644
--- a/Source/Engine/ContentImporters/CreateJson.h
+++ b/Source/Engine/ContentImporters/CreateJson.h
@@ -18,6 +18,7 @@ public:
static bool Create(const StringView& path, rapidjson_flax::StringBuffer& data, const String& dataTypename);
static bool Create(const StringView& path, rapidjson_flax::StringBuffer& data, const char* dataTypename);
static bool Create(const StringView& path, StringAnsiView& data, StringAnsiView& dataTypename);
+ static CreateAssetResult ImportPo(CreateAssetContext& context);
};
#endif
diff --git a/Source/Engine/ContentImporters/Types.h b/Source/Engine/ContentImporters/Types.h
index 051b865d8..92aa7f533 100644
--- a/Source/Engine/ContentImporters/Types.h
+++ b/Source/Engine/ContentImporters/Types.h
@@ -111,12 +111,6 @@ public:
/// The json metadata writer.
void AddMeta(JsonWriter& writer) const;
- ///
- /// Save asset file data to the hard drive
- ///
- /// Saving result
- CreateAssetResult Save();
-
private:
void ApplyChanges();
@@ -130,12 +124,17 @@ struct AssetImporter
public:
///
- /// Extension of the file to import with that importer
+ /// Extension of the file to import with that importer (without leading dot).
///
String FileExtension;
///
- /// Call asset importing process
+ /// Extension of the output file as output with that importer (without leading dot).
+ ///
+ String ResultExtension;
+
+ ///
+ /// Callback for the asset importing process.
///
CreateAssetFunction Callback;
};
diff --git a/Source/Engine/Core/Collections/Array.h b/Source/Engine/Core/Collections/Array.h
index 6a841bac5..3819323a9 100644
--- a/Source/Engine/Core/Collections/Array.h
+++ b/Source/Engine/Core/Collections/Array.h
@@ -2,6 +2,7 @@
#pragma once
+#include
#include "Engine/Platform/Platform.h"
#include "Engine/Core/Memory/Memory.h"
#include "Engine/Core/Memory/Allocation.h"
@@ -47,6 +48,20 @@ public:
_allocation.Allocate(capacity);
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The initial values defined in the array.
+ Array(std::initializer_list initList)
+ {
+ _count = _capacity = (int32)initList.size();
+ if (_count > 0)
+ {
+ _allocation.Allocate(_count);
+ Memory::ConstructItems(Get(), initList.begin(), _count);
+ }
+ }
+
///
/// Initializes a new instance of the class.
///
@@ -123,6 +138,24 @@ public:
_allocation.Swap(other._allocation);
}
+ ///
+ /// The assignment operator that deletes the current collection of items and the copies items from the initializer list.
+ ///
+ /// The other collection to copy.
+ /// The reference to this.
+ Array& operator=(std::initializer_list initList) noexcept
+ {
+ Memory::DestructItems(Get(), _count);
+
+ _count = _capacity = (int32)initList.size();
+ if (_capacity > 0)
+ {
+ _allocation.Allocate(_capacity);
+ Memory::ConstructItems(Get(), initList.begin(), _count);
+ }
+ return *this;
+ }
+
///
/// The assignment operator that deletes the current collection of items and the copies items from the other array.
///
diff --git a/Source/Engine/Core/Config/GameSettings.cpp b/Source/Engine/Core/Config/GameSettings.cpp
index a47aefdee..5b333b227 100644
--- a/Source/Engine/Core/Config/GameSettings.cpp
+++ b/Source/Engine/Core/Config/GameSettings.cpp
@@ -13,6 +13,7 @@
#include "Engine/Input/InputSettings.h"
#include "Engine/Audio/AudioSettings.h"
#include "Engine/Navigation/NavigationSettings.h"
+#include "Engine/Localization/LocalizationSettings.h"
#include "Engine/Content/Content.h"
#include "Engine/Content/JsonAsset.h"
#include "Engine/Content/AssetReference.h"
@@ -55,6 +56,8 @@ IMPLEMENT_SETTINGS_GETTER(PS4PlatformSettings, PS4Platform);
IMPLEMENT_SETTINGS_GETTER(XboxScarlettPlatformSettings, XboxScarlettPlatform);
#elif PLATFORM_ANDROID
IMPLEMENT_SETTINGS_GETTER(AndroidPlatformSettings, AndroidPlatform);
+#elif PLATFORM_SWITCH
+IMPLEMENT_SETTINGS_GETTER(SwitchPlatformSettings, SwitchPlatform);
#else
#error Unknown platform
#endif
@@ -125,6 +128,7 @@ bool GameSettings::Load()
PRELOAD_SETTINGS(Input);
PRELOAD_SETTINGS(Graphics);
PRELOAD_SETTINGS(Navigation);
+ PRELOAD_SETTINGS(Localization);
PRELOAD_SETTINGS(GameCooking);
#undef PRELOAD_SETTINGS
@@ -156,6 +160,7 @@ void GameSettings::Apply()
APPLY_SETTINGS(InputSettings);
APPLY_SETTINGS(GraphicsSettings);
APPLY_SETTINGS(NavigationSettings);
+ APPLY_SETTINGS(LocalizationSettings);
APPLY_SETTINGS(BuildSettings);
APPLY_SETTINGS(PlatformSettings);
#undef APPLY_SETTINGS
@@ -195,6 +200,7 @@ void GameSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* mo
DESERIALIZE(Input);
DESERIALIZE(Graphics);
DESERIALIZE(Navigation);
+ DESERIALIZE(Localization);
DESERIALIZE(GameCooking);
// Per-platform settings containers
@@ -204,6 +210,7 @@ void GameSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* mo
DESERIALIZE(PS4Platform);
DESERIALIZE(XboxScarlettPlatform);
DESERIALIZE(AndroidPlatform);
+ DESERIALIZE(SwitchPlatform);
}
void LayersAndTagsSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
diff --git a/Source/Engine/Core/Config/GameSettings.cs b/Source/Engine/Core/Config/GameSettings.cs
index a4f8d8e55..ed96ef4e6 100644
--- a/Source/Engine/Core/Config/GameSettings.cs
+++ b/Source/Engine/Core/Config/GameSettings.cs
@@ -11,6 +11,7 @@ namespace FlaxEditor.Content.Settings
{
internal const string PS4PlatformSettingsTypename = "FlaxEditor.Content.Settings.PS4PlatformSettings";
internal const string XboxScarlettPlatformSettingsTypename = "FlaxEditor.Content.Settings.XboxScarlettPlatformSettings";
+ internal const string SwitchPlatformSettingsTypename = "FlaxEditor.Content.Settings.SwitchPlatformSettings";
///
/// The default application icon.
@@ -78,6 +79,12 @@ namespace FlaxEditor.Content.Settings
[EditorOrder(1045), EditorDisplay("Other Settings"), AssetReference(typeof(NavigationSettings), true), Tooltip("Reference to Navigation Settings asset")]
public JsonAsset Navigation;
+ ///
+ /// Reference to asset.
+ ///
+ [EditorOrder(1046), EditorDisplay("Other Settings"), AssetReference(typeof(LocalizationSettings), true), Tooltip("Reference to Localization Settings asset")]
+ public JsonAsset Localization;
+
///
/// Reference to asset.
///
@@ -138,6 +145,14 @@ namespace FlaxEditor.Content.Settings
public JsonAsset AndroidPlatform;
#endif
+#if FLAX_EDITOR || PLATFORM_SWITCH
+ ///
+ /// Reference to Switch Platform Settings asset. Used to apply configuration on Switch platform.
+ ///
+ [EditorOrder(2070), EditorDisplay("Platform Settings", "Switch"), AssetReference(SwitchPlatformSettingsTypename, true), Tooltip("Reference to Switch Platform Settings asset")]
+ public JsonAsset SwitchPlatform;
+#endif
+
///
/// Gets the absolute path to the game settings asset file.
///
@@ -210,6 +225,8 @@ namespace FlaxEditor.Content.Settings
return LoadAsset(gameSettings.Graphics) as T;
if (type == typeof(NavigationSettings))
return LoadAsset(gameSettings.Navigation) as T;
+ if (type == typeof(LocalizationSettings))
+ return LoadAsset(gameSettings.Localization) as T;
if (type == typeof(BuildSettings))
return LoadAsset(gameSettings.GameCooking) as T;
if (type == typeof(InputSettings))
@@ -240,6 +257,10 @@ namespace FlaxEditor.Content.Settings
if (type == typeof(AndroidPlatformSettings))
return LoadAsset(gameSettings.AndroidPlatform) as T;
#endif
+#if FLAX_EDITOR || PLATFORM_SWITCH
+ if (type.FullName == SwitchPlatformSettingsTypename)
+ return LoadAsset(gameSettings.SwitchPlatform, SwitchPlatformSettingsTypename) as T;
+#endif
if (gameSettings.CustomSettings != null)
{
@@ -308,6 +329,8 @@ namespace FlaxEditor.Content.Settings
return SaveAsset(gameSettings, ref gameSettings.Graphics, obj);
if (type == typeof(NavigationSettings))
return SaveAsset(gameSettings, ref gameSettings.Navigation, obj);
+ if (type == typeof(LocalizationSettings))
+ return SaveAsset(gameSettings, ref gameSettings.Localization, obj);
if (type == typeof(BuildSettings))
return SaveAsset(gameSettings, ref gameSettings.GameCooking, obj);
if (type == typeof(InputSettings))
@@ -324,6 +347,8 @@ namespace FlaxEditor.Content.Settings
return SaveAsset(gameSettings, ref gameSettings.XboxScarlettPlatform, obj);
if (type == typeof(AndroidPlatformSettings))
return SaveAsset(gameSettings, ref gameSettings.AndroidPlatform, obj);
+ if (type.FullName == SwitchPlatformSettingsTypename)
+ return SaveAsset(gameSettings, ref gameSettings.SwitchPlatform, obj);
if (type == typeof(AudioSettings))
return SaveAsset(gameSettings, ref gameSettings.Audio, obj);
diff --git a/Source/Engine/Core/Config/GameSettings.h b/Source/Engine/Core/Config/GameSettings.h
index 16e1fe7b5..8016bdbe4 100644
--- a/Source/Engine/Core/Config/GameSettings.h
+++ b/Source/Engine/Core/Config/GameSettings.h
@@ -68,6 +68,7 @@ public:
Guid Input;
Guid Graphics;
Guid Navigation;
+ Guid Localization;
Guid GameCooking;
// Per-platform settings containers
@@ -77,6 +78,7 @@ public:
Guid PS4Platform;
Guid XboxScarlettPlatform;
Guid AndroidPlatform;
+ Guid SwitchPlatform;
public:
diff --git a/Source/Engine/Core/Config/LayersTagsSettings.h b/Source/Engine/Core/Config/LayersTagsSettings.h
index 066b5cdd5..c72ab3974 100644
--- a/Source/Engine/Core/Config/LayersTagsSettings.h
+++ b/Source/Engine/Core/Config/LayersTagsSettings.h
@@ -3,6 +3,8 @@
#pragma once
#include "Engine/Core/Config/Settings.h"
+#include "Engine/Core/Types/String.h"
+#include "Engine/Core/Collections/Array.h"
///
/// Layers and objects tags settings.
diff --git a/Source/Engine/Core/Config/PlatformSettings.h b/Source/Engine/Core/Config/PlatformSettings.h
index 2148989b9..29cf7959f 100644
--- a/Source/Engine/Core/Config/PlatformSettings.h
+++ b/Source/Engine/Core/Config/PlatformSettings.h
@@ -23,3 +23,6 @@
#if PLATFORM_ANDROID
#include "Engine/Platform/Android/AndroidPlatformSettings.h"
#endif
+#if PLATFORM_SWITCH
+#include "Platforms/Switch/Engine/Platform/SwitchPlatformSettings.h"
+#endif
diff --git a/Source/Engine/Core/Config/TimeSettings.h b/Source/Engine/Core/Config/TimeSettings.h
index 7e383380f..bdfcd927a 100644
--- a/Source/Engine/Core/Config/TimeSettings.h
+++ b/Source/Engine/Core/Config/TimeSettings.h
@@ -15,31 +15,31 @@ public:
///
/// The target amount of the game logic updates per second (script updates frequency).
///
- API_FIELD(Attributes="EditorOrder(1), DefaultValue(30.0f), Limit(0, 1000), EditorDisplay(\"General\", \"Update FPS\")")
- float UpdateFPS = 30.0f;
+ API_FIELD(Attributes="EditorOrder(1), Limit(0, 1000), EditorDisplay(\"General\", \"Update FPS\")")
+ float UpdateFPS = 60.0f;
///
/// The target amount of the physics simulation updates per second (also fixed updates frequency).
///
- API_FIELD(Attributes="EditorOrder(2), DefaultValue(60.0f), Limit(0, 1000), EditorDisplay(\"General\", \"Physics FPS\")")
+ API_FIELD(Attributes="EditorOrder(2), Limit(0, 1000), EditorDisplay(\"General\", \"Physics FPS\")")
float PhysicsFPS = 60.0f;
///
/// The target amount of the frames rendered per second (actual game FPS).
///
- API_FIELD(Attributes="EditorOrder(3), DefaultValue(60.0f), Limit(0, 1000), EditorDisplay(\"General\", \"Draw FPS\")")
+ API_FIELD(Attributes="EditorOrder(3), Limit(0, 1000), EditorDisplay(\"General\", \"Draw FPS\")")
float DrawFPS = 60.0f;
///
/// The game time scale factor. Default is 1.
///
- API_FIELD(Attributes="EditorOrder(10), DefaultValue(1.0f), Limit(0, 1000.0f, 0.1f), EditorDisplay(\"General\")")
+ API_FIELD(Attributes="EditorOrder(10), Limit(0, 1000.0f, 0.1f), EditorDisplay(\"General\")")
float TimeScale = 1.0f;
///
/// The maximum allowed delta time (in seconds) for the game logic update step.
///
- API_FIELD(Attributes="EditorOrder(20), DefaultValue(0.1f), Limit(0.1f, 1000.0f, 0.01f), EditorDisplay(\"General\")")
+ API_FIELD(Attributes="EditorOrder(20), Limit(0.1f, 1000.0f, 0.01f), EditorDisplay(\"General\")")
float MaxUpdateDeltaTime = 0.1f;
public:
diff --git a/Source/Engine/Core/Delegate.h b/Source/Engine/Core/Delegate.h
index d4118c3da..17c0c6afe 100644
--- a/Source/Engine/Core/Delegate.h
+++ b/Source/Engine/Core/Delegate.h
@@ -4,11 +4,6 @@
#include "Engine/Core/Memory/Allocation.h"
-template
-class Function;
-template
-class Delegate;
-
///
/// The function object.
///
diff --git a/Source/Engine/Core/Math/Int2.cpp b/Source/Engine/Core/Math/Int2.cpp
new file mode 100644
index 000000000..1293d23ac
--- /dev/null
+++ b/Source/Engine/Core/Math/Int2.cpp
@@ -0,0 +1,51 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+#include "Int2.h"
+#include "Int3.h"
+#include "Int4.h"
+#include "Vector2.h"
+#include "Vector3.h"
+#include "Vector4.h"
+#include "Engine/Core/Types/String.h"
+
+static_assert(sizeof(Int2) == 8, "Invalid Int2 type size.");
+
+const Int2 Int2::Zero(0);
+const Int2 Int2::One(1);
+const Int2 Int2::Minimum(MIN_int32);
+const Int2 Int2::Maximum(MAX_int32);
+
+Int2::Int2(const Int3& xyz)
+ : X(xyz.X)
+ , Y(xyz.Y)
+{
+}
+
+Int2::Int2(const Int4& xyzw)
+ : X(xyzw.X)
+ , Y(xyzw.Y)
+{
+}
+
+Int2::Int2(const Vector2& xy)
+ : X(static_cast(xy.X))
+ , Y(static_cast(xy.Y))
+{
+}
+
+Int2::Int2(const Vector3& xyz)
+ : X(static_cast(xyz.X))
+ , Y(static_cast(xyz.Y))
+{
+}
+
+Int2::Int2(const Vector4& xyzw)
+ : X(static_cast(xyzw.X))
+ , Y(static_cast(xyzw.Y))
+{
+}
+
+String Int2::ToString() const
+{
+ return String::Format(TEXT("{}"), *this);
+}
diff --git a/Source/Engine/Core/Math/Int2.cs b/Source/Engine/Core/Math/Int2.cs
index 0bf38e95f..a063e1bbf 100644
--- a/Source/Engine/Core/Math/Int2.cs
+++ b/Source/Engine/Core/Math/Int2.cs
@@ -12,9 +12,8 @@ namespace FlaxEngine
/// Represents a two dimensional mathematical vector (signed integers).
///
[Serializable]
- [StructLayout(LayoutKind.Sequential, Pack = 4)]
[TypeConverter(typeof(TypeConverters.Int2Converter))]
- public struct Int2 : IEquatable, IFormattable
+ partial struct Int2 : IEquatable, IFormattable
{
private static readonly string _formatString = "X:{0} Y:{1}";
@@ -53,16 +52,6 @@ namespace FlaxEngine
///
public static readonly Int2 Maximum = new Int2(int.MaxValue);
- ///
- /// The X component of the vector.
- ///
- public int X;
-
- ///
- /// The Y component of the vector.
- ///
- public int Y;
-
///
/// Initializes a new instance of the struct.
///
diff --git a/Source/Engine/Core/Math/Int2.h b/Source/Engine/Core/Math/Int2.h
index a6038d1b0..236768254 100644
--- a/Source/Engine/Core/Math/Int2.h
+++ b/Source/Engine/Core/Math/Int2.h
@@ -6,26 +6,27 @@
#include "Engine/Core/Formatting.h"
#include "Engine/Core/Templates.h"
-struct Vector2;
-struct Vector3;
-struct Vector4;
-
///
/// Two-components vector (32 bit integer type).
///
-API_STRUCT(InBuild) struct FLAXENGINE_API Int2
+API_STRUCT() struct FLAXENGINE_API Int2
{
+DECLARE_SCRIPTING_TYPE_MINIMAL(Int2);
public:
union
{
struct
{
- // X component
- int32 X;
+ ///
+ /// The X component.
+ ///
+ API_FIELD() int32 X;
- // Y component
- int32 Y;
+ ///
+ /// The Y component.
+ ///
+ API_FIELD() int32 Y;
};
// Raw values
@@ -40,6 +41,12 @@ public:
// Vector with all components equal 1
static const Int2 One;
+ // A minimum Int2
+ static const Int2 Minimum;
+
+ // A maximum Int2
+ static const Int2 Maximum;
+
public:
///
@@ -67,9 +74,25 @@ public:
}
// Init
- // @param v Vector to use X and Y components
- explicit Int2(const Vector2& v);
+ // @param xyz Int3 to use X and Y components
+ Int2(const Int3& xyz);
+ // Init
+ // @param xyzw Int4 to use X and Y components
+ Int2(const Int4& xyzw);
+
+ // Init
+ // @param xy Vector2 to use X and Y components
+ explicit Int2(const Vector2& xy);
+
+ // Init
+ // @param xyz Vector3 to use X and Y components
+ explicit Int2(const Vector3& xyz);
+
+ // Init
+ // @param xyzw Vector4 to use X and Y components
+ explicit Int2(const Vector4& xyzw);
+
public:
String ToString() const;
@@ -211,29 +234,29 @@ public:
public:
- static void Add(const Int2& a, const Int2& b, Int2* result)
+ static void Add(const Int2& a, const Int2& b, Int2& result)
{
- result->X = a.X + b.X;
- result->Y = a.Y + b.Y;
+ result.X = a.X + b.X;
+ result.Y = a.Y + b.Y;
}
static Int2 Add(const Int2& a, const Int2& b)
{
Int2 result;
- Add(a, b, &result);
+ Add(a, b, result);
return result;
}
- static void Subtract(const Int2& a, const Int2& b, Int2* result)
+ static void Subtract(const Int2& a, const Int2& b, Int2& result)
{
- result->X = a.X - b.X;
- result->Y = a.Y - b.Y;
+ result.X = a.X - b.X;
+ result.Y = a.Y - b.Y;
}
static Int2 Subtract(const Int2& a, const Int2& b)
{
Int2 result;
- Subtract(a, b, &result);
+ Subtract(a, b, result);
return result;
}
@@ -257,17 +280,112 @@ public:
return Int2(a.X / b, a.Y / b);
}
- // Creates vector from minimum components of two vectors
+ ///
+ /// Gets a value indicting whether this vector is zero.
+ ///
+ /// True if the vector is zero, otherwise false.
+ bool IsZero() const
+ {
+ return X == 0 && Y == 0;
+ }
+
+ ///
+ /// Gets a value indicting whether any vector component is zero.
+ ///
+ /// True if a component is zero, otherwise false.
+ bool IsAnyZero() const
+ {
+ return X == 0 || Y == 0;
+ }
+
+ ///
+ /// Gets a value indicting whether this vector is one.
+ ///
+ /// True if the vector is one, otherwise false.
+ bool IsOne() const
+ {
+ return X == 1 && Y == 1;
+ }
+
+ ///
+ /// Calculates a vector with values being opposite to values of that vector
+ ///
+ /// Negative vector
+ Int2 GetNegative() const
+ {
+ return Int2(-X, -Y);
+ }
+
+ ///
+ /// Returns average arithmetic of all the components
+ ///
+ /// Average arithmetic of all the components
+ float AverageArithmetic() const
+ {
+ return (X + Y) * 0.5f;
+ }
+
+ ///
+ /// Gets sum of all vector components values
+ ///
+ /// Sum of X, Y, Z and W
+ int32 SumValues() const
+ {
+ return X + Y;
+ }
+
+ ///
+ /// Returns minimum value of all the components
+ ///
+ /// Minimum value
+ int32 MinValue() const
+ {
+ return Math::Min(X, Y);
+ }
+
+ ///
+ /// Returns maximum value of all the components
+ ///
+ /// Maximum value
+ int32 MaxValue() const
+ {
+ return Math::Max(X, Y);
+ }
+
+
+ // Returns a vector containing the smallest components of the specified vectors
+ // @param a The first source vector
+ // @param b The second source vector
static Int2 Min(const Int2& a, const Int2& b)
{
return Int2(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y);
}
- // Creates vector from maximum components of two vectors
+ // Returns a vector containing the largest components of the specified vectors
+ // @param a The first source vector
+ // @param b The second source vector
static Int2 Max(const Int2& a, const Int2& b)
{
return Int2(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y);
}
+
+ // Returns a vector containing the smallest components of the specified vectors
+ // @param a The first source vector
+ // @param b The second source vector
+ // @param result When the method completes, contains an new vector composed of the smallest components of the source vectors
+ static void Min(const Int2& a, const Int2& b, Int2& result)
+ {
+ result = Int2(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y);
+ }
+
+ // Returns a vector containing the largest components of the specified vectors
+ // @param a The first source vector
+ // @param b The second source vector
+ // @param result When the method completes, contains an new vector composed of the largest components of the source vectors
+ static void Max(const Int2& a, const Int2& b, Int2& result)
+ {
+ result = Int2(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y);
+ }
};
template<>
diff --git a/Source/Engine/Core/Math/Int3.cpp b/Source/Engine/Core/Math/Int3.cpp
new file mode 100644
index 000000000..327437d70
--- /dev/null
+++ b/Source/Engine/Core/Math/Int3.cpp
@@ -0,0 +1,56 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+#include "Int2.h"
+#include "Int3.h"
+#include "Int4.h"
+#include "Vector2.h"
+#include "Vector3.h"
+#include "Vector4.h"
+#include "Engine/Core/Types/String.h"
+
+static_assert(sizeof(Int3) == 12, "Invalid Int3 type size.");
+
+const Int3 Int3::Zero(0);
+const Int3 Int3::One(1);
+const Int3 Int3::Minimum(MIN_int32);
+const Int3 Int3::Maximum(MAX_int32);
+
+Int3::Int3(const Int2& xy, int32 z)
+ : X(xy.X)
+ , Y(xy.Y)
+ , Z(z)
+{
+}
+
+Int3::Int3(const Int4& xyzw)
+ : X(xyzw.X)
+ , Y(xyzw.Y)
+ , Z(xyzw.Z)
+{
+}
+
+Int3::Int3(const Vector2& xy, int32 z)
+ : X(static_cast(xy.X))
+ , Y(static_cast(xy.Y))
+ , Z(z)
+{
+}
+
+Int3::Int3(const Vector3& xyz)
+ : X(static_cast(xyz.X))
+ , Y(static_cast(xyz.Y))
+ , Z(static_cast(xyz.Z))
+{
+}
+
+Int3::Int3(const Vector4& xyzw)
+ : X(static_cast(xyzw.X))
+ , Y(static_cast(xyzw.Y))
+ , Z(static_cast(xyzw.Z))
+{
+}
+
+String Int3::ToString() const
+{
+ return String::Format(TEXT("{}"), *this);
+}
diff --git a/Source/Engine/Core/Math/Int3.cs b/Source/Engine/Core/Math/Int3.cs
index 93193881a..e0c67bd33 100644
--- a/Source/Engine/Core/Math/Int3.cs
+++ b/Source/Engine/Core/Math/Int3.cs
@@ -12,9 +12,8 @@ namespace FlaxEngine
/// Represents a three dimensional mathematical vector (signed integers).
///
[Serializable]
- [StructLayout(LayoutKind.Sequential, Pack = 4)]
[TypeConverter(typeof(TypeConverters.Int3Converter))]
- public struct Int3 : IEquatable, IFormattable
+ partial struct Int3 : IEquatable, IFormattable
{
private static readonly string _formatString = "X:{0} Y:{1} Z:{2}";
@@ -58,21 +57,6 @@ namespace FlaxEngine
///
public static readonly Int3 Maximum = new Int3(int.MaxValue);
- ///
- /// The X component of the vector.
- ///
- public int X;
-
- ///
- /// The Y component of the vector.
- ///
- public int Y;
-
- ///
- /// The Z component of the vector.
- ///
- public int Z;
-
///
/// Initializes a new instance of the struct.
///
diff --git a/Source/Engine/Core/Math/Int3.h b/Source/Engine/Core/Math/Int3.h
index 6886acc6b..92311e2b1 100644
--- a/Source/Engine/Core/Math/Int3.h
+++ b/Source/Engine/Core/Math/Int3.h
@@ -6,29 +6,33 @@
#include "Engine/Core/Formatting.h"
#include "Engine/Core/Templates.h"
-struct Vector2;
-struct Vector3;
-struct Vector4;
///
/// Three-components vector (32 bit integer type).
///
-API_STRUCT(InBuild) struct FLAXENGINE_API Int3
+API_STRUCT() struct FLAXENGINE_API Int3
{
+DECLARE_SCRIPTING_TYPE_MINIMAL(Int3);
public:
union
{
struct
{
- // X component
- int32 X;
+ ///
+ /// The X component.
+ ///
+ API_FIELD() int32 X;
- // Y component
- int32 Y;
+ ///
+ /// The Y component.
+ ///
+ API_FIELD() int32 Y;
- // Y component
- int32 Z;
+ ///
+ /// The Z component.
+ ///
+ API_FIELD() int32 Z;
};
// Raw values
@@ -43,6 +47,12 @@ public:
// Vector with all components equal 1
static const Int3 One;
+ // A minimum Int3
+ static const Int3 Minimum;
+
+ // A maximum Int3
+ static const Int3 Maximum;
+
public:
///
@@ -73,19 +83,293 @@ public:
}
// Init
- // @param v Vector to use X, Y and Z components
- explicit Int3(const Vector3& v);
+ // @param v Int2 to use X and Y components
+ // @param z Z component value
+ Int3(const Int2& xy, int32 z);
+ // Init
+ // @param v Int4 to use X and Y components
+ Int3(const Int4& xyzw);
+
+ // Init
+ // @param v Vector2 to use X and Y components
+ // @param z Z component value
+ explicit Int3(const Vector2& xy, int32 z);
+
+ // Init
+ // @param v Vector3 to use X, Y and Z components
+ explicit Int3(const Vector3& xyz);
+
+ // Init
+ // @param v Vector4 to use X and Y components
+ explicit Int3(const Vector4& xyzw);
+
public:
String ToString() const;
public:
+ // Arithmetic operators with Int2
+
+ Int3 operator+(const Int3& b) const
+ {
+ return Add(*this, b);
+ }
+
+ Int3 operator-(const Int3& b) const
+ {
+ return Subtract(*this, b);
+ }
+
+ Int3 operator*(const Int3& b) const
+ {
+ return Multiply(*this, b);
+ }
+
+ Int3 operator/(const Int3& b) const
+ {
+ return Divide(*this, b);
+ }
+
+ Int3 operator-() const
+ {
+ return Int3(-X, -Y, -Z);
+ }
+
+ // op= operators with Int2
+
+ Int3& operator+=(const Int3& b)
+ {
+ *this = Add(*this, b);
+ return *this;
+ }
+
+ Int3& operator-=(const Int3& b)
+ {
+ *this = Subtract(*this, b);
+ return *this;
+ }
+
+ Int3& operator*=(const Int3& b)
+ {
+ *this = Multiply(*this, b);
+ return *this;
+ }
+
+ Int3& operator/=(const Int3& b)
+ {
+ *this = Divide(*this, b);
+ return *this;
+ }
+
+ // Arithmetic operators with int32
+
+ Int3 operator+(int32 b) const
+ {
+ return Add(*this, b);
+ }
+
+ Int3 operator-(int32 b) const
+ {
+ return Subtract(*this, b);
+ }
+
+ Int3 operator*(int32 b) const
+ {
+ return Multiply(*this, b);
+ }
+
+ Int3 operator/(int32 b) const
+ {
+ return Divide(*this, b);
+ }
+
+ // op= operators with int32
+
+ Int3& operator+=(int32 b)
+ {
+ *this = Add(*this, b);
+ return *this;
+ }
+
+ Int3& operator-=(int32 b)
+ {
+ *this = Subtract(*this, b);
+ return *this;
+ }
+
+ Int3& operator*=(int32 b)
+ {
+ *this = Multiply(*this, b);
+ return *this;
+ }
+
+ Int3& operator/=(int32 b)
+ {
+ *this = Divide(*this, b);
+ return *this;
+ }
+
+ // Comparison operators
+
+ bool operator==(const Int3& b) const
+ {
+ return X == b.X && Y == b.Y;
+ }
+
+ bool operator!=(const Int3& b) const
+ {
+ return X != b.X || Y != b.Y;
+ }
+
+ bool operator>(const Int3& b) const
+ {
+ return X > b.X && Y > b.Y;
+ }
+
+ bool operator>=(const Int3& b) const
+ {
+ return X >= b.X && Y >= b.Y;
+ }
+
+ bool operator<(const Int3& b) const
+ {
+ return X < b.X && Y < b.Y;
+ }
+
+ bool operator<=(const Int3& b) const
+ {
+ return X <= b.X && Y <= b.Y;
+ }
+
+public:
+
+ static void Add(const Int3& a, const Int3& b, Int3& result)
+ {
+ result.X = a.X + b.X;
+ result.Y = a.Y + b.Y;
+ result.Z = a.Z + b.Z;
+ }
+
+ static Int3 Add(const Int3& a, const Int3& b)
+ {
+ Int3 result;
+ Add(a, b, result);
+ return result;
+ }
+
+ static void Subtract(const Int3& a, const Int3& b, Int3& result)
+ {
+ result.X = a.X - b.X;
+ result.Y = a.Y - b.Y;
+ result.Z = a.Z - b.Z;
+ }
+
+ static Int3 Subtract(const Int3& a, const Int3& b)
+ {
+ Int3 result;
+ Subtract(a, b, result);
+ return result;
+ }
+
+ static Int3 Multiply(const Int3& a, const Int3& b)
+ {
+ return Int3(a.X * b.X, a.Y * b.Y, a.Z * b.Z);
+ }
+
+ static Int3 Multiply(const Int3& a, int32 b)
+ {
+ return Int3(a.X * b, a.Y * b, a.Z * b);
+ }
+
+ static Int3 Divide(const Int3& a, const Int3& b)
+ {
+ return Int3(a.X / b.X, a.Y / b.Y, a.Z / b.Z);
+ }
+
+ static Int3 Divide(const Int3& a, int32 b)
+ {
+ return Int3(a.X / b, a.Y / b, a.Z / b);
+ }
+
+public:
+
+ ///
+ /// Gets a value indicting whether this vector is zero.
+ ///
+ /// True if the vector is zero, otherwise false.
+ bool IsZero() const
+ {
+ return X == 0 && Y == 0 && Z == 0;
+ }
+
+ ///
+ /// Gets a value indicting whether any vector component is zero.
+ ///
+ /// True if a component is zero, otherwise false.
+ bool IsAnyZero() const
+ {
+ return X == 0 || Y == 0 || Z == 0;
+ }
+
+ ///
+ /// Gets a value indicting whether this vector is one.
+ ///
+ /// True if the vector is one, otherwise false.
+ bool IsOne() const
+ {
+ return X == 1 && Y == 1 && Z == 1;
+ }
+
+ ///
+ /// Calculates a vector with values being opposite to values of that vector
+ ///
+ /// Negative vector
+ Int3 GetNegative() const
+ {
+ return Int3(-X, -Y, -Z);
+ }
+
+ ///
+ /// Returns average arithmetic of all the components
+ ///
+ /// Average arithmetic of all the components
+ float AverageArithmetic() const
+ {
+ return (X + Y + Z) / 3.0f;
+ }
+
+ ///
+ /// Gets sum of all vector components values
+ ///
+ /// Sum of X, Y, Z and W
+ int32 SumValues() const
+ {
+ return X + Y + Z;
+ }
+
+ ///
+ /// Returns minimum value of all the components
+ ///
+ /// Minimum value
+ int32 MinValue() const
+ {
+ return Math::Min(X, Y, Z);
+ }
+
+ ///
+ /// Returns maximum value of all the components
+ ///
+ /// Maximum value
+ int32 MaxValue() const
+ {
+ return Math::Max(X, Y, Z);
+ }
+
// Returns a vector containing the largest components of the specified vectors
// @param a The first source vector
// @param b The second source vector
- // @param result When the method completes, contains an new vector composed of the largest components of the source vectors
static Int3 Max(const Int3& a, const Int3& b)
{
return Int3(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y, a.Z > b.Z ? a.Z : b.Z);
@@ -94,7 +378,6 @@ public:
// Returns a vector containing the smallest components of the specified vectors
// @param a The first source vector
// @param b The second source vector
- // @param result When the method completes, contains an new vector composed of the smallest components of the source vectors
static Int3 Min(const Int3& a, const Int3& b)
{
return Int3(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y, a.Z < b.Z ? a.Z : b.Z);
@@ -104,18 +387,18 @@ public:
// @param a The first source vector
// @param b The second source vector
// @param result When the method completes, contains an new vector composed of the largest components of the source vectors
- static void Max(const Int3& a, const Int3& b, Int3* result)
+ static void Max(const Int3& a, const Int3& b, Int3& result)
{
- *result = Int3(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y, a.Z > b.Z ? a.Z : b.Z);
+ result = Int3(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y, a.Z > b.Z ? a.Z : b.Z);
}
// Returns a vector containing the smallest components of the specified vectors
// @param a The first source vector
// @param b The second source vector
// @param result When the method completes, contains an new vector composed of the smallest components of the source vectors
- static void Min(const Int3& a, const Int3& b, Int3* result)
+ static void Min(const Int3& a, const Int3& b, Int3 result)
{
- *result = Int3(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y, a.Z < b.Z ? a.Z : b.Z);
+ result = Int3(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y, a.Z < b.Z ? a.Z : b.Z);
}
};
diff --git a/Source/Engine/Core/Math/VectorInt.cpp b/Source/Engine/Core/Math/Int4.cpp
similarity index 56%
rename from Source/Engine/Core/Math/VectorInt.cpp
rename to Source/Engine/Core/Math/Int4.cpp
index 300343da5..a8f6be236 100644
--- a/Source/Engine/Core/Math/VectorInt.cpp
+++ b/Source/Engine/Core/Math/Int4.cpp
@@ -1,42 +1,51 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
-#include "VectorInt.h"
+#include "Int2.h"
+#include "Int3.h"
+#include "Int4.h"
#include "Vector2.h"
#include "Vector3.h"
#include "Vector4.h"
#include "Engine/Core/Types/String.h"
-const Int2 Int2::Zero(0);
-const Int2 Int2::One(1);
-
-Int2::Int2(const Vector2& v)
- : X(static_cast(v.X))
- , Y(static_cast(v.Y))
-{
-}
-
-String Int2::ToString() const
-{
- return String::Format(TEXT("{}"), *this);
-}
-
-const Int3 Int3::Zero(0);
-const Int3 Int3::One(1);
-
-Int3::Int3(const Vector3& v)
- : X(static_cast(v.X))
- , Y(static_cast(v.Y))
- , Z(static_cast(v.Z))
-{
-}
-
-String Int3::ToString() const
-{
- return String::Format(TEXT("{}"), *this);
-}
+static_assert(sizeof(Int4) == 16, "Invalid Int4 type size.");
const Int4 Int4::Zero(0);
const Int4 Int4::One(1);
+const Int4 Int4::Minimum(MIN_int32);
+const Int4 Int4::Maximum(MAX_int32);
+
+Int4::Int4(const Int2& xy, int32 z, int32 w)
+ : X(xy.X)
+ , Y(xy.Y)
+ , Z(z)
+ , W(w)
+{
+}
+
+Int4::Int4(const Int3& xyz, int32 w)
+ : X(xyz.X)
+ , Y(xyz.Y)
+ , Z(xyz.Z)
+ , W(w)
+{
+}
+
+Int4::Int4(const Vector2& v, int32 z, int32 w)
+ : X(static_cast(v.X))
+ , Y(static_cast(v.Y))
+ , Z(z)
+ , W(w)
+{
+}
+
+Int4::Int4(const Vector3& v, int32 w)
+ : X(static_cast(v.X))
+ , Y(static_cast(v.Y))
+ , Z(static_cast(v.Z))
+ , W(w)
+{
+}
Int4::Int4(const Vector4& v)
: X(static_cast(v.X))
diff --git a/Source/Engine/Core/Math/Int4.cs b/Source/Engine/Core/Math/Int4.cs
index 0617f7b71..5328dcc73 100644
--- a/Source/Engine/Core/Math/Int4.cs
+++ b/Source/Engine/Core/Math/Int4.cs
@@ -12,9 +12,8 @@ namespace FlaxEngine
/// Represents a four dimensional mathematical vector (signed integers).
///
[Serializable]
- [StructLayout(LayoutKind.Sequential, Pack = 4)]
[TypeConverter(typeof(TypeConverters.Int4Converter))]
- public struct Int4 : IEquatable, IFormattable
+ partial struct Int4 : IEquatable, IFormattable
{
private static readonly string _formatString = "X:{0} Y:{1} Z:{2} W:{3}";
@@ -63,26 +62,6 @@ namespace FlaxEngine
///
public static readonly Int4 Maximum = new Int4(int.MaxValue);
- ///
- /// The X component of the vector.
- ///
- public int X;
-
- ///
- /// The Y component of the vector.
- ///
- public int Y;
-
- ///
- /// The Z component of the vector.
- ///
- public int Z;
-
- ///
- /// The W component of the vector.
- ///
- public int W;
-
///
/// Initializes a new instance of the struct.
///
diff --git a/Source/Engine/Core/Math/Int4.h b/Source/Engine/Core/Math/Int4.h
index c8e9eebd8..8c7f148be 100644
--- a/Source/Engine/Core/Math/Int4.h
+++ b/Source/Engine/Core/Math/Int4.h
@@ -6,32 +6,37 @@
#include "Engine/Core/Formatting.h"
#include "Engine/Core/Templates.h"
-struct Vector2;
-struct Vector3;
-struct Vector4;
-
///
/// Four-components vector (32 bit integer type).
///
-API_STRUCT(InBuild) struct FLAXENGINE_API Int4
+API_STRUCT() struct FLAXENGINE_API Int4
{
+DECLARE_SCRIPTING_TYPE_MINIMAL(Int4);
public:
union
{
struct
{
- // X component
- int32 X;
+ ///
+ /// The X component.
+ ///
+ API_FIELD() int32 X;
- // Y component
- int32 Y;
+ ///
+ /// The Y component.
+ ///
+ API_FIELD() int32 Y;
- // Z component
- int32 Z;
+ ///
+ /// The Z component.
+ ///
+ API_FIELD() int32 Z;
- // W component
- int32 W;
+ ///
+ /// The W component.
+ ///
+ API_FIELD() int32 W;
};
// Raw values
@@ -46,6 +51,12 @@ public:
// Vector with all components equal 1
static const Int4 One;
+ // A minimum Int4
+ static const Int4 Minimum;
+
+ // A maximum Int4
+ static const Int4 Maximum;
+
public:
///
@@ -78,9 +89,31 @@ public:
{
}
+ // Init
+ // @param v Int2 to use X and Y components
+ // @param z Z component value
+ // @param w W component value
+ Int4(const Int2& xy, int32 z, int32 w);
+
+ // Init
+ // @param v Int3 to use X , Y and Z components
+ // @param w W component value
+ Int4(const Int3& xyz, int32 w);
+
+ // Init
+ // @param v Vector2 to use X and Y components
+ // @param z Z component value
+ // @param w W component value
+ explicit Int4(const Vector2& xy, int32 z, int32 w);
+
+ // Init
+ // @param v Vector3 to use X , Y and Z components
+ // @param w W component value
+ explicit Int4(const Vector3& xyz, int32 w);
+
// Init
// @param v Vector to use X, Y, Z and W components
- explicit Int4(const Vector4& v);
+ explicit Int4(const Vector4& xyzw);
public:
@@ -88,6 +121,229 @@ public:
public:
+ // Arithmetic operators with Int2
+
+ Int4 operator+(const Int4& b) const
+ {
+ return Add(*this, b);
+ }
+
+ Int4 operator-(const Int4& b) const
+ {
+ return Subtract(*this, b);
+ }
+
+ Int4 operator*(const Int4& b) const
+ {
+ return Multiply(*this, b);
+ }
+
+ Int4 operator/(const Int4& b) const
+ {
+ return Divide(*this, b);
+ }
+
+ Int4 operator-() const
+ {
+ return Int4(-X, -Y, -Z, -W);
+ }
+
+ // op= operators with Int2
+
+ Int4& operator+=(const Int4& b)
+ {
+ *this = Add(*this, b);
+ return *this;
+ }
+
+ Int4& operator-=(const Int4& b)
+ {
+ *this = Subtract(*this, b);
+ return *this;
+ }
+
+ Int4& operator*=(const Int4& b)
+ {
+ *this = Multiply(*this, b);
+ return *this;
+ }
+
+ Int4& operator/=(const Int4& b)
+ {
+ *this = Divide(*this, b);
+ return *this;
+ }
+
+ // Arithmetic operators with int32
+
+ Int4 operator+(int32 b) const
+ {
+ return Add(*this, b);
+ }
+
+ Int4 operator-(int32 b) const
+ {
+ return Subtract(*this, b);
+ }
+
+ Int4 operator*(int32 b) const
+ {
+ return Multiply(*this, b);
+ }
+
+ Int4 operator/(int32 b) const
+ {
+ return Divide(*this, b);
+ }
+
+ // op= operators with int32
+
+ Int4& operator+=(int32 b)
+ {
+ *this = Add(*this, b);
+ return *this;
+ }
+
+ Int4& operator-=(int32 b)
+ {
+ *this = Subtract(*this, b);
+ return *this;
+ }
+
+ Int4& operator*=(int32 b)
+ {
+ *this = Multiply(*this, b);
+ return *this;
+ }
+
+ Int4& operator/=(int32 b)
+ {
+ *this = Divide(*this, b);
+ return *this;
+ }
+
+ // Comparison operators
+
+ bool operator==(const Int4& b) const
+ {
+ return X == b.X && Y == b.Y;
+ }
+
+ bool operator!=(const Int4& b) const
+ {
+ return X != b.X || Y != b.Y;
+ }
+
+ bool operator>(const Int4& b) const
+ {
+ return X > b.X && Y > b.Y;
+ }
+
+ bool operator>=(const Int4& b) const
+ {
+ return X >= b.X && Y >= b.Y;
+ }
+
+ bool operator<(const Int4& b) const
+ {
+ return X < b.X && Y < b.Y;
+ }
+
+ bool operator<=(const Int4& b) const
+ {
+ return X <= b.X && Y <= b.Y;
+ }
+
+public:
+
+ static void Add(const Int4& a, const Int4& b, Int4& result)
+ {
+ result.X = a.X + b.X;
+ result.Y = a.Y + b.Y;
+ result.Z = a.Z + b.Z;
+ result.W = a.W + b.W;
+ }
+
+ static Int4 Add(const Int4& a, const Int4& b)
+ {
+ Int4 result;
+ Add(a, b, result);
+ return result;
+ }
+
+ static void Subtract(const Int4& a, const Int4& b, Int4& result)
+ {
+ result.X = a.X - b.X;
+ result.Y = a.Y - b.Y;
+ result.Z = a.Z - b.Z;
+ result.W = a.W - b.W;
+ }
+
+ static Int4 Subtract(const Int4& a, const Int4& b)
+ {
+ Int4 result;
+ Subtract(a, b, result);
+ return result;
+ }
+
+ static Int4 Multiply(const Int4& a, const Int4& b)
+ {
+ return Int4(a.X * b.X, a.Y * b.Y, a.Z * b.Z, a.W * b.W);
+ }
+
+ static Int4 Multiply(const Int4& a, int32 b)
+ {
+ return Int4(a.X * b, a.Y * b, a.Z * b, a.W * b);
+ }
+
+ static Int4 Divide(const Int4& a, const Int4& b)
+ {
+ return Int4(a.X / b.X, a.Y / b.Y, a.Z / b.Z, a.W / b.W);
+ }
+
+ static Int4 Divide(const Int4& a, int32 b)
+ {
+ return Int4(a.X / b, a.Y / b, a.Z / b, a.Y / b);
+ }
+
+public:
+
+ ///
+ /// Gets a value indicting whether this vector is zero.
+ ///
+ /// True if the vector is zero, otherwise false.
+ bool IsZero() const
+ {
+ return X == 0 && Y == 0 && Z == 0 && W == 0;
+ }
+
+ ///
+ /// Gets a value indicting whether any vector component is zero.
+ ///
+ /// True if a component is zero, otherwise false.
+ bool IsAnyZero() const
+ {
+ return X == 0 || Y == 0 || Z == 0 || W == 0;
+ }
+
+ ///
+ /// Gets a value indicting whether this vector is one.
+ ///
+ /// True if the vector is one, otherwise false.
+ bool IsOne() const
+ {
+ return X == 1 && Y == 1 && Z == 1 && W == 1;
+ }
+
+ ///
+ /// Calculates a vector with values being opposite to values of that vector
+ ///
+ /// Negative vector
+ Int4 GetNegative() const
+ {
+ return Int4(-X, -Y, -Z, -W);
+ }
+
///
/// Returns average arithmetic of all the components
///
@@ -123,6 +379,40 @@ public:
{
return Math::Max(X, Y, Z, W);
}
+
+ // Returns a vector containing the largest components of the specified vectors
+ // @param a The first source vector
+ // @param b The second source vector
+ static Int4 Max(const Int4& a, const Int4& b)
+ {
+ return Int4(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y, a.Z > b.Z ? a.Z : b.Z, a.W > b.W ? a.W : b.W);
+ }
+
+ // Returns a vector containing the smallest components of the specified vectors
+ // @param a The first source vector
+ // @param b The second source vector
+ static Int4 Min(const Int4& a, const Int4& b)
+ {
+ return Int4(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y, a.Z < b.Z ? a.Z : b.Z, a.W < b.W ? a.W : b.W);
+ }
+
+ // Returns a vector containing the largest components of the specified vectors
+ // @param a The first source vector
+ // @param b The second source vector
+ // @param result When the method completes, contains an new vector composed of the largest components of the source vectors
+ static void Max(const Int4& a, const Int4& b, Int4& result)
+ {
+ result = Int4(a.X > b.X ? a.X : b.X, a.Y > b.Y ? a.Y : b.Y, a.Z > b.Z ? a.Z : b.Z, a.W > b.W ? a.W : b.W);
+ }
+
+ // Returns a vector containing the smallest components of the specified vectors
+ // @param a The first source vector
+ // @param b The second source vector
+ // @param result When the method completes, contains an new vector composed of the smallest components of the source vectors
+ static void Min(const Int4& a, const Int4& b, Int4& result)
+ {
+ result = Int4(a.X < b.X ? a.X : b.X, a.Y < b.Y ? a.Y : b.Y, a.Z < b.Z ? a.Z : b.Z, a.W < b.W ? a.W : b.W);
+ }
};
template<>
diff --git a/Source/Engine/Core/Math/Math.h b/Source/Engine/Core/Math/Math.h
index ee3b34b9a..e9bd6e58f 100644
--- a/Source/Engine/Core/Math/Math.h
+++ b/Source/Engine/Core/Math/Math.h
@@ -13,6 +13,7 @@
#define PI_OVER_2 1.57079632679f
#define PI_OVER_4 0.78539816339f
#define PI_HALF PI_OVER_2
+#define GOLDEN_RATIO 1.6180339887f
// The value for which all absolute numbers smaller than are considered equal to zero.
#define ZeroTolerance 1e-6f
@@ -648,9 +649,9 @@ namespace Math
{
float delta = a2 - a1;
if (delta > PI)
- delta = delta - PI * 2.0f;
+ delta = delta - TWO_PI;
else if (delta < -PI)
- delta = delta + PI * 2.0f;
+ delta = delta + TWO_PI;
return delta;
}
@@ -658,9 +659,9 @@ namespace Math
static float UnwindRadians(float a)
{
while (a > PI)
- a -= (float)PI * 2.0f;
+ a -= TWO_PI;
while (a < -PI)
- a += (float)PI * 2.0f;
+ a += TWO_PI;
return a;
}
diff --git a/Source/Engine/Core/Math/Rectangle.cs b/Source/Engine/Core/Math/Rectangle.cs
index 50f9adce4..d1fb16abc 100644
--- a/Source/Engine/Core/Math/Rectangle.cs
+++ b/Source/Engine/Core/Math/Rectangle.cs
@@ -285,6 +285,19 @@ namespace FlaxEngine
return new Rectangle(Location - toExpand * 0.5f, Size + toExpand);
}
+ ///
+ /// Calculates a rectangle that includes the margins (inside).
+ ///
+ /// The rectangle.
+ /// The margin to apply to the rectangle.
+ /// Rectangle inside the given rectangle after applying margins inside it.
+ public static Rectangle Margin(Rectangle value, GUI.Margin margin)
+ {
+ value.Location += margin.Location;
+ value.Size -= margin.Size;
+ return value;
+ }
+
///
/// Calculates a rectangle that contains the union of a and b rectangles
///
diff --git a/Source/Engine/Core/Math/Vector2.cpp b/Source/Engine/Core/Math/Vector2.cpp
index c23e79d19..2c6979575 100644
--- a/Source/Engine/Core/Math/Vector2.cpp
+++ b/Source/Engine/Core/Math/Vector2.cpp
@@ -5,6 +5,8 @@
#include "Vector4.h"
#include "Color.h"
#include "Int2.h"
+#include "Int3.h"
+#include "Int4.h"
#include "../Types/String.h"
static_assert(sizeof(Vector2) == 8, "Invalid Vector2 type size.");
@@ -16,21 +18,33 @@ const Vector2 Vector2::UnitY(0, 1);
const Vector2 Vector2::Minimum(MIN_float);
const Vector2 Vector2::Maximum(MAX_float);
-Vector2::Vector2(const Int2& v)
- : X((float)v.X)
- , Y((float)v.Y)
+Vector2::Vector2(const Int2& xy)
+ : X(static_cast(xy.X))
+ , Y(static_cast(xy.Y))
{
}
-Vector2::Vector2(const Vector3& v)
- : X(v.X)
- , Y(v.Y)
+Vector2::Vector2(const Int3& xyz)
+ : X(static_cast(xyz.X))
+ , Y(static_cast(xyz.Y))
{
}
-Vector2::Vector2(const Vector4& v)
- : X(v.X)
- , Y(v.Y)
+Vector2::Vector2(const Int4& xyzw)
+ : X(static_cast(xyzw.X))
+ , Y(static_cast(xyzw.Y))
+{
+}
+
+Vector2::Vector2(const Vector3& xyz)
+ : X(xyz.X)
+ , Y(xyz.Y)
+{
+}
+
+Vector2::Vector2(const Vector4& xyzw)
+ : X(xyzw.X)
+ , Y(xyzw.Y)
{
}
diff --git a/Source/Engine/Core/Math/Vector2.h b/Source/Engine/Core/Math/Vector2.h
index 7a1b1519b..aaea1d73c 100644
--- a/Source/Engine/Core/Math/Vector2.h
+++ b/Source/Engine/Core/Math/Vector2.h
@@ -8,6 +8,9 @@
struct Vector3;
struct Vector4;
+struct Int2;
+struct Int3;
+struct Int4;
struct Color;
struct Matrix;
@@ -85,16 +88,24 @@ public:
}
// Init
- // @param v Vector to use X and Y components
- explicit Vector2(const Int2& v);
+ // @param v Int2 to use X and Y components
+ explicit Vector2(const Int2& xy);
// Init
- // @param v Vector to use X and Y components
- explicit Vector2(const Vector3& v);
+ // @param v Int3 to use X and Y components
+ explicit Vector2(const Int3& xyz);
+
+ // Init
+ // @param v Int4 to use X and Y components
+ explicit Vector2(const Int4& xyzw);
+
+ // Init
+ // @param v Vector3 to use X and Y components
+ explicit Vector2(const Vector3& xyz);
// Init
// @param v Vector4 to use X and Y components
- explicit Vector2(const Vector4& v);
+ explicit Vector2(const Vector4& xyzw);
// Init
// @param color Color value
diff --git a/Source/Engine/Core/Math/Vector3.cpp b/Source/Engine/Core/Math/Vector3.cpp
index f66bbcbbd..9c8783dad 100644
--- a/Source/Engine/Core/Math/Vector3.cpp
+++ b/Source/Engine/Core/Math/Vector3.cpp
@@ -6,7 +6,9 @@
#include "Color.h"
#include "Quaternion.h"
#include "Matrix.h"
+#include "Int2.h"
#include "Int3.h"
+#include "Int4.h"
#include "../Types/String.h"
static_assert(sizeof(Vector3) == 12, "Invalid Vector3 type size.");
@@ -40,10 +42,24 @@ Vector3::Vector3(const Vector2& xy)
{
}
+Vector3::Vector3(const Int2& xy, float z)
+ : X(static_cast(xy.X))
+ , Y(static_cast(xy.Y))
+ , Z(static_cast(z))
+{
+}
+
Vector3::Vector3(const Int3& xyz)
- : X((float)xyz.X)
- , Y((float)xyz.Y)
- , Z((float)xyz.Z)
+ : X(static_cast(xyz.X))
+ , Y(static_cast(xyz.Y))
+ , Z(static_cast(xyz.Z))
+{
+}
+
+Vector3::Vector3(const Int4& xyzw)
+ : X(static_cast(xyzw.X))
+ , Y(static_cast(xyzw.Y))
+ , Z(static_cast(xyzw.Z))
{
}
diff --git a/Source/Engine/Core/Math/Vector3.h b/Source/Engine/Core/Math/Vector3.h
index 1f4792e31..761977c96 100644
--- a/Source/Engine/Core/Math/Vector3.h
+++ b/Source/Engine/Core/Math/Vector3.h
@@ -12,6 +12,8 @@ struct Vector2;
struct Vector4;
struct Color;
class String;
+struct Int3;
+struct Int4;
///
/// Represents a three dimensional mathematical vector.
@@ -138,10 +140,19 @@ public:
// @param xy Vector3 value
explicit Vector3(const Vector2& xy);
+ // Init
+ // @param xy Int22 with X and Y components values
+ // @param z Z component value
+ explicit Vector3(const Int2& xy, float z);
+
// Init
// @param xyz Int3 value
explicit Vector3(const Int3& xyz);
+ // Init
+ // @param xyzw Int4 value
+ explicit Vector3(const Int4& xyzw);
+
// Init
// @param xyz Vector4 value
explicit Vector3(const Vector4& xyz);
@@ -901,6 +912,7 @@ public:
/// The third triangle vertex.
/// The triangle area.
static float TriangleArea(const Vector3& v0, const Vector3& v1, const Vector3& v2);
+
};
inline Vector3 operator+(float a, const Vector3& b)
diff --git a/Source/Engine/Core/Math/Vector4.cpp b/Source/Engine/Core/Math/Vector4.cpp
index 34fa27aac..5da725c20 100644
--- a/Source/Engine/Core/Math/Vector4.cpp
+++ b/Source/Engine/Core/Math/Vector4.cpp
@@ -3,10 +3,12 @@
#include "Vector4.h"
#include "Vector2.h"
#include "Vector3.h"
+#include "Int2.h"
+#include "Int3.h"
+#include "Int4.h"
#include "Color.h"
#include "Matrix.h"
#include "Rectangle.h"
-#include "Int4.h"
#include "../Types/String.h"
static_assert(sizeof(Vector4) == 16, "Invalid Vector4 type size.");
@@ -49,11 +51,27 @@ Vector4::Vector4(const Vector3& xyz, float w)
{
}
+Vector4::Vector4(const Int2& xy, float z, float w)
+ : X(static_cast(xy.X))
+ , Y(static_cast(xy.Y))
+ , Z(z)
+ , W(w)
+{
+}
+
+Vector4::Vector4(const Int3& xyz, float w)
+ : X(static_cast(xyz.X))
+ , Y(static_cast(xyz.Y))
+ , Z(static_cast(xyz.Z))
+ , W(w)
+{
+}
+
Vector4::Vector4(const Int4& xyzw)
- : X((float)xyzw.X)
- , Y((float)xyzw.Y)
- , Z((float)xyzw.X)
- , W((float)xyzw.Y)
+ : X(static_cast(xyzw.X))
+ , Y(static_cast(xyzw.Y))
+ , Z(static_cast(xyzw.X))
+ , W(static_cast(xyzw.Y))
{
}
diff --git a/Source/Engine/Core/Math/Vector4.h b/Source/Engine/Core/Math/Vector4.h
index c7771aa67..fe25a80bd 100644
--- a/Source/Engine/Core/Math/Vector4.h
+++ b/Source/Engine/Core/Math/Vector4.h
@@ -13,6 +13,9 @@ struct Color;
struct Matrix;
struct Rectangle;
class String;
+struct Int2;
+struct Int3;
+struct Int4;
///
/// Represents a four dimensional mathematical vector.
@@ -133,6 +136,17 @@ public:
// @param w W component value
Vector4(const Vector3& xyz, float w);
+ // Init
+ // @param xy X and Y values in the vector
+ // @param z Z component value
+ // @param w W component value
+ explicit Vector4(const Int2& xy, float z, float w);
+
+ // Init
+ // @param xyz X, Y and Z values in the vector
+ // @param w W component value
+ explicit Vector4(const Int3& xyz, float w);
+
// Init
// @param color Int4 value
explicit Vector4(const Int4& xyzw);
diff --git a/Source/Engine/Core/Math/VectorInt.h b/Source/Engine/Core/Math/VectorInt.h
deleted file mode 100644
index d9611d615..000000000
--- a/Source/Engine/Core/Math/VectorInt.h
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
-
-#pragma once
-
-#include "Int2.h"
-#include "Int3.h"
-#include "Int4.h"
diff --git a/Source/Engine/Core/Types/BaseTypes.h b/Source/Engine/Core/Types/BaseTypes.h
index b57f139ff..90ad934c2 100644
--- a/Source/Engine/Core/Types/BaseTypes.h
+++ b/Source/Engine/Core/Types/BaseTypes.h
@@ -97,6 +97,10 @@ template
class Pair;
template
class Dictionary;
+template
+class Function;
+template
+class Delegate;
// Declares full set of operators for the enum type (using binary operation on integer values)
#define DECLARE_ENUM_OPERATORS(T) \
diff --git a/Source/Engine/Core/Types/String.h b/Source/Engine/Core/Types/String.h
index 87babc637..950018c03 100644
--- a/Source/Engine/Core/Types/String.h
+++ b/Source/Engine/Core/Types/String.h
@@ -225,9 +225,7 @@ public:
const T* start = _data;
if (startPosition != -1)
start += startPosition < Length() ? startPosition : Length();
- const T* tmp = searchCase == StringSearchCase::IgnoreCase
- ? StringUtils::FindIgnoreCase(start, subStr)
- : StringUtils::Find(start, subStr);
+ const T* tmp = searchCase == StringSearchCase::IgnoreCase ? StringUtils::FindIgnoreCase(start, subStr) : StringUtils::Find(start, subStr);
return tmp ? static_cast(tmp - **this) : -1;
}
diff --git a/Source/Engine/Core/Types/StringView.h b/Source/Engine/Core/Types/StringView.h
index b413ff552..bbfdbccd7 100644
--- a/Source/Engine/Core/Types/StringView.h
+++ b/Source/Engine/Core/Types/StringView.h
@@ -160,16 +160,16 @@ public:
{
const int32 length = Length();
if (searchCase == StringSearchCase::IgnoreCase)
- return length > 0 && _data[0] == c;
- return length > 0 && StringUtils::ToLower(_data[0]) == StringUtils::ToLower(c);
+ return length > 0 && StringUtils::ToLower(_data[0]) == StringUtils::ToLower(c);
+ return length > 0 && _data[0] == c;
}
bool EndsWith(T c, StringSearchCase searchCase = StringSearchCase::IgnoreCase) const
{
const int32 length = Length();
if (searchCase == StringSearchCase::IgnoreCase)
- return length > 0 && _data[length - 1] == c;
- return length > 0 && StringUtils::ToLower(_data[length - 1]) == StringUtils::ToLower(c);
+ return length > 0 && StringUtils::ToLower(_data[length - 1]) == StringUtils::ToLower(c);
+ return length > 0 && _data[length - 1] == c;
}
bool StartsWith(const StringViewBase& prefix, StringSearchCase searchCase = StringSearchCase::IgnoreCase) const
diff --git a/Source/Engine/Core/Types/Variant.cpp b/Source/Engine/Core/Types/Variant.cpp
index db71c2f77..97bcfc412 100644
--- a/Source/Engine/Core/Types/Variant.cpp
+++ b/Source/Engine/Core/Types/Variant.cpp
@@ -11,6 +11,9 @@
#include "Engine/Core/Math/Vector2.h"
#include "Engine/Core/Math/Vector3.h"
#include "Engine/Core/Math/Vector4.h"
+#include "Engine/Core/Math/Int2.h"
+#include "Engine/Core/Math/Int3.h"
+#include "Engine/Core/Math/Int4.h"
#include "Engine/Core/Math/Quaternion.h"
#include "Engine/Core/Math/Color.h"
#include "Engine/Core/Math/Matrix.h"
@@ -551,6 +554,24 @@ Variant::Variant(const Vector4& v)
*(Vector4*)AsData = v;
}
+Variant::Variant(const Int2& v)
+ : Type(VariantType::Int2)
+{
+ *(Int2*)AsData = v;
+}
+
+Variant::Variant(const Int3& v)
+ : Type(VariantType::Int3)
+{
+ *(Int3*)AsData = v;
+}
+
+Variant::Variant(const Int4& v)
+ : Type(VariantType::Int4)
+{
+ *(Int4*)AsData = v;
+}
+
Variant::Variant(const Color& v)
: Type(VariantType::Color)
{
@@ -691,7 +712,7 @@ Variant::Variant(const CommonValue& value)
*this = Variant(value.AsRay);
break;
default:
- CRASH;
+ CRASH;
}
}
@@ -1504,6 +1525,132 @@ Variant::operator Vector4() const
}
}
+Variant::operator Int2() const
+{
+ switch (Type.Type)
+ {
+ case VariantType::Bool:
+ return Int2((int32)(AsBool ? 1.0f : 0.0f));
+ case VariantType::Int:
+ return Int2((int32)AsInt);
+ case VariantType::Uint:
+ return Int2((int32)AsUint);
+ case VariantType::Int64:
+ return Int2((int32)AsInt64);
+ case VariantType::Uint64:
+ case VariantType::Enum:
+ return Int2((int32)AsUint64);
+ case VariantType::Float:
+ return Int2((int32)AsFloat);
+ case VariantType::Double:
+ return Int2((int32)AsDouble);
+ case VariantType::Pointer:
+ return Int2((int32)(intptr)AsPointer);
+ case VariantType::Vector2:
+ return Int2(*(Vector2*)AsData);
+ case VariantType::Vector3:
+ return Int2(*(Vector3*)AsData);
+ case VariantType::Vector4:
+ return Int2(*(Vector4*)AsData);
+ case VariantType::Int2:
+ return Int2(*(Int2*)AsData);
+ case VariantType::Int3:
+ return Int2(*(Int3*)AsData);
+ case VariantType::Int4:
+ case VariantType::Color:
+ return Int2(*(Int4*)AsData);
+ case VariantType::Structure:
+ if (StringUtils::Compare(Type.TypeName, Int2::TypeInitializer.GetType().Fullname.Get()) == 0)
+ return *(Int2*)AsBlob.Data;
+ default:
+ return Int3::Zero;
+ }
+}
+
+Variant::operator Int3() const
+{
+ switch (Type.Type)
+ {
+ case VariantType::Bool:
+ return Int3((int32)(AsBool ? 1 : 0));
+ case VariantType::Int:
+ return Int3((int32)AsInt);
+ case VariantType::Uint:
+ return Int3((int32)AsUint);
+ case VariantType::Int64:
+ return Int3((int32)AsInt64);
+ case VariantType::Uint64:
+ case VariantType::Enum:
+ return Int3((int32)AsUint64);
+ case VariantType::Float:
+ return Int3((int32)AsFloat);
+ case VariantType::Double:
+ return Int3((int32)AsDouble);
+ case VariantType::Pointer:
+ return Int3((int32)(intptr)AsPointer);
+ case VariantType::Vector2:
+ return Int3(*(Vector2*)AsData, 0);
+ case VariantType::Vector3:
+ return Int3(*(Vector3*)AsData);
+ case VariantType::Vector4:
+ return Int3(*(Vector4*)AsData);
+ case VariantType::Int2:
+ return Int3(*(Int2*)AsData, 0);
+ case VariantType::Int3:
+ return Int3(*(Int3*)AsData);
+ case VariantType::Int4:
+ case VariantType::Color:
+ return Int3(*(Int4*)AsData);
+ case VariantType::Structure:
+ if (StringUtils::Compare(Type.TypeName, Int3::TypeInitializer.GetType().Fullname.Get()) == 0)
+ return *(Int3*)AsBlob.Data;
+ default:
+ return Int3::Zero;
+ }
+}
+
+Variant::operator Int4() const
+{
+ switch (Type.Type)
+ {
+ case VariantType::Bool:
+ return Int4((int32)(AsBool ? 1 : 0));
+ case VariantType::Int:
+ return Int4(AsInt);
+ case VariantType::Uint:
+ return Int4((int32)AsUint);
+ case VariantType::Int64:
+ return Int4((int32)AsInt64);
+ case VariantType::Uint64:
+ case VariantType::Enum:
+ return Int4((int32)AsUint64);
+ case VariantType::Float:
+ return Int4((int32)AsFloat);
+ case VariantType::Double:
+ return Int4((int32)AsDouble);
+ case VariantType::Pointer:
+ return Int4((int32)(intptr)AsPointer);
+ case VariantType::Vector2:
+ return Int4(*(Vector2*)AsData, 0, 0);
+ case VariantType::Vector3:
+ return Int4(*(Vector3*)AsData, 0);
+ case VariantType::Vector4:
+ return Int4(*(Vector4*)AsData);
+ case VariantType::Int2:
+ return Int4(*(Int2*)AsData, 0, 0);
+ case VariantType::Int3:
+ return Int4(*(Int3*)AsData, 0);
+ case VariantType::Int4:
+ case VariantType::Color:
+ return *(Int4*)AsData;
+ case VariantType::Structure:
+ if (StringUtils::Compare(Type.TypeName, Int4::TypeInitializer.GetType().Fullname.Get()) == 0)
+ return *(Int4*)AsBlob.Data;
+ default:
+ return Int4::Zero;
+ }
+}
+
Variant::operator Color() const
{
switch (Type.Type)
@@ -1670,6 +1817,21 @@ const Vector4& Variant::AsVector4() const
return *(const Vector4*)AsData;
}
+const Int2& Variant::AsInt2() const
+{
+ return *(const Int2*)AsData;
+}
+
+const Int3& Variant::AsInt3() const
+{
+ return *(const Int3*)AsData;
+}
+
+const Int4& Variant::AsInt4() const
+{
+ return *(const Int4*)AsData;
+}
+
const Color& Variant::AsColor() const
{
return *(const Color*)AsData;
diff --git a/Source/Engine/Core/Types/Variant.h b/Source/Engine/Core/Types/Variant.h
index 98fd9cf24..ac9af0e79 100644
--- a/Source/Engine/Core/Types/Variant.h
+++ b/Source/Engine/Core/Types/Variant.h
@@ -54,6 +54,10 @@ API_STRUCT(InBuild) struct FLAXENGINE_API VariantType
ManagedObject,
Typename,
+ Int2,
+ Int3,
+ Int4,
+
MAX
};
@@ -198,6 +202,9 @@ public:
Variant(const Vector2& v);
Variant(const Vector3& v);
Variant(const Vector4& v);
+ Variant(const Int2& v);
+ Variant(const Int3& v);
+ Variant(const Int4& v);
Variant(const Color& v);
Variant(const Quaternion& v);
Variant(const BoundingSphere& v);
@@ -262,6 +269,9 @@ public:
explicit operator Vector2() const;
explicit operator Vector3() const;
explicit operator Vector4() const;
+ explicit operator Int2() const;
+ explicit operator Int3() const;
+ explicit operator Int4() const;
explicit operator Color() const;
explicit operator Quaternion() const;
explicit operator Guid() const;
@@ -275,6 +285,9 @@ public:
const Vector2& AsVector2() const;
const Vector3& AsVector3() const;
const Vector4& AsVector4() const;
+ const Int2& AsInt2() const;
+ const Int3& AsInt3() const;
+ const Int4& AsInt4() const;
const Color& AsColor() const;
const Quaternion& AsQuaternion() const;
diff --git a/Source/Engine/Engine/Engine.Build.cs b/Source/Engine/Engine/Engine.Build.cs
index 507651f8f..0ee4e7a7c 100644
--- a/Source/Engine/Engine/Engine.Build.cs
+++ b/Source/Engine/Engine/Engine.Build.cs
@@ -35,6 +35,7 @@ public class Engine : EngineModule
options.PublicDependencies.Add("UI");
options.PublicDependencies.Add("Utilities");
options.PublicDependencies.Add("Visject");
+ options.PublicDependencies.Add("Localization");
// Use source folder per platform group
switch (options.Platform.Target)
@@ -42,6 +43,9 @@ public class Engine : EngineModule
case TargetPlatform.PS4:
options.SourcePaths.Add(Path.Combine(Globals.EngineRoot, "Source", "Platforms", "PS4", "Engine", "Engine"));
break;
+ case TargetPlatform.Switch:
+ options.SourcePaths.Add(Path.Combine(Globals.EngineRoot, "Source", "Platforms", "Switch", "Engine", "Engine"));
+ break;
}
}
}
diff --git a/Source/Engine/Engine/Engine.cpp b/Source/Engine/Engine/Engine.cpp
index 979a2547b..012b3290c 100644
--- a/Source/Engine/Engine/Engine.cpp
+++ b/Source/Engine/Engine/Engine.cpp
@@ -622,7 +622,7 @@ void EngineImpl::InitMainWindow()
if (exception)
{
MException ex(exception);
- ex.Log(LogType::Fatal, TEXT("FlaxEngine.ClassLibraryInitializer.SetWindow"));
+ ex.Log(LogType::Fatal, TEXT("FlaxEngine.Scripting.SetWindow"));
}
#endif
}
diff --git a/Source/Engine/Engine/Game.h b/Source/Engine/Engine/Game.h
index 2e9050314..585bfd3b3 100644
--- a/Source/Engine/Engine/Game.h
+++ b/Source/Engine/Engine/Game.h
@@ -16,6 +16,8 @@
#include "Platforms/XboxScarlett/Engine/Engine/XboxScarlettGame.h"
#elif PLATFORM_ANDROID
#include "Android/AndroidGame.h"
+#elif PLATFORM_SWITCH
+#include "Platforms/Switch/Engine/Engine/SwitchGame.h"
#else
#error Missing Game implementation!
#endif
diff --git a/Source/Engine/Engine/Time.cpp b/Source/Engine/Engine/Time.cpp
index f26f4f759..2dd348207 100644
--- a/Source/Engine/Engine/Time.cpp
+++ b/Source/Engine/Engine/Time.cpp
@@ -17,7 +17,7 @@ namespace
bool Time::_gamePaused = false;
float Time::_physicsMaxDeltaTime = 0.1f;
DateTime Time::StartupTime;
-float Time::UpdateFPS = 30.0f;
+float Time::UpdateFPS = 60.0f;
float Time::PhysicsFPS = 60.0f;
float Time::DrawFPS = 60.0f;
float Time::TimeScale = 1.0f;
diff --git a/Source/Engine/Graphics/Graphics.Build.cs b/Source/Engine/Graphics/Graphics.Build.cs
index ff25348b0..82e279360 100644
--- a/Source/Engine/Graphics/Graphics.Build.cs
+++ b/Source/Engine/Graphics/Graphics.Build.cs
@@ -75,6 +75,9 @@ public class Graphics : EngineModule
case TargetPlatform.Android:
options.PrivateDependencies.Add("GraphicsDeviceVulkan");
break;
+ case TargetPlatform.Switch:
+ options.PrivateDependencies.Add("GraphicsDeviceVulkan");
+ break;
default: throw new InvalidPlatformException(options.Platform.Target);
}
diff --git a/Source/Engine/Graphics/Graphics.cpp b/Source/Engine/Graphics/Graphics.cpp
index 69170dca0..292e6c570 100644
--- a/Source/Engine/Graphics/Graphics.cpp
+++ b/Source/Engine/Graphics/Graphics.cpp
@@ -171,6 +171,14 @@ bool GraphicsService::Init()
device = CreateGPUDeviceVulkan();
#endif
+#elif PLATFORM_SWITCH
+
+ // Switch
+#if GRAPHICS_API_VULKAN
+ if (!device)
+ device = CreateGPUDeviceVulkan();
+#endif
+
#elif !defined(GRAPHICS_API_NULL)
#error "Platform does not support GPU devices."
diff --git a/Source/Engine/Graphics/Models/Mesh.cpp b/Source/Engine/Graphics/Models/Mesh.cpp
index 5d7f712a8..4454a44ce 100644
--- a/Source/Engine/Graphics/Models/Mesh.cpp
+++ b/Source/Engine/Graphics/Models/Mesh.cpp
@@ -133,20 +133,22 @@ namespace
bool Mesh::UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0ElementType* vb0, VB1ElementType* vb1, VB2ElementType* vb2, void* ib, bool use16BitIndices)
{
+ auto model = (Model*)_model;
+
Unload();
// Setup GPU resources
- _model->LODs[_lodIndex]._verticesCount -= _vertices;
+ model->LODs[_lodIndex]._verticesCount -= _vertices;
const bool failed = Load(vertexCount, triangleCount, vb0, vb1, vb2, ib, use16BitIndices);
if (!failed)
{
- _model->LODs[_lodIndex]._verticesCount += _vertices;
+ model->LODs[_lodIndex]._verticesCount += _vertices;
// Calculate mesh bounds
SetBounds(BoundingBox::FromPoints((Vector3*)vb0, vertexCount));
// Send event (actors using this model can update bounds, etc.)
- _model->onLoaded();
+ model->onLoaded();
}
return failed;
@@ -214,17 +216,6 @@ Mesh::~Mesh()
SAFE_DELETE_GPU_RESOURCE(_indexBuffer);
}
-void Mesh::SetMaterialSlotIndex(int32 value)
-{
- if (value < 0 || value >= _model->MaterialSlots.Count())
- {
- LOG(Warning, "Cannot set mesh material slot to {0} while model has {1} slots.", value, _model->MaterialSlots.Count());
- return;
- }
-
- _materialSlotIndex = value;
-}
-
bool Mesh::Load(uint32 vertices, uint32 triangles, void* vb0, void* vb1, void* vb2, void* ib, bool use16BitIndexBuffer)
{
// Cache data
@@ -443,7 +434,7 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float
// TODO: cache vertexOffset within the model LOD per-mesh
uint32 vertexOffset = 0;
for (int32 meshIndex = 0; meshIndex < _index; meshIndex++)
- vertexOffset += _model->LODs[_lodIndex].Meshes[meshIndex].GetVertexCount();
+ vertexOffset += ((Model*)_model)->LODs[_lodIndex].Meshes[meshIndex].GetVertexCount();
drawCall.Geometry.VertexBuffers[2] = info.VertexColors[_lodIndex];
drawCall.Geometry.VertexBuffersOffsets[2] = vertexOffset * sizeof(VB2ElementType);
}
@@ -464,7 +455,7 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float
renderContext.List->AddDrawCall(drawModes, info.Flags, drawCall, entry.ReceiveDecals);
}
-bool Mesh::ExtractData(MeshBufferType type, BytesContainer& result) const
+bool Mesh::DownloadDataGPU(MeshBufferType type, BytesContainer& result) const
{
GPUBuffer* buffer = nullptr;
switch (type)
@@ -485,7 +476,7 @@ bool Mesh::ExtractData(MeshBufferType type, BytesContainer& result) const
return buffer && buffer->DownloadData(result);
}
-Task* Mesh::ExtractDataAsync(MeshBufferType type, BytesContainer& result) const
+Task* Mesh::DownloadDataGPUAsync(MeshBufferType type, BytesContainer& result) const
{
GPUBuffer* buffer = nullptr;
switch (type)
@@ -506,6 +497,15 @@ Task* Mesh::ExtractDataAsync(MeshBufferType type, BytesContainer& result) const
return buffer ? buffer->DownloadDataAsync(result) : nullptr;
}
+bool Mesh::DownloadDataCPU(MeshBufferType type, BytesContainer& result) const
+{
+#if !BUILD_RELEASE
+ // TODO: implement this
+ LOG(Error, "Mesh::DownloadDataCPU not implemented.");
+#endif
+ return true;
+}
+
ScriptingObject* Mesh::GetParentModel()
{
return _model;
@@ -661,7 +661,7 @@ bool Mesh::DownloadBuffer(bool forceGpu, MonoArray* resultObj, int32 typeI)
// TODO: support reusing the input memory buffer to perform a single copy from staging buffer to the input CPU buffer
BytesContainer data;
- auto task = mesh->ExtractDataAsync(bufferType, data);
+ auto task = mesh->DownloadDataGPUAsync(bufferType, data);
if (task == nullptr)
return true;
diff --git a/Source/Engine/Graphics/Models/Mesh.h b/Source/Engine/Graphics/Models/Mesh.h
index 83c37c530..f378f9f8e 100644
--- a/Source/Engine/Graphics/Models/Mesh.h
+++ b/Source/Engine/Graphics/Models/Mesh.h
@@ -2,9 +2,7 @@
#pragma once
-#include "Engine/Core/Math/BoundingBox.h"
-#include "Engine/Core/Math/BoundingSphere.h"
-#include "Engine/Scripting/ScriptingObject.h"
+#include "MeshBase.h"
#include "Engine/Renderer/RenderList.h"
#include "Engine/Graphics/RenderTask.h"
#include "ModelInstanceEntry.h"
@@ -19,21 +17,14 @@ class GPUBuffer;
///
/// Represents part of the model that is made of vertices and can be rendered using custom material and transformation.
///
-API_CLASS(NoSpawn) class FLAXENGINE_API Mesh : public PersistentScriptingObject
+API_CLASS(NoSpawn) class FLAXENGINE_API Mesh : public MeshBase
{
-DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(Mesh, PersistentScriptingObject);
+DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(Mesh, MeshBase);
protected:
- Model* _model;
int32 _index;
int32 _lodIndex;
- int32 _materialSlotIndex;
- bool _use16BitIndexBuffer;
bool _hasLightmapUVs;
- BoundingBox _box;
- BoundingSphere _sphere;
- uint32 _vertices;
- uint32 _triangles;
GPUBuffer* _vertexBuffers[3];
GPUBuffer* _indexBuffer;
#if USE_PRECISE_MESH_INTERSECTS
@@ -62,7 +53,7 @@ public:
///
FORCE_INLINE Model* GetModel() const
{
- return _model;
+ return (Model*)_model;
}
///
@@ -81,35 +72,6 @@ public:
return _index;
}
- ///
- /// Gets the index of the material slot to use during this mesh rendering.
- ///
- API_PROPERTY() FORCE_INLINE int32 GetMaterialSlotIndex() const
- {
- return _materialSlotIndex;
- }
-
- ///
- /// Sets the index of the material slot to use during this mesh rendering.
- ///
- API_PROPERTY() void SetMaterialSlotIndex(int32 value);
-
- ///
- /// Gets the triangle count.
- ///
- API_PROPERTY() FORCE_INLINE int32 GetTriangleCount() const
- {
- return _triangles;
- }
-
- ///
- /// Gets the vertex count.
- ///
- API_PROPERTY() FORCE_INLINE int32 GetVertexCount() const
- {
- return _vertices;
- }
-
///
/// Gets the index buffer.
///
@@ -138,15 +100,6 @@ public:
return _vertexBuffers[0] != nullptr;
}
- ///
- /// Determines whether this mesh is using 16 bit index buffer, otherwise it's 32 bit.
- ///
- /// True if this mesh is using 16 bit index buffer, otherwise 32 bit index buffer.
- API_PROPERTY() FORCE_INLINE bool Use16BitIndexBuffer() const
- {
- return _use16BitIndexBuffer;
- }
-
///
/// Determines whether this mesh has a vertex colors buffer.
///
@@ -165,34 +118,6 @@ public:
return _hasLightmapUVs;
}
- ///
- /// Sets the mesh bounds.
- ///
- /// The bounding box.
- void SetBounds(const BoundingBox& box)
- {
- _box = box;
- BoundingSphere::FromBox(box, _sphere);
- }
-
- ///
- /// Gets the box.
- ///
- /// The bounding box.
- API_PROPERTY() FORCE_INLINE const BoundingBox& GetBox() const
- {
- return _box;
- }
-
- ///
- /// Gets the sphere.
- ///
- /// The bounding sphere.
- API_PROPERTY() FORCE_INLINE const BoundingSphere& GetSphere() const
- {
- return _sphere;
- }
-
#if USE_PRECISE_MESH_INTERSECTS
///
@@ -473,21 +398,10 @@ public:
public:
- ///
- /// Extract mesh buffer data (cannot be called from the main thread!).
- ///
- /// Buffer type
- /// The result data
- /// True if failed, otherwise false
- bool ExtractData(MeshBufferType type, BytesContainer& result) const;
-
- ///
- /// Extracts mesh buffer data in the async task.
- ///
- /// Buffer type
- /// The result data
- /// Created async task used to gather the buffer data.
- Task* ExtractDataAsync(MeshBufferType type, BytesContainer& result) const;
+ // [MeshBase]
+ bool DownloadDataGPU(MeshBufferType type, BytesContainer& result) const override;
+ Task* DownloadDataGPUAsync(MeshBufferType type, BytesContainer& result) const override;
+ bool DownloadDataCPU(MeshBufferType type, BytesContainer& result) const override;
private:
diff --git a/Source/Engine/Graphics/Models/MeshBase.h b/Source/Engine/Graphics/Models/MeshBase.h
new file mode 100644
index 000000000..bedb57c90
--- /dev/null
+++ b/Source/Engine/Graphics/Models/MeshBase.h
@@ -0,0 +1,134 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+#pragma once
+
+#include "Engine/Core/Math/BoundingBox.h"
+#include "Engine/Core/Math/BoundingSphere.h"
+#include "Engine/Core/Types/DataContainer.h"
+#include "Engine/Graphics/Models/Types.h"
+#include "Engine/Scripting/ScriptingObject.h"
+
+class Task;
+class ModelBase;
+
+///
+/// Base class for model resources meshes.
+///
+API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API MeshBase : public PersistentScriptingObject
+{
+DECLARE_SCRIPTING_TYPE_MINIMAL(MeshBase);
+protected:
+
+ ModelBase* _model;
+ bool _use16BitIndexBuffer;
+ BoundingBox _box;
+ BoundingSphere _sphere;
+ uint32 _vertices;
+ uint32 _triangles;
+ int32 _materialSlotIndex;
+
+ explicit MeshBase(const SpawnParams& params)
+ : PersistentScriptingObject(params)
+ {
+ }
+
+public:
+
+ ///
+ /// Gets the model owning this mesh.
+ ///
+ FORCE_INLINE ModelBase* GetModelBase() const
+ {
+ return _model;
+ }
+
+ ///
+ /// Gets the triangle count.
+ ///
+ /// The triangles
+ API_PROPERTY() FORCE_INLINE int32 GetTriangleCount() const
+ {
+ return _triangles;
+ }
+
+ ///
+ /// Gets the vertex count.
+ ///
+ /// The vertices
+ API_PROPERTY() FORCE_INLINE int32 GetVertexCount() const
+ {
+ return _vertices;
+ }
+
+ ///
+ /// Gets the box.
+ ///
+ /// The bounding box.
+ API_PROPERTY() FORCE_INLINE const BoundingBox& GetBox() const
+ {
+ return _box;
+ }
+
+ ///
+ /// Gets the sphere.
+ ///
+ /// The bounding sphere.
+ API_PROPERTY() FORCE_INLINE const BoundingSphere& GetSphere() const
+ {
+ return _sphere;
+ }
+
+ ///
+ /// Determines whether this mesh is using 16 bit index buffer, otherwise it's 32 bit.
+ ///
+ /// True if this mesh is using 16 bit index buffer, otherwise 32 bit index buffer.
+ API_PROPERTY() FORCE_INLINE bool Use16BitIndexBuffer() const
+ {
+ return _use16BitIndexBuffer;
+ }
+
+ ///
+ /// Gets the index of the material slot to use during this mesh rendering.
+ ///
+ API_PROPERTY() FORCE_INLINE int32 GetMaterialSlotIndex() const
+ {
+ return _materialSlotIndex;
+ }
+
+ ///
+ /// Sets the index of the material slot to use during this mesh rendering.
+ ///
+ API_PROPERTY() void SetMaterialSlotIndex(int32 value);
+
+ ///
+ /// Sets the mesh bounds.
+ ///
+ /// The bounding box.
+ void SetBounds(const BoundingBox& box);
+
+public:
+
+ ///
+ /// Extract mesh buffer data from GPU. Cannot be called from the main thread.
+ ///
+ /// Buffer type
+ /// The result data
+ /// True if failed, otherwise false
+ virtual bool DownloadDataGPU(MeshBufferType type, BytesContainer& result) const = 0;
+
+ ///
+ /// Extracts mesh buffer data from GPU in the async task.
+ ///
+ /// Buffer type
+ /// The result data
+ /// Created async task used to gather the buffer data.
+ virtual Task* DownloadDataGPUAsync(MeshBufferType type, BytesContainer& result) const = 0;
+
+ ///
+ /// Extract mesh buffer data from CPU. Cached internally.
+ ///
+ /// Buffer type
+ /// The result data
+ /// True if failed, otherwise false
+ virtual bool DownloadDataCPU(MeshBufferType type, BytesContainer& result) const = 0;
+};
diff --git a/Source/Engine/Graphics/Models/SkeletonData.h b/Source/Engine/Graphics/Models/SkeletonData.h
index 5f336d8be..3e5700304 100644
--- a/Source/Engine/Graphics/Models/SkeletonData.h
+++ b/Source/Engine/Graphics/Models/SkeletonData.h
@@ -5,6 +5,8 @@
#include "Engine/Core/Math/Transform.h"
#include "Engine/Core/Math/Matrix.h"
#include "Engine/Core/Types/String.h"
+#include "Engine/Core/Types/StringView.h"
+#include "Engine/Core/Collections/Array.h"
///
/// Describes a single skeleton node data. Used by the runtime.
diff --git a/Source/Engine/Graphics/Models/SkinnedMesh.cpp b/Source/Engine/Graphics/Models/SkinnedMesh.cpp
index 9e26867ab..41d7cfb5b 100644
--- a/Source/Engine/Graphics/Models/SkinnedMesh.cpp
+++ b/Source/Engine/Graphics/Models/SkinnedMesh.cpp
@@ -34,17 +34,6 @@ SkinnedMesh::~SkinnedMesh()
SAFE_DELETE_GPU_RESOURCE(_indexBuffer);
}
-void SkinnedMesh::SetMaterialSlotIndex(int32 value)
-{
- if (value < 0 || value >= _model->MaterialSlots.Count())
- {
- LOG(Warning, "Cannot set mesh material slot to {0} while model has {1} slots.", value, _model->MaterialSlots.Count());
- return;
- }
-
- _materialSlotIndex = value;
-}
-
bool SkinnedMesh::Load(uint32 vertices, uint32 triangles, void* vb0, void* ib, bool use16BitIndexBuffer)
{
// Cache data
@@ -101,6 +90,8 @@ void SkinnedMesh::Unload()
bool SkinnedMesh::UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0SkinnedElementType* vb, void* ib, bool use16BitIndices)
{
+ auto model = (SkinnedModel*)_model;
+
// Setup GPU resources
const bool failed = Load(vertexCount, triangleCount, vb, ib, use16BitIndices);
if (!failed)
@@ -109,7 +100,7 @@ bool SkinnedMesh::UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0Skinne
SetBounds(BoundingBox::FromPoints((Vector3*)vb, vertexCount));
// Send event (actors using this model can update bounds, etc.)
- _model->onLoaded();
+ model->onLoaded();
}
return failed;
@@ -218,7 +209,7 @@ bool SkinnedMesh::DownloadDataGPU(MeshBufferType type, BytesContainer& result) c
return buffer && buffer->DownloadData(result);
}
-Task* SkinnedMesh::DownloadDataAsyncGPU(MeshBufferType type, BytesContainer& result) const
+Task* SkinnedMesh::DownloadDataGPUAsync(MeshBufferType type, BytesContainer& result) const
{
GPUBuffer* buffer = nullptr;
switch (type)
@@ -535,7 +526,7 @@ bool SkinnedMesh::DownloadBuffer(bool forceGpu, MonoArray* resultObj, int32 type
{
// Get data from GPU
// TODO: support reusing the input memory buffer to perform a single copy from staging buffer to the input CPU buffer
- auto task = mesh->DownloadDataAsyncGPU(bufferType, data);
+ auto task = mesh->DownloadDataGPUAsync(bufferType, data);
if (task == nullptr)
return true;
task->Start();
diff --git a/Source/Engine/Graphics/Models/SkinnedMesh.h b/Source/Engine/Graphics/Models/SkinnedMesh.h
index bbdf38014..c61b0a794 100644
--- a/Source/Engine/Graphics/Models/SkinnedMesh.h
+++ b/Source/Engine/Graphics/Models/SkinnedMesh.h
@@ -2,9 +2,7 @@
#pragma once
-#include "Engine/Core/Math/BoundingBox.h"
-#include "Engine/Core/Math/BoundingSphere.h"
-#include "Engine/Scripting/ScriptingObject.h"
+#include "MeshBase.h"
#include "Engine/Renderer/RenderList.h"
#include "Engine/Graphics/RenderTask.h"
#include "ModelInstanceEntry.h"
@@ -16,20 +14,13 @@ class GPUBuffer;
///
/// Represents part of the skinned model that is made of vertices and can be rendered using custom material, transformation and skeleton bones hierarchy.
///
-API_CLASS(NoSpawn) class FLAXENGINE_API SkinnedMesh : public PersistentScriptingObject
+API_CLASS(NoSpawn) class FLAXENGINE_API SkinnedMesh : public MeshBase
{
-DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(SkinnedMesh, PersistentScriptingObject);
+DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(SkinnedMesh, MeshBase);
protected:
- SkinnedModel* _model;
int32 _index;
int32 _lodIndex;
- int32 _materialSlotIndex;
- bool _use16BitIndexBuffer;
- BoundingBox _box;
- BoundingSphere _sphere;
- uint32 _vertices;
- uint32 _triangles;
GPUBuffer* _vertexBuffer;
GPUBuffer* _indexBuffer;
mutable Array _cachedIndexBuffer;
@@ -40,7 +31,7 @@ public:
SkinnedMesh(const SkinnedMesh& other)
: SkinnedMesh()
{
-#if !!BUILD_RELEASE
+#if !BUILD_RELEASE
CRASH; // Not used
#endif
}
@@ -58,7 +49,7 @@ public:
/// The skinned model
FORCE_INLINE SkinnedModel* GetSkinnedModel() const
{
- return _model;
+ return (SkinnedModel*)_model;
}
///
@@ -70,39 +61,6 @@ public:
return _index;
}
- ///
- /// Gets the material slot index.
- ///
- /// The material slot index
- API_PROPERTY() FORCE_INLINE int32 GetMaterialSlotIndex() const
- {
- return _materialSlotIndex;
- }
-
- ///
- /// Sets the index of the material slot index.
- ///
- /// The value.
- API_PROPERTY() void SetMaterialSlotIndex(int32 value);
-
- ///
- /// Gets the triangle count.
- ///
- /// The triangles
- API_PROPERTY() FORCE_INLINE int32 GetTriangleCount() const
- {
- return _triangles;
- }
-
- ///
- /// Gets the vertex count.
- ///
- /// The vertices
- API_PROPERTY() FORCE_INLINE int32 GetVertexCount() const
- {
- return _vertices;
- }
-
///
/// Determines whether this mesh is initialized (has vertex and index buffers initialized).
///
@@ -112,15 +70,6 @@ public:
return _vertexBuffer != nullptr;
}
- ///
- /// Determines whether this mesh is using 16 bit index buffer, otherwise it's 32 bit.
- ///
- /// True if this mesh is using 16 bit index buffer, otherwise 32 bit index buffer.
- API_PROPERTY() FORCE_INLINE bool Use16BitIndexBuffer() const
- {
- return _use16BitIndexBuffer;
- }
-
///
/// Blend shapes used by this mesh.
///
@@ -194,36 +143,6 @@ public:
/// True if failed, otherwise false.
bool UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0SkinnedElementType* vb, void* ib, bool use16BitIndices);
-public:
-
- ///
- /// Sets the mesh bounds.
- ///
- /// The bounding box.
- void SetBounds(const BoundingBox& box)
- {
- _box = box;
- BoundingSphere::FromBox(box, _sphere);
- }
-
- ///
- /// Gets the box.
- ///
- /// The bounding box.
- API_PROPERTY() FORCE_INLINE BoundingBox GetBox() const
- {
- return _box;
- }
-
- ///
- /// Gets the sphere.
- ///
- /// The bounding sphere.
- API_PROPERTY() FORCE_INLINE BoundingSphere GetSphere() const
- {
- return _sphere;
- }
-
public:
///
@@ -319,29 +238,10 @@ public:
public:
- ///
- /// Extract mesh buffer data from the GPU (cannot be called from the main thread!).
- ///
- /// Buffer type
- /// The result data
- /// True if failed, otherwise false
- bool DownloadDataGPU(MeshBufferType type, BytesContainer& result) const;
-
- ///
- /// Extracts mesh buffer data from the GPU in the async task.
- ///
- /// Buffer type
- /// The result data
- /// Created async task used to gather the buffer data.
- Task* DownloadDataAsyncGPU(MeshBufferType type, BytesContainer& result) const;
-
- ///
- /// Extract mesh buffer data from the CPU.
- ///
- /// Buffer type
- /// The result data
- /// True if failed, otherwise false
- bool DownloadDataCPU(MeshBufferType type, BytesContainer& result) const;
+ // [MeshBase]
+ bool DownloadDataGPU(MeshBufferType type, BytesContainer& result) const override;
+ Task* DownloadDataGPUAsync(MeshBufferType type, BytesContainer& result) const override;
+ bool DownloadDataCPU(MeshBufferType type, BytesContainer& result) const override;
private:
diff --git a/Source/Engine/Graphics/RenderTools.cpp b/Source/Engine/Graphics/RenderTools.cpp
index 4fc5e2e1d..c14a18c40 100644
--- a/Source/Engine/Graphics/RenderTools.cpp
+++ b/Source/Engine/Graphics/RenderTools.cpp
@@ -553,3 +553,20 @@ float ViewToCenterLessRadius(const RenderView& view, const Vector3& center, floa
// Calculate result
return viewToCenter - radius;
}
+
+void MeshBase::SetMaterialSlotIndex(int32 value)
+{
+ if (value < 0 || value >= _model->MaterialSlots.Count())
+ {
+ LOG(Warning, "Cannot set mesh material slot to {0} while model has {1} slots.", value, _model->MaterialSlots.Count());
+ return;
+ }
+
+ _materialSlotIndex = value;
+}
+
+void MeshBase::SetBounds(const BoundingBox& box)
+{
+ _box = box;
+ BoundingSphere::FromBox(box, _sphere);
+}
diff --git a/Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.cpp
index f9a39574c..ac56a2a9f 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/CmdBufferVulkan.cpp
@@ -43,7 +43,7 @@ void CmdBufferVulkan::End()
{
ASSERT(IsOutsideRenderPass());
-#if GPU_ALLOW_PROFILE_EVENTS
+#if GPU_ALLOW_PROFILE_EVENTS && VK_EXT_debug_utils
// End remaining events
while (_eventsBegin--)
vkCmdEndDebugUtilsLabelEXT(GetHandle());
@@ -89,6 +89,7 @@ void CmdBufferVulkan::AcquirePoolSet()
void CmdBufferVulkan::BeginEvent(const Char* name)
{
+#if VK_EXT_debug_utils
if (!vkCmdBeginDebugUtilsLabelEXT)
return;
@@ -108,15 +109,18 @@ void CmdBufferVulkan::BeginEvent(const Char* name)
RenderToolsVulkan::ZeroStruct(label, VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT);
label.pLabelName = buffer;
vkCmdBeginDebugUtilsLabelEXT(GetHandle(), &label);
+#endif
}
void CmdBufferVulkan::EndEvent()
{
+#if VK_EXT_debug_utils
if (_eventsBegin == 0 || !vkCmdEndDebugUtilsLabelEXT)
return;
_eventsBegin--;
vkCmdEndDebugUtilsLabelEXT(GetHandle());
+#endif
}
#endif
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.cpp
index 1cd90b11b..2acd2712c 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.cpp
@@ -17,14 +17,17 @@ void GPUBufferViewVulkan::Init(GPUDeviceVulkan* device, GPUBufferVulkan* owner,
Buffer = buffer;
Size = size;
- VkBufferViewCreateInfo viewInfo;
- RenderToolsVulkan::ZeroStruct(viewInfo, VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO);
- viewInfo.buffer = Buffer;
- viewInfo.format = RenderToolsVulkan::ToVulkanFormat(format);
- viewInfo.offset = 0;
- viewInfo.range = Size;
-
- VALIDATE_VULKAN_RESULT(vkCreateBufferView(device->Device, &viewInfo, nullptr, &View));
+ if (owner->IsShaderResource() && !(owner->GetDescription().Flags & GPUBufferFlags::Structured))
+ {
+ VkBufferViewCreateInfo viewInfo;
+ RenderToolsVulkan::ZeroStruct(viewInfo, VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO);
+ viewInfo.buffer = Buffer;
+ viewInfo.format = RenderToolsVulkan::ToVulkanFormat(format);
+ viewInfo.offset = 0;
+ viewInfo.range = Size;
+ ASSERT_LOW_LAYER(viewInfo.format != VK_FORMAT_UNDEFINED);
+ VALIDATE_VULKAN_RESULT(vkCreateBufferView(device->Device, &viewInfo, nullptr, &View));
+ }
}
void GPUBufferViewVulkan::Release()
@@ -32,19 +35,18 @@ void GPUBufferViewVulkan::Release()
if (View != VK_NULL_HANDLE)
{
Device->DeferredDeletionQueue.EnqueueResource(DeferredDeletionQueueVulkan::BufferView, View);
-
View = VK_NULL_HANDLE;
-
-#if BUILD_DEBUG
- Device = nullptr;
- Owner = nullptr;
- Buffer = VK_NULL_HANDLE;
-#endif
}
+#if BUILD_DEBUG
+ Device = nullptr;
+ Owner = nullptr;
+ Buffer = VK_NULL_HANDLE;
+#endif
}
void GPUBufferViewVulkan::DescriptorAsUniformTexelBuffer(GPUContextVulkan* context, const VkBufferView*& bufferView)
{
+ ASSERT_LOW_LAYER(View != VK_NULL_HANDLE);
bufferView = &View;
context->AddBufferBarrier(Owner, VK_ACCESS_SHADER_READ_BIT);
@@ -52,6 +54,7 @@ void GPUBufferViewVulkan::DescriptorAsUniformTexelBuffer(GPUContextVulkan* conte
void GPUBufferViewVulkan::DescriptorAsStorageBuffer(GPUContextVulkan* context, VkBuffer& buffer, VkDeviceSize& offset, VkDeviceSize& range)
{
+ ASSERT_LOW_LAYER(Buffer);
buffer = Buffer;
offset = 0;
range = Size;
@@ -88,7 +91,7 @@ bool GPUBufferVulkan::OnInit()
bufferInfo.size = _desc.Size;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- if (useSRV)
+ if (useSRV && !(_desc.Flags & GPUBufferFlags::Structured))
bufferInfo.usage |= VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
if (useUAV || _desc.Flags & GPUBufferFlags::RawBuffer)
bufferInfo.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
@@ -165,7 +168,7 @@ bool GPUBufferVulkan::OnInit()
}
}
// Check if need to bind buffer to the shaders
- else if (useSRV)
+ else if (useSRV || useUAV)
{
// Create buffer view
_view.Init(_device, this, _buffer, _desc.Size, _desc.Format);
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp
index 07eabe814..d61296f49 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp
@@ -52,6 +52,8 @@ VkDebugReportCallbackEXT MsgCallback = VK_NULL_HANDLE;
extern VulkanValidationLevel ValidationLevel;
+#if VK_EXT_debug_report
+
static VKAPI_ATTR VkBool32 VKAPI_PTR DebugReportFunction(VkDebugReportFlagsEXT msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, int32 msgCode, const char* layerPrefix, const char* msg, void* userData)
{
const Char* msgPrefix = TEXT("UNKNOWN");
@@ -126,6 +128,8 @@ static VKAPI_ATTR VkBool32 VKAPI_PTR DebugReportFunction(VkDebugReportFlagsEXT m
return VK_FALSE;
}
+#endif
+
#if VK_EXT_debug_utils
static VKAPI_ATTR VkBool32 VKAPI_PTR DebugUtilsCallback(VkDebugUtilsMessageSeverityFlagBitsEXT msgSeverity, VkDebugUtilsMessageTypeFlagsEXT msgType, const VkDebugUtilsMessengerCallbackDataEXT* callbackData, void* userData)
@@ -140,8 +144,8 @@ static VKAPI_ATTR VkBool32 VKAPI_PTR DebugUtilsCallback(VkDebugUtilsMessageSever
case 2: // Fragment shader writes to output location 0 with no matching attachment
case 3: // Attachment 2 not written by fragment shader
case 5: // SPIR-V module not valid: MemoryBarrier: Vulkan specification requires Memory Semantics to have one of the following bits set: Acquire, Release, AcquireRelease or SequentiallyConsistent
-#if PLATFORM_ANDROID
case -1666394502: // After query pool creation, each query must be reset before it is used. Queries must also be reset between uses.
+#if PLATFORM_ANDROID
case 602160055: // Attachment 4 not written by fragment shader; undefined values will be written to attachment. TODO: investigate it for PS_GBuffer shader from Deferred material with USE_LIGHTMAP=1
#endif
return VK_FALSE;
@@ -270,6 +274,7 @@ void SetupDebugLayerCallback()
if (SupportsDebugCallbackExt)
#endif
{
+#if VK_EXT_debug_report
if (vkCreateDebugReportCallbackEXT)
{
VkDebugReportCallbackCreateInfoEXT createInfo;
@@ -303,6 +308,7 @@ void SetupDebugLayerCallback()
{
LOG(Warning, "GetProcAddr: Unable to find vkDbgCreateMsgCallback; debug reporting skipped!");
}
+#endif
}
else
{
@@ -324,8 +330,10 @@ void RemoveDebugLayerCallback()
if (MsgCallback != VK_NULL_HANDLE)
#endif
{
+#if VK_EXT_debug_report
if (vkDestroyDebugReportCallbackEXT)
vkDestroyDebugReportCallbackEXT(GPUDeviceVulkan::Instance, MsgCallback, nullptr);
+#endif
MsgCallback = VK_NULL_HANDLE;
}
}
@@ -1085,13 +1093,17 @@ GPUDevice* GPUDeviceVulkan::Create()
}
#endif
+ VkResult result;
+
+#if !PLATFORM_SWITCH
// Initialize bindings
- VkResult result = volkInitialize();
+ result = volkInitialize();
if (result != VK_SUCCESS)
{
LOG(Warning, "Graphics Device init failed with error {0}", RenderToolsVulkan::GetVkErrorString(result));
return nullptr;
}
+#endif
// Engine registration
const StringAsANSI<256> appName(*Globals::ProductName);
@@ -1170,10 +1182,12 @@ GPUDevice* GPUDeviceVulkan::Create()
return nullptr;
}
+#if !PLATFORM_SWITCH
// Setup bindings
volkLoadInstance(Instance);
+#endif
- // Setup debug layer
+// Setup debug layer
#if VULKAN_USE_DEBUG_LAYER
SetupDebugLayerCallback();
#endif
@@ -1658,8 +1672,10 @@ bool GPUDeviceVulkan::Init()
// Create the device
VALIDATE_VULKAN_RESULT(vkCreateDevice(gpu, &deviceInfo, nullptr, &Device));
+#if !PLATFORM_SWITCH
// Optimize bindings
volkLoadDevice(Device);
+#endif
// Create queues
if (graphicsQueueFamilyIndex == -1)
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GraphicsDeviceVulkan.Build.cs b/Source/Engine/GraphicsDevice/Vulkan/GraphicsDeviceVulkan.Build.cs
index 68eb5ffcc..4779beb4f 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GraphicsDeviceVulkan.Build.cs
+++ b/Source/Engine/GraphicsDevice/Vulkan/GraphicsDeviceVulkan.Build.cs
@@ -108,7 +108,15 @@ public class GraphicsDeviceVulkan : GraphicsDeviceBaseModule
options.PublicDefinitions.Add("GRAPHICS_API_VULKAN");
- options.PrivateDependencies.Add("volk");
options.PrivateDependencies.Add("VulkanMemoryAllocator");
+
+ if (options.Platform.Target == TargetPlatform.Switch)
+ {
+ options.SourcePaths.Add(Path.Combine(Globals.EngineRoot, "Source", "Platforms", "Switch", "Engine", "GraphicsDevice", "Vulkan"));
+ }
+ else
+ {
+ options.PrivateDependencies.Add("volk");
+ }
}
}
diff --git a/Source/Engine/GraphicsDevice/Vulkan/IncludeVulkanHeaders.h b/Source/Engine/GraphicsDevice/Vulkan/IncludeVulkanHeaders.h
index 3e00a9e87..fec251eca 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/IncludeVulkanHeaders.h
+++ b/Source/Engine/GraphicsDevice/Vulkan/IncludeVulkanHeaders.h
@@ -8,6 +8,19 @@
#include "Engine/Core/Math/Math.h"
+#if PLATFORM_SWITCH
+
+#define VK_USE_PLATFORM_VI_NN 1
+#include
+#undef VK_EXT_debug_utils
+#undef VK_EXT_debug_report
+#undef VK_EXT_validation_cache
+#define VMA_DEDICATED_ALLOCATION 0
+#pragma clang diagnostic ignored "-Wpointer-bool-conversion"
+#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
+
+#else
+
#if PLATFORM_WIN32
#include "Engine/Platform/Win32/IncludeWindowsHeaders.h"
#endif
@@ -17,6 +30,8 @@
// License: MIT
#include
+#endif
+
// Use Vulkan Memory Allocator for buffer and image memory allocations
// Source: https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/
// License: MIT
diff --git a/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.cpp
index e974396a4..d24c5742d 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.cpp
@@ -241,7 +241,9 @@ String RenderToolsVulkan::GetVkErrorString(VkResult result)
VKERR(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR);
VKERR(VK_ERROR_VALIDATION_FAILED_EXT);
VKERR(VK_ERROR_INVALID_SHADER_NV);
+#if VK_HEADER_VERSION >= 89
VKERR(VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT);
+#endif
VKERR(VK_ERROR_FRAGMENTATION_EXT);
VKERR(VK_ERROR_NOT_PERMITTED_EXT);
#if VK_HEADER_VERSION < 140
diff --git a/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.h
index cf9b7e9cf..ec5d882bc 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.h
+++ b/Source/Engine/GraphicsDevice/Vulkan/RenderToolsVulkan.h
@@ -78,6 +78,9 @@ public:
case 0:
stageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
break;
+ case VK_ACCESS_INDIRECT_COMMAND_READ_BIT:
+ stageFlags = VK_PIPELINE_STAGE_TRANSFER_BIT;
+ break;
case VK_ACCESS_TRANSFER_WRITE_BIT:
stageFlags = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
diff --git a/Source/Engine/GraphicsDevice/Vulkan/VulkanPlatform.h b/Source/Engine/GraphicsDevice/Vulkan/VulkanPlatform.h
index 8e585c78e..bc216190b 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/VulkanPlatform.h
+++ b/Source/Engine/GraphicsDevice/Vulkan/VulkanPlatform.h
@@ -8,4 +8,6 @@
#include "Linux/LinuxVulkanPlatform.h"
#elif PLATFORM_ANDROID
#include "Android/AndroidVulkanPlatform.h"
+#elif PLATFORM_SWITCH
+#include "Platforms/Switch/Engine/GraphicsDevice/Vulkan/SwitchVulkanPlatform.h"
#endif
diff --git a/Source/Engine/Input/InputSettings.h b/Source/Engine/Input/InputSettings.h
index 7771028e8..fd594f3ee 100644
--- a/Source/Engine/Input/InputSettings.h
+++ b/Source/Engine/Input/InputSettings.h
@@ -5,6 +5,7 @@
#include "Engine/Core/Config/Settings.h"
#include "Engine/Serialization/JsonTools.h"
#include "VirtualInput.h"
+#include "Engine/Core/Collections/Array.h"
///
/// Input settings container.
diff --git a/Source/Engine/Level/Actor.cpp b/Source/Engine/Level/Actor.cpp
index ef5b2a554..93f5c05c6 100644
--- a/Source/Engine/Level/Actor.cpp
+++ b/Source/Engine/Level/Actor.cpp
@@ -16,6 +16,7 @@
#include "Engine/Core/Collections/CollectionPoolCache.h"
#include "Engine/Debug/Exceptions/JsonParseException.h"
#include "Engine/Graphics/RenderView.h"
+#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Scripting/Scripting.h"
#include "Engine/Serialization/ISerializeModifier.h"
#include "Engine/Serialization/Serialization.h"
@@ -1494,6 +1495,7 @@ void WriteObjectToBytes(SceneObject* obj, rapidjson_flax::StringBuffer& buffer,
bool Actor::ToBytes(const Array& actors, MemoryWriteStream& output)
{
+ PROFILE_CPU();
if (actors.IsEmpty())
{
// Cannot serialize empty list
@@ -1553,6 +1555,7 @@ Array Actor::ToBytes(const Array& actors)
bool Actor::FromBytes(const Span& data, Array& output, ISerializeModifier* modifier)
{
+ PROFILE_CPU();
output.Clear();
ASSERT(modifier);
@@ -1597,7 +1600,7 @@ bool Actor::FromBytes(const Span& data, Array& output, ISerializeM
// Order in parent
int32 orderInParent;
stream.ReadInt32(&orderInParent);
- order.At(i) = orderInParent;
+ order[i] = orderInParent;
// Load JSON
rapidjson_flax::Document document;
@@ -1637,7 +1640,6 @@ bool Actor::FromBytes(const Span& data, Array& output, ISerializeM
// Order in parent
int32 orderInParent;
stream.ReadInt32(&orderInParent);
- order.Add(orderInParent);
// Load JSON
rapidjson_flax::Document document;
@@ -1655,17 +1657,19 @@ bool Actor::FromBytes(const Span& data, Array& output, ISerializeM
Scripting::ObjectsLookupIdMapping.Set(nullptr);
// Link objects
- for (int32 i = 0; i < objectsCount; i++)
+ //for (int32 i = 0; i < objectsCount; i++)
{
- SceneObject* obj = sceneObjects->At(i);
- obj->PostLoad();
+ //SceneObject* obj = sceneObjects->At(i);
+ // TODO: post load or post spawn?
+ //obj->PostLoad();
}
// Update objects order
- for (int32 i = 0; i < objectsCount; i++)
+ //for (int32 i = 0; i < objectsCount; i++)
{
- SceneObject* obj = sceneObjects->At(i);
- obj->SetOrderInParent(order[i]);
+ //SceneObject* obj = sceneObjects->At(i);
+ // TODO: remove order from saved data?
+ //obj->SetOrderInParent(order[i]);
}
// Call events (only for parents because they will propagate events down the tree)
@@ -1682,6 +1686,10 @@ bool Actor::FromBytes(const Span& data, Array& output, ISerializeM
}
}
for (int32 i = 0; i < parents->Count(); i++)
+ {
+ parents->At(i)->PostSpawn();
+ }
+ for (int32 i = 0; i < parents->Count(); i++)
{
Actor* actor = parents->At(i);
actor->OnTransformChanged();
@@ -1723,6 +1731,7 @@ Array Actor::FromBytes(const Span& data, const Dictionary Actor::TryGetSerializedObjectsIds(const Span& data)
{
+ PROFILE_CPU();
Array result;
if (data.Length() > 0)
{
@@ -1743,6 +1752,7 @@ Array Actor::TryGetSerializedObjectsIds(const Span& data)
String Actor::ToJson()
{
+ PROFILE_CPU();
rapidjson_flax::StringBuffer buffer;
CompactJsonWriter writer(buffer);
writer.SceneObject(this);
@@ -1754,6 +1764,8 @@ String Actor::ToJson()
void Actor::FromJson(const StringAnsiView& json)
{
+ PROFILE_CPU();
+
// Load JSON
rapidjson_flax::Document document;
document.Parse(json.Get(), json.Length());
diff --git a/Source/Engine/Level/Prefabs/Prefab.cpp b/Source/Engine/Level/Prefabs/Prefab.cpp
index ed4ed2a2b..53bbb9d14 100644
--- a/Source/Engine/Level/Prefabs/Prefab.cpp
+++ b/Source/Engine/Level/Prefabs/Prefab.cpp
@@ -11,7 +11,7 @@
#include "Engine/Scripting/Scripting.h"
#endif
-REGISTER_JSON_ASSET(Prefab, "FlaxEngine.Prefab");
+REGISTER_JSON_ASSET(Prefab, "FlaxEngine.Prefab", false);
Prefab::Prefab(const SpawnParams& params, const AssetInfo* info)
: JsonAssetBase(params, info)
diff --git a/Source/Engine/Level/Scene/Scene.cpp b/Source/Engine/Level/Scene/Scene.cpp
index 94de9d713..968c6d0aa 100644
--- a/Source/Engine/Level/Scene/Scene.cpp
+++ b/Source/Engine/Level/Scene/Scene.cpp
@@ -14,7 +14,7 @@
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Serialization/Serialization.h"
-REGISTER_JSON_ASSET(SceneAsset, "FlaxEngine.SceneAsset");
+REGISTER_JSON_ASSET(SceneAsset, "FlaxEngine.SceneAsset", false);
SceneAsset::SceneAsset(const SpawnParams& params, const AssetInfo* info)
: JsonAsset(params, info)
diff --git a/Source/Engine/Localization/CultureInfo.cpp b/Source/Engine/Localization/CultureInfo.cpp
new file mode 100644
index 000000000..d46bacfbe
--- /dev/null
+++ b/Source/Engine/Localization/CultureInfo.cpp
@@ -0,0 +1,190 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+#include "CultureInfo.h"
+#include "Engine/Core/Log.h"
+#include "Engine/Scripting/ManagedCLR/MType.h"
+#include "Engine/Utilities/StringConverter.h"
+#if USE_MONO
+#include
+#include
+#include
+
+typedef struct
+{
+ MonoObject obj;
+ MonoBoolean is_read_only;
+ gint32 lcid;
+ //...
+} MonoCultureInfo;
+#endif
+
+CultureInfo::CultureInfo(int32 lcid)
+{
+ _lcid = lcid;
+ _lcidParent = 0;
+ _data = nullptr;
+ if (lcid == 0)
+ return;
+ if (lcid == 127)
+ {
+ _englishName = TEXT("Invariant Culture");
+ return;
+ }
+#if USE_MONO
+ for (int32 i = 0; i < NUM_CULTURE_ENTRIES; i++)
+ {
+ auto& e = culture_entries[i];
+ if (e.lcid == lcid)
+ {
+ _data = (void*)&e;
+ _lcidParent = (int32)e.parent_lcid;
+ const char* name = idx2string(e.name);
+ _name.SetUTF8(name, StringUtils::Length(name));
+ const char* nativename = idx2string(e.nativename);
+ _nativeName.SetUTF8(nativename, StringUtils::Length(nativename));
+ const char* englishname = idx2string(e.englishname);
+ _englishName.SetUTF8(englishname, StringUtils::Length(englishname));
+ break;
+ }
+ }
+#else
+#error "Missing CultureInfo implementation."
+#endif
+ if (!_data)
+ {
+ _englishName = TEXT("Invariant Culture");
+ LOG(Error, "Unknown LCID {0} for CultureInfo", lcid);
+ }
+}
+
+CultureInfo::CultureInfo(const StringView& name)
+ : CultureInfo(StringAnsiView(StringAsANSI<16>(name.Get(), name.Length()).Get(), name.Length()))
+{
+}
+
+CultureInfo::CultureInfo(const StringAnsiView& name)
+{
+ _data = nullptr;
+ if (name.IsEmpty())
+ {
+ _lcid = 127;
+ _lcidParent = 0;
+ _englishName = TEXT("Invariant Culture");
+ return;
+ }
+#if USE_MONO
+ for (int32 i = 0; i < NUM_CULTURE_ENTRIES; i++)
+ {
+ auto& e = culture_entries[i];
+ if (name == idx2string(e.name))
+ {
+ _data = (void*)&e;
+ _lcid = (int32)e.lcid;
+ _lcidParent = (int32)e.parent_lcid;
+ _name.SetUTF8(name.Get(), name.Length());
+ const char* nativename = idx2string(e.nativename);
+ _nativeName.SetUTF8(nativename, StringUtils::Length(nativename));
+ const char* englishname = idx2string(e.englishname);
+ _englishName.SetUTF8(englishname, StringUtils::Length(englishname));
+ break;
+ }
+ }
+#else
+#error "Missing CultureInfo implementation."
+#endif
+ if (!_data)
+ {
+ _lcid = 127;
+ _lcidParent = 0;
+ _englishName = TEXT("Invariant Culture");
+ LOG(Error, "Unknown name {0} for CultureInfo", String(name));
+ }
+}
+
+int32 CultureInfo::GetLCID() const
+{
+ return _lcid;
+}
+
+int32 CultureInfo::GetParentLCID() const
+{
+ return _lcidParent;
+}
+
+const String& CultureInfo::GetName() const
+{
+ return _name;
+}
+
+const String& CultureInfo::GetNativeName() const
+{
+ return _nativeName;
+}
+
+const String& CultureInfo::GetEnglishName() const
+{
+ return _englishName;
+}
+
+bool CultureInfo::IsRightToLeft() const
+{
+#if USE_MONO
+ const auto data = static_cast(_data);
+ if (data)
+ return data->text_info.is_right_to_left ? true : false;
+#else
+#error "Missing CultureInfo implementation."
+#endif
+ return false;
+}
+
+String CultureInfo::ToString() const
+{
+ return _name;
+}
+
+bool CultureInfo::operator==(const CultureInfo& other) const
+{
+ return _lcid == other._lcid;
+}
+
+void* MUtils::ToManaged(const CultureInfo& value)
+{
+#if USE_MONO
+ const auto klass = mono_class_from_name(mono_get_corlib(), "System.Globalization", "CultureInfo");
+ if (klass)
+ {
+ void* iter = nullptr;
+ MonoMethod* method;
+ while ((method = mono_class_get_methods(klass, &iter)))
+ {
+ if (StringUtils::Compare(mono_method_get_name(method), ".ctor") == 0)
+ {
+ const auto sig = mono_method_signature(method);
+ void* sigParams = nullptr;
+ mono_signature_get_params(sig, &sigParams);
+ if (mono_signature_get_param_count(sig) == 1 && mono_type_get_class(((MonoType**)sigParams)[0]) != mono_get_string_class())
+ {
+ MonoObject* obj = mono_object_new(mono_domain_get(), klass);
+ int32 lcid = value.GetLCID();
+ void* params[1];
+ params[0] = &lcid;
+ mono_runtime_invoke(method, obj, params, nullptr);
+ return obj;
+ }
+ }
+ }
+ }
+#endif
+ return nullptr;
+}
+
+CultureInfo MUtils::ToNative(void* value)
+{
+ int32 lcid = 127;
+#if USE_MONO
+ if (value)
+ lcid = static_cast(value)->lcid;
+#endif
+ return CultureInfo(lcid);
+}
diff --git a/Source/Engine/Localization/CultureInfo.h b/Source/Engine/Localization/CultureInfo.h
new file mode 100644
index 000000000..7a156e2dd
--- /dev/null
+++ b/Source/Engine/Localization/CultureInfo.h
@@ -0,0 +1,82 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+#pragma once
+
+#include "Engine/Core/Types/String.h"
+#include "Engine/Core/Formatting.h"
+
+///
+/// The information about a specific culture (aka locale). The information includes the names for the culture, the writing system, the calendar used, the sort order of strings, and formatting for dates and numbers.
+///
+API_CLASS(InBuild, Namespace="System.Globalization") class FLAXENGINE_API CultureInfo
+{
+DECLARE_SCRIPTING_TYPE_MINIMAL(CultureInfo);
+private:
+ void* _data;
+ int32 _lcid;
+ int32 _lcidParent;
+ String _name;
+ String _nativeName;
+ String _englishName;
+
+public:
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The culture identifier.
+ CultureInfo(int32 lcid);
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The culture name (eg. pl-PL).
+ CultureInfo(const StringView& name);
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The culture name (eg. pl-PL).
+ CultureInfo(const StringAnsiView& name);
+
+public:
+ ///
+ /// Gets the culture identifier.
+ ///
+ int32 GetLCID() const;
+
+ ///
+ /// Gets the parent culture identifier.
+ ///
+ int32 GetParentLCID() const;
+
+ ///
+ /// Gets the culture name (eg. pl-PL).
+ ///
+ const String& GetName() const;
+
+ ///
+ /// Gets the full localized culture name (eg. Polish (Poland)).
+ ///
+ const String& GetNativeName() const;
+
+ ///
+ /// Gets the culture name in English (eg. polski (Polska)).
+ ///
+ const String& GetEnglishName() const;
+
+ ///
+ /// Returns true if culture uses right-to-left (RTL) text layout. Otherwise it's more common left-to-right.
+ ///
+ bool IsRightToLeft() const;
+
+ String ToString() const;
+ bool operator==(const CultureInfo& other) const;
+};
+
+DEFINE_DEFAULT_FORMATTING_VIA_TO_STRING(CultureInfo);
+
+namespace MUtils
+{
+ extern void* ToManaged(const CultureInfo& value);
+ extern CultureInfo ToNative(void* value);
+}
diff --git a/Source/Engine/Localization/Localization.Build.cs b/Source/Engine/Localization/Localization.Build.cs
new file mode 100644
index 000000000..7f730dcab
--- /dev/null
+++ b/Source/Engine/Localization/Localization.Build.cs
@@ -0,0 +1,23 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+using Flax.Build;
+using Flax.Build.NativeCpp;
+
+///
+/// Localization and internalization module.
+///
+public class Localization : EngineModule
+{
+ ///
+ public override void Setup(BuildOptions options)
+ {
+ base.Setup(options);
+
+ options.PublicDependencies.Add("Scripting");
+
+ if (options.Target.IsEditor)
+ {
+ options.PrivateDependencies.Add("ContentImporters");
+ }
+ }
+}
diff --git a/Source/Engine/Localization/Localization.cpp b/Source/Engine/Localization/Localization.cpp
new file mode 100644
index 000000000..1de886590
--- /dev/null
+++ b/Source/Engine/Localization/Localization.cpp
@@ -0,0 +1,286 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+#include "Localization.h"
+#include "CultureInfo.h"
+#include "LocalizedString.h"
+#include "LocalizationSettings.h"
+#include "Engine/Core/Log.h"
+#include "Engine/Core/Config/GameSettings.h"
+#include "Engine/Engine/EngineService.h"
+#include "Engine/Content/Content.h"
+#include "Engine/Profiler/ProfilerCPU.h"
+#include "Engine/Serialization/Serialization.h"
+#include
+
+class LocalizationService : public EngineService
+{
+public:
+ CultureInfo CurrentCulture;
+ CultureInfo CurrentLanguage;
+ Array> LocalizedStringTables;
+
+ LocalizationService()
+ : EngineService(TEXT("Localization"), -500)
+ , CurrentCulture(0)
+ , CurrentLanguage(0)
+ {
+ }
+
+ void OnLocalizationChanged();
+
+ bool Init() override;
+};
+
+namespace
+{
+ LocalizationService Instance;
+}
+
+IMPLEMENT_SETTINGS_GETTER(LocalizationSettings, Localization);
+
+void LocalizationSettings::Apply()
+{
+ Instance.OnLocalizationChanged();
+}
+
+void LocalizationSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
+{
+ DESERIALIZE(LocalizedStringTables);
+}
+
+LocalizedString::LocalizedString(const LocalizedString& other)
+ : Id(other.Id)
+ , Value(other.Value)
+{
+}
+
+LocalizedString::LocalizedString(LocalizedString&& other) noexcept
+ : Id(MoveTemp(other.Id))
+ , Value(MoveTemp(other.Value))
+{
+}
+
+LocalizedString::LocalizedString(const StringView& value)
+ : Value(value)
+{
+}
+
+LocalizedString::LocalizedString(String&& value) noexcept
+ : Value(MoveTemp(value))
+{
+}
+
+LocalizedString& LocalizedString::operator=(const LocalizedString& other)
+{
+ if (this != &other)
+ {
+ Id = other.Id;
+ Value = other.Value;
+ }
+ return *this;
+}
+
+LocalizedString& LocalizedString::operator=(LocalizedString&& other) noexcept
+{
+ if (this != &other)
+ {
+ Id = MoveTemp(other.Id);
+ Value = MoveTemp(other.Value);
+ }
+ return *this;
+}
+
+LocalizedString& LocalizedString::operator=(const StringView& value)
+{
+ Id.Clear();
+ Value = value;
+ return *this;
+}
+
+LocalizedString& LocalizedString::operator=(String&& value) noexcept
+{
+ Id.Clear();
+ Value = MoveTemp(value);
+ return *this;
+}
+
+String LocalizedString::ToString() const
+{
+ return Localization::GetString(Id, Value);
+}
+
+String LocalizedString::ToStringPlural(int32 n) const
+{
+ return Localization::GetPluralString(Id, n, Value);
+}
+
+void LocalizationService::OnLocalizationChanged()
+{
+ PROFILE_CPU();
+
+ Instance.LocalizedStringTables.Clear();
+
+ // Collect all localization tables into mapping locale -> tables
+ auto& settings = *LocalizationSettings::Get();
+ Dictionary, InlinedAllocation<8>>> tables;
+ for (auto& e : settings.LocalizedStringTables)
+ {
+ auto table = e.Get();
+ if (table && !table->WaitForLoaded())
+ {
+ tables[table->Locale].Add(table);
+ }
+ }
+
+ // Pick localization tables for a current language
+ auto* table = tables.TryGet(Instance.CurrentLanguage.GetName());
+ if (!table)
+ {
+ // Try using parent culture (eg. en if en-GB is missing)
+ const CultureInfo parentLanguage(Instance.CurrentLanguage.GetParentLCID());
+ if (parentLanguage.GetName().HasChars())
+ table = tables.TryGet(parentLanguage.GetName());
+ if (!table)
+ {
+ // Fallback to English
+ const CultureInfo english("en");
+ table = tables.TryGet(english.GetName());
+ }
+ }
+
+ // Apply localization table
+ if (table)
+ {
+ String locale;
+ for (auto& e : tables)
+ {
+ if (&e.Value == table)
+ {
+ locale = e.Key;
+ break;
+ }
+ }
+ LOG(Info, "Using localization for {0}", locale);
+ Instance.LocalizedStringTables.Add(table->Get(), table->Count());
+ }
+
+ // Change C++ locale (eg. used by fmt lib for values formatting)
+ {
+ char localeName[100];
+ const auto& currentCulture = Instance.CurrentCulture.GetName();
+ if (currentCulture.IsEmpty())
+ {
+ localeName[0] = 0;
+ }
+ else
+ {
+ StringUtils::ConvertUTF162ANSI(currentCulture.GetText(), localeName, currentCulture.Length());
+ for (int32 i = 0; i < currentCulture.Length(); i++)
+ if (localeName[i] == '-')
+ localeName[i] = '_';
+ localeName[currentCulture.Length() + 0] = '.';
+ localeName[currentCulture.Length() + 1] = 'U';
+ localeName[currentCulture.Length() + 2] = 'T';
+ localeName[currentCulture.Length() + 3] = 'F';
+ localeName[currentCulture.Length() + 4] = '-';
+ localeName[currentCulture.Length() + 5] = '8';
+ localeName[currentCulture.Length() + 6] = 0;
+ }
+ std::locale::global(std::locale(localeName));
+ }
+
+ // Send event
+ Localization::LocalizationChanged();
+}
+
+bool LocalizationService::Init()
+{
+ // Use system language as default
+ CurrentLanguage = CurrentCulture = CultureInfo(Platform::GetUserLocaleName());
+
+ // Setup localization
+ Instance.OnLocalizationChanged();
+
+ return false;
+}
+
+Delegate<> Localization::LocalizationChanged;
+
+const CultureInfo& Localization::GetCurrentCulture()
+{
+ return Instance.CurrentCulture;
+}
+
+void Localization::SetCurrentCulture(const CultureInfo& value)
+{
+ if (Instance.CurrentCulture == value)
+ return;
+
+ LOG(Info, "Changing current culture to: {0} ({1})", value.GetName(), value.GetLCID());
+ Instance.CurrentCulture = value;
+ Instance.OnLocalizationChanged();
+}
+
+const CultureInfo& Localization::GetCurrentLanguage()
+{
+ return Instance.CurrentLanguage;
+}
+
+void Localization::SetCurrentLanguage(const CultureInfo& value)
+{
+ if (Instance.CurrentLanguage == value)
+ return;
+
+ LOG(Info, "Changing current language to: {0} ({1})", value.GetName(), value.GetLCID());
+ Instance.CurrentLanguage = value;
+ Instance.OnLocalizationChanged();
+}
+
+void Localization::SetCurrentLanguageCulture(const CultureInfo& value)
+{
+ if (Instance.CurrentCulture == value && Instance.CurrentLanguage == value)
+ return;
+
+ LOG(Info, "Changing current language and culture to: {0} ({1})", value.GetName(), value.GetLCID());
+ Instance.CurrentCulture = value;
+ Instance.CurrentLanguage = value;
+ Instance.OnLocalizationChanged();
+}
+
+String Localization::GetString(const String& id, const String& fallback)
+{
+ String result;
+ for (auto& e : Instance.LocalizedStringTables)
+ {
+ const auto table = e.Get();
+ const auto messages = table ? table->Entries.TryGet(id) : nullptr;
+ if (messages && messages->Count() != 0)
+ {
+ result = messages->At(0);
+ break;
+ }
+ }
+ if (result.IsEmpty())
+ result = fallback;
+ return result;
+}
+
+String Localization::GetPluralString(const String& id, int32 n, const String& fallback)
+{
+ CHECK_RETURN(n >= 1, fallback);
+ n--;
+ StringView result;
+ for (auto& e : Instance.LocalizedStringTables)
+ {
+ const auto table = e.Get();
+ const auto messages = table ? table->Entries.TryGet(id) : nullptr;
+ if (messages && messages->Count() > n)
+ {
+ result = messages->At(n);
+ break;
+ }
+ }
+ if (result.IsEmpty())
+ result = fallback;
+ return String::Format(result.GetText(), n);
+}
diff --git a/Source/Engine/Localization/Localization.h b/Source/Engine/Localization/Localization.h
new file mode 100644
index 000000000..6502c5523
--- /dev/null
+++ b/Source/Engine/Localization/Localization.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+#pragma once
+
+#include "CultureInfo.h"
+#include "Engine/Core/Types/BaseTypes.h"
+
+///
+/// The language and culture localization manager.
+///
+API_CLASS(Static) class FLAXENGINE_API Localization
+{
+DECLARE_SCRIPTING_TYPE_MINIMAL(Localization);
+public:
+ ///
+ /// Gets the current culture (date, time, currency and values formatting locale).
+ ///
+ API_PROPERTY() static const CultureInfo& GetCurrentCulture();
+
+ ///
+ /// Sets the current culture (date, time, currency and values formatting locale).
+ ///
+ API_PROPERTY() static void SetCurrentCulture(const CultureInfo& value);
+
+ ///
+ /// Gets the current language (text display locale).
+ ///
+ API_PROPERTY() static const CultureInfo& GetCurrentLanguage();
+
+ ///
+ /// Sets the current language (text display locale).
+ ///
+ API_PROPERTY() static void SetCurrentLanguage(const CultureInfo& value);
+
+ ///
+ /// Sets both the current language (text display locale) and the current culture (date, time, currency and values formatting locale) at once.
+ ///
+ API_FUNCTION() static void SetCurrentLanguageCulture(const CultureInfo& value);
+
+ ///
+ /// Occurs when current culture or language gets changed. Can be used to refresh UI to reflect language changes.
+ ///
+ API_EVENT() static Delegate<> LocalizationChanged;
+
+public:
+ ///
+ /// Gets the localized string for the current language by using string id lookup.
+ ///
+ /// The message identifier.
+ /// The optional fallback string value to use if localized string is missing.
+ /// The localized text.
+ API_FUNCTION() static String GetString(const String& id, const String& fallback = String::Empty);
+
+ ///
+ /// Gets the localized plural string for the current language by using string id lookup.
+ ///
+ /// The message identifier.
+ /// The value count for plural message selection.
+ /// The optional fallback string value to use if localized string is missing.
+ /// The localized text.
+ API_FUNCTION() static String GetPluralString(const String& id, int32 n, const String& fallback = String::Empty);
+};
diff --git a/Source/Engine/Localization/LocalizationSettings.h b/Source/Engine/Localization/LocalizationSettings.h
new file mode 100644
index 000000000..26ba06c96
--- /dev/null
+++ b/Source/Engine/Localization/LocalizationSettings.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+#pragma once
+
+#include "Engine/Core/Config/Settings.h"
+#include "Engine/Content/AssetReference.h"
+#include "LocalizedStringTable.h"
+
+///
+/// Game localization and internalization settings container.
+///
+API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API LocalizationSettings : public SettingsBase
+{
+DECLARE_SCRIPTING_TYPE_MINIMAL(LocalizationSettings);
+public:
+ ///
+ /// The list of the string localization tables used by the game.
+ ///
+ API_FIELD()
+ Array> LocalizedStringTables;
+
+public:
+ ///
+ /// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use.
+ ///
+ static LocalizationSettings* Get();
+
+ // [SettingsBase]
+ void Apply() override;
+ void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override;
+};
diff --git a/Source/Engine/Localization/LocalizedString.cs b/Source/Engine/Localization/LocalizedString.cs
new file mode 100644
index 000000000..2d6535336
--- /dev/null
+++ b/Source/Engine/Localization/LocalizedString.cs
@@ -0,0 +1,150 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+using System;
+using System.Globalization;
+
+namespace FlaxEngine
+{
+ partial class Localization
+ {
+ ///
+ /// Creates new culture.
+ ///
+ /// The name (eg. en, pl-PL).
+ /// The culture.
+ public static CultureInfo NewCulture(string name)
+ {
+ return new CultureInfo(name);
+ }
+ }
+
+ partial class LocalizedString : IEquatable, IEquatable, IComparable, IComparable, IComparable
+ {
+ ///
+ /// Empty string without localization.
+ ///
+ public static readonly LocalizedString Empty = new LocalizedString(null);
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The value.
+ public LocalizedString(string value)
+ {
+ Value = value;
+ }
+
+ ///
+ /// Gets the localized plural string for the current language by using string id lookup.
+ ///
+ /// The value count for plural message selection.
+ /// The localized text.
+ public string ToStringPlural(int n)
+ {
+ return string.IsNullOrEmpty(Value) ? Localization.GetPluralString(Id, n) : Value;
+ }
+
+ ///
+ /// Implicit converter of into .
+ ///
+ /// The localized string.
+ /// The string.
+ public static implicit operator string(LocalizedString str)
+ {
+ if ((object)str == null)
+ return null;
+ return string.IsNullOrEmpty(str.Value) ? Localization.GetString(str.Id) : str.Value;
+ }
+
+ ///
+ /// Implicit converter of into .
+ ///
+ /// The string.
+ /// The localized string.
+ public static implicit operator LocalizedString(string str)
+ {
+ if (str == null)
+ return null;
+ return new LocalizedString(str);
+ }
+
+ ///
+ /// Compares two localized strings.
+ ///
+ /// The lft string.
+ /// The right string.
+ /// True if both values are equal, otherwise false.
+ public static bool operator ==(LocalizedString left, LocalizedString right)
+ {
+ return left?.Equals(right) ?? (object)right == null;
+ }
+
+ ///
+ /// Compares two localized strings.
+ ///
+ /// The lft string.
+ /// The right string.
+ /// True if both values are not equal, otherwise false.
+ public static bool operator !=(LocalizedString left, LocalizedString right)
+ {
+ if ((object)left == null)
+ return (object)right != null;
+ return !left.Equals(right);
+ }
+
+ ///
+ public int CompareTo(object obj)
+ {
+ if (obj is string asString)
+ return CompareTo(asString);
+ if (obj is LocalizedString asLocalizedString)
+ return CompareTo(asLocalizedString);
+ return 0;
+ }
+
+ ///
+ public bool Equals(LocalizedString other)
+ {
+ return (object)other != null && Id == other.Id && Value == other.Value;
+ }
+
+ ///
+ public bool Equals(string other)
+ {
+ return Value == other || Localization.GetString(Id) == other;
+ }
+
+ ///
+ public int CompareTo(LocalizedString other)
+ {
+ return string.Compare(ToString(), ToString(), StringComparison.Ordinal);
+ }
+
+ ///
+ public int CompareTo(string other)
+ {
+ return string.Compare(ToString(), other, StringComparison.Ordinal);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ return (object)this == (object)obj || obj is LocalizedString other && Equals(other);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return ((Id != null ? Id.GetHashCode() : 0) * 397) ^ (Value != null ? Value.GetHashCode() : 0);
+ }
+ }
+
+ ///
+ public override string ToString()
+ {
+ return string.IsNullOrEmpty(Value) ? Localization.GetString(Id) : Value;
+ }
+ }
+}
diff --git a/Source/Engine/Localization/LocalizedString.h b/Source/Engine/Localization/LocalizedString.h
new file mode 100644
index 000000000..8137808b1
--- /dev/null
+++ b/Source/Engine/Localization/LocalizedString.h
@@ -0,0 +1,119 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+#pragma once
+
+#include "Engine/Core/Types/String.h"
+#include "Engine/Serialization/SerializationFwd.h"
+
+///
+/// The string container that supports using localized text.
+///
+API_CLASS(Sealed) class FLAXENGINE_API LocalizedString
+{
+DECLARE_SCRIPTING_TYPE_MINIMAL(LocalizedString);
+public:
+ ///
+ /// The localized string identifier. Used to lookup text value for a current language (via ).
+ ///
+ API_FIELD() String Id;
+
+ ///
+ /// The overriden string value to use. If empty, the localized string will be used.
+ ///
+ API_FIELD() String Value;
+
+public:
+ LocalizedString() = default;
+ LocalizedString(const LocalizedString& other);
+ LocalizedString(LocalizedString&& other) noexcept;
+ LocalizedString(const StringView& value);
+ LocalizedString(String&& value) noexcept;
+
+ LocalizedString& operator=(const LocalizedString& other);
+ LocalizedString& operator=(LocalizedString&& other) noexcept;
+ LocalizedString& operator=(const StringView& value);
+ LocalizedString& operator=(String&& value) noexcept;
+
+ friend bool operator==(const LocalizedString& a, const LocalizedString& b)
+ {
+ return a.Id == b.Id && a.Value == b.Value;
+ }
+
+ friend bool operator!=(const LocalizedString& a, const LocalizedString& b)
+ {
+ return !(a == b);
+ }
+
+ friend bool operator==(const LocalizedString& a, const StringView& b)
+ {
+ return a.Value == b || a.ToString() == b;
+ }
+
+ friend bool operator!=(const LocalizedString& a, const StringView& b)
+ {
+ return !(a == b);
+ }
+
+public:
+ String ToString() const;
+ String ToStringPlural(int32 n) const;
+};
+
+inline uint32 GetHash(const LocalizedString& key)
+{
+ return GetHash(key.ToString());
+}
+
+namespace Serialization
+{
+ inline bool ShouldSerialize(const LocalizedString& v, const void* otherObj)
+ {
+ return !otherObj || v != *(LocalizedString*)otherObj;
+ }
+
+ inline void Serialize(ISerializable::SerializeStream& stream, const LocalizedString& v, const void* otherObj)
+ {
+ if (v.Id.IsEmpty())
+ {
+ stream.String(v.Value);
+ }
+ else
+ {
+ stream.StartObject();
+ stream.JKEY("Id");
+ stream.String(v.Id);
+ if (v.Value.HasChars())
+ {
+ stream.JKEY("Value");
+ stream.String(v.Value);
+ }
+ stream.EndObject();
+ }
+ }
+
+ inline void Deserialize(ISerializable::DeserializeStream& stream, LocalizedString& v, ISerializeModifier* modifier)
+ {
+ if (stream.IsString())
+ {
+ v.Id = String::Empty;
+ v.Value = stream.GetText();
+ }
+ else if (stream.IsObject())
+ {
+ auto e = SERIALIZE_FIND_MEMBER(stream, "Id");
+ if (e != stream.MemberEnd())
+ v.Id.SetUTF8(e->value.GetString(), e->value.GetStringLength());
+ e = SERIALIZE_FIND_MEMBER(stream, "Value");
+ if (e != stream.MemberEnd())
+ v.Value.SetUTF8(e->value.GetString(), e->value.GetStringLength());
+ else if (v.Id.HasChars())
+ v.Value.Clear();
+ }
+ else
+ {
+ v = LocalizedString();
+ }
+ }
+}
+
+DEFINE_DEFAULT_FORMATTING_VIA_TO_STRING(LocalizedString);
diff --git a/Source/Engine/Localization/LocalizedStringTable.cpp b/Source/Engine/Localization/LocalizedStringTable.cpp
new file mode 100644
index 000000000..e9cb33a46
--- /dev/null
+++ b/Source/Engine/Localization/LocalizedStringTable.cpp
@@ -0,0 +1,138 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+#include "LocalizedStringTable.h"
+#include "Engine/Serialization/JsonTools.h"
+#include "Engine/Serialization/SerializationFwd.h"
+#include "Engine/Content/Factories/JsonAssetFactory.h"
+#if USE_EDITOR
+#include "Engine/ContentImporters/CreateJson.h"
+#include "Engine/Serialization/JsonWriters.h"
+#include "Engine/Threading/Threading.h"
+#include "Engine/Core/Log.h"
+#endif
+
+REGISTER_JSON_ASSET(LocalizedStringTable, "FlaxEngine.LocalizedStringTable", true);
+
+LocalizedStringTable::LocalizedStringTable(const SpawnParams& params, const AssetInfo* info)
+ : JsonAssetBase(params, info)
+{
+}
+
+void LocalizedStringTable::AddString(const StringView& id, const StringView& value)
+{
+ auto& values = Entries[id];
+ values.Resize(1);
+ values[0] = value;
+}
+
+void LocalizedStringTable::AddPluralString(const StringView& id, const StringView& value, int32 n)
+{
+ CHECK(n >= 0 && n < 1024);
+ auto& values = Entries[id];
+ values.Resize(Math::Max(values.Count(), n + 1));
+ values[n] = value;
+}
+
+#if USE_EDITOR
+
+bool LocalizedStringTable::Save(const StringView& path)
+{
+ // Validate state
+ if (WaitForLoaded())
+ {
+ LOG(Error, "Asset loading failed. Cannot save it.");
+ return true;
+ }
+ if (IsVirtual() && path.IsEmpty())
+ {
+ LOG(Error, "To save virtual asset asset you need to specify the target asset path location.");
+ return true;
+ }
+
+ ScopeLock lock(Locker);
+
+ // Serialize data
+ rapidjson_flax::StringBuffer outputData;
+ PrettyJsonWriter writerObj(outputData);
+ JsonWriter& writer = writerObj;
+ writer.StartObject();
+ {
+ writer.JKEY("Locale");
+ writer.String(Locale);
+
+ writer.JKEY("Entries");
+ writer.StartObject();
+ for (auto& e : Entries)
+ {
+ writer.Key(e.Key);
+ if (e.Value.Count() == 1)
+ {
+ writer.String(e.Value[0]);
+ }
+ else
+ {
+ writer.StartArray();
+ for (auto& q : e.Value)
+ writer.String(q);
+ writer.EndArray();
+ }
+ }
+ writer.EndObject();
+ }
+ writer.EndObject();
+
+ // Save asset
+ const bool saveResult = CreateJson::Create(path.HasChars() ? path : GetPath(), outputData, TypeName);
+ if (saveResult)
+ {
+ LOG(Error, "Cannot save \'{0}\'", ToString());
+ return true;
+ }
+
+ return false;
+}
+
+#endif
+
+Asset::LoadResult LocalizedStringTable::loadAsset()
+{
+ // Base
+ auto result = JsonAssetBase::loadAsset();
+ if (result != LoadResult::Ok || IsInternalType())
+ return result;
+
+ JsonTools::GetString(Locale, *Data, "Locale");
+ const auto entriesMember = SERIALIZE_FIND_MEMBER((*Data), "Entries");
+ if (entriesMember != Data->MemberEnd() && entriesMember->value.IsObject())
+ {
+ Entries.EnsureCapacity(entriesMember->value.MemberCount());
+ for (auto i = entriesMember->value.MemberBegin(); i != entriesMember->value.MemberEnd(); ++i)
+ {
+ const String key(i->name.GetText());
+ auto& e = Entries[key];
+ auto& value = i->value;
+ if (value.IsString())
+ {
+ e.Resize(1);
+ e[0] = value.GetText();
+ }
+ else if (value.IsArray())
+ {
+ e.Resize(value.Size());
+ for (int32 q = 0; q < e.Count(); q++)
+ e[q] = value[q].GetText();
+ }
+ }
+ }
+
+ return result;
+}
+
+void LocalizedStringTable::unload(bool isReloading)
+{
+ // Base
+ JsonAssetBase::unload(isReloading);
+
+ Locale.Clear();
+ Entries.Clear();
+}
diff --git a/Source/Engine/Localization/LocalizedStringTable.h b/Source/Engine/Localization/LocalizedStringTable.h
new file mode 100644
index 000000000..53e5bd6a4
--- /dev/null
+++ b/Source/Engine/Localization/LocalizedStringTable.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+#pragma once
+
+#include "Engine/Content/JsonAsset.h"
+#include "Engine/Core/Collections/Dictionary.h"
+
+///
+/// Contains localized strings table for a given culture.
+///
+///
+API_CLASS(NoSpawn) class FLAXENGINE_API LocalizedStringTable : public JsonAssetBase
+{
+DECLARE_ASSET_HEADER(LocalizedStringTable);
+public:
+ ///
+ /// The locale of the localized string table (eg. pl-PL).
+ ///
+ API_FIELD() String Locale;
+
+ ///
+ /// The string table. Maps the message id into the localized text. For plural messages the list contains separate items for value numbers.
+ ///
+ API_FIELD() Dictionary> Entries;
+
+public:
+ ///
+ /// Adds the localized string to the table.
+ ///
+ /// The message id. Used for lookups.
+ /// The localized text.
+ API_FUNCTION() void AddString(const StringView& id, const StringView& value);
+
+ ///
+ /// Adds the localized plural string to the table.
+ ///
+ /// The message id. Used for lookups.
+ /// The localized text.
+ /// The plural value (0, 1, 2..).
+ API_FUNCTION() void AddPluralString(const StringView& id, const StringView& value, int32 n);
+
+#if USE_EDITOR
+
+ ///
+ /// Saves this asset to the file. Supported only in Editor.
+ ///
+ /// The custom asset path to use for the saving. Use empty value to save this asset to its own storage location. Can be used to duplicate asset. Must be specified when saving virtual asset.
+ /// True if cannot save data, otherwise false.
+ API_FUNCTION() bool Save(const StringView& path = StringView::Empty);
+
+#endif
+
+protected:
+ // [JsonAssetBase]
+ LoadResult loadAsset() override;
+ void unload(bool isReloading) override;
+};
diff --git a/Source/Engine/Main/Main.Build.cs b/Source/Engine/Main/Main.Build.cs
index 6c8106760..669e5435b 100644
--- a/Source/Engine/Main/Main.Build.cs
+++ b/Source/Engine/Main/Main.Build.cs
@@ -64,6 +64,9 @@ public class Main : EngineModule
case TargetPlatform.Android:
options.SourcePaths.Add(Path.Combine(FolderPath, "Android"));
break;
+ case TargetPlatform.Switch:
+ options.SourcePaths.Add(Path.Combine(Globals.EngineRoot, "Source", "Platforms", "Switch", "Engine", "Main"));
+ break;
default: throw new InvalidPlatformException(options.Platform.Target);
}
}
diff --git a/Source/Engine/Navigation/NavMeshRuntime.cpp b/Source/Engine/Navigation/NavMeshRuntime.cpp
index 0060445c9..b35ade92d 100644
--- a/Source/Engine/Navigation/NavMeshRuntime.cpp
+++ b/Source/Engine/Navigation/NavMeshRuntime.cpp
@@ -16,9 +16,6 @@
#define USE_NAV_MESH_ALLOC 1
// TODO: try not using USE_NAV_MESH_ALLOC
-#define DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL 50.0f
-#define DEFAULT_NAV_QUERY_EXTENT_VERTICAL 250.0f
-
namespace
{
FORCE_INLINE void InitFilter(dtQueryFilter& filter)
@@ -58,7 +55,7 @@ bool NavMeshRuntime::FindDistanceToWall(const Vector3& startPosition, NavMeshHit
dtQueryFilter filter;
InitFilter(filter);
- Vector3 extent(DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL, DEFAULT_NAV_QUERY_EXTENT_VERTICAL, DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL);
+ Vector3 extent = Properties.DefaultQueryExtent;
Vector3 startPositionNavMesh;
Vector3::Transform(startPosition, Properties.Rotation, startPositionNavMesh);
@@ -96,7 +93,7 @@ bool NavMeshRuntime::FindPath(const Vector3& startPosition, const Vector3& endPo
dtQueryFilter filter;
InitFilter(filter);
- Vector3 extent(DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL, DEFAULT_NAV_QUERY_EXTENT_VERTICAL, DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL);
+ Vector3 extent = Properties.DefaultQueryExtent;
Vector3 startPositionNavMesh, endPositionNavMesh;
Vector3::Transform(startPosition, Properties.Rotation, startPositionNavMesh);
@@ -126,10 +123,9 @@ bool NavMeshRuntime::FindPath(const Vector3& startPosition, const Vector3& endPo
Quaternion invRotation;
Quaternion::Invert(Properties.Rotation, invRotation);
- // Check for special case, where path has not been found, and starting polygon was the one closest to the target
if (pathSize == 1 && dtStatusDetail(findPathStatus, DT_PARTIAL_RESULT))
{
- // In this case we find a point on starting polygon, that's closest to destination and store it as path end
+ // TODO: skip adding 2nd end point if it's not reachable (use navmesh raycast check? or physics check? or local Z distance check?)
resultPath.Resize(2);
resultPath[0] = startPosition;
resultPath[1] = startPositionNavMesh;
@@ -165,7 +161,7 @@ bool NavMeshRuntime::TestPath(const Vector3& startPosition, const Vector3& endPo
dtQueryFilter filter;
InitFilter(filter);
- Vector3 extent(DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL, DEFAULT_NAV_QUERY_EXTENT_VERTICAL, DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL);
+ Vector3 extent = Properties.DefaultQueryExtent;
Vector3 startPositionNavMesh, endPositionNavMesh;
Vector3::Transform(startPosition, Properties.Rotation, startPositionNavMesh);
@@ -212,7 +208,7 @@ bool NavMeshRuntime::ProjectPoint(const Vector3& point, Vector3& result) const
dtQueryFilter filter;
InitFilter(filter);
- Vector3 extent(DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL, DEFAULT_NAV_QUERY_EXTENT_VERTICAL, DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL);
+ Vector3 extent = Properties.DefaultQueryExtent;
Vector3 pointNavMesh;
Vector3::Transform(point, Properties.Rotation, pointNavMesh);
@@ -270,7 +266,7 @@ bool NavMeshRuntime::FindRandomPointAroundCircle(const Vector3& center, float ra
dtQueryFilter filter;
InitFilter(filter);
- Vector3 extent(DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL, DEFAULT_NAV_QUERY_EXTENT_VERTICAL, DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL);
+ Vector3 extent = Properties.DefaultQueryExtent;
Vector3 centerNavMesh;
Vector3::Transform(center, Properties.Rotation, centerNavMesh);
@@ -308,7 +304,7 @@ bool NavMeshRuntime::RayCast(const Vector3& startPosition, const Vector3& endPos
dtQueryFilter filter;
InitFilter(filter);
- Vector3 extent(DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL, DEFAULT_NAV_QUERY_EXTENT_VERTICAL, DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL);
+ Vector3 extent = Properties.DefaultQueryExtent;
Vector3 startPositionNavMesh, endPositionNavMesh;
Vector3::Transform(startPosition, Properties.Rotation, startPositionNavMesh);
diff --git a/Source/Engine/Navigation/Navigation.cpp b/Source/Engine/Navigation/Navigation.cpp
index db9c95089..d7fdcfc33 100644
--- a/Source/Engine/Navigation/Navigation.cpp
+++ b/Source/Engine/Navigation/Navigation.cpp
@@ -146,7 +146,7 @@ bool NavAreaProperties::operator==(const NavAreaProperties& other) const
bool NavMeshProperties::operator==(const NavMeshProperties& other) const
{
- return Name == other.Name && Quaternion::NearEqual(Rotation, other.Rotation, 0.001f) && Agent == other.Agent;
+ return Name == other.Name && Quaternion::NearEqual(Rotation, other.Rotation, 0.001f) && Agent == other.Agent && Vector3::NearEqual(DefaultQueryExtent, other.DefaultQueryExtent);
}
class NavigationService : public EngineService
diff --git a/Source/Engine/Navigation/NavigationSettings.cs b/Source/Engine/Navigation/NavigationSettings.cs
index 8a97e4adc..bfd2b5381 100644
--- a/Source/Engine/Navigation/NavigationSettings.cs
+++ b/Source/Engine/Navigation/NavigationSettings.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
using System;
+using System.Runtime.Serialization;
using FlaxEngine;
namespace FlaxEditor.Content.Settings
@@ -22,6 +23,7 @@ namespace FlaxEditor.Content.Settings
navMesh.Agent.Height = 144.0f;
navMesh.Agent.StepHeight = 35.0f;
navMesh.Agent.MaxSlopeAngle = 60.0f;
+ navMesh.DefaultQueryExtent = new Vector3(50.0f, 250.0f, 50.0f);
// Init nav areas
NavAreas = new NavAreaProperties[2];
@@ -51,6 +53,7 @@ namespace FlaxEditor.Content.Settings
navMesh.Agent.Height = 144.0f;
navMesh.Agent.StepHeight = 35.0f;
navMesh.Agent.MaxSlopeAngle = 60.0f;
+ navMesh.DefaultQueryExtent = new Vector3(50.0f, 250.0f, 50.0f);
}
// [Deprecated on 12.01.2021, expires on 12.01.2022]
@@ -105,6 +108,23 @@ namespace FlaxEditor.Content.Settings
namespace FlaxEngine
{
+ partial struct NavMeshProperties
+ {
+ [OnDeserialized]
+ internal void OnDeserialized(StreamingContext context)
+ {
+ // [Deprecated on 07.04.2021, expires on 07.04.2022]
+ if (DefaultQueryExtent.IsZero)
+ DefaultQueryExtent = new Vector3(50.0f, 250.0f, 50.0f);
+ }
+
+ ///
+ public override string ToString()
+ {
+ return Name;
+ }
+ }
+
partial struct NavAgentProperties
{
///
diff --git a/Source/Engine/Navigation/NavigationTypes.h b/Source/Engine/Navigation/NavigationTypes.h
index 11ebaeb1a..732ce4a0f 100644
--- a/Source/Engine/Navigation/NavigationTypes.h
+++ b/Source/Engine/Navigation/NavigationTypes.h
@@ -83,6 +83,12 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(NavMeshProperties);
API_FIELD(Attributes="EditorOrder(30)")
NavAgentProperties Agent;
+ ///
+ /// The default extents for the nav queries that defines the search distance along each axis (x, y, z). Smaller values prevent queries from snapping to too far locations.
+ ///
+ API_FIELD(Attributes="EditorOrder(40)")
+ Vector3 DefaultQueryExtent = Vector3(50.0f, 250.0f, 50.0f);
+
bool operator==(const NavMeshProperties& other) const;
bool operator!=(const NavMeshProperties& other) const
diff --git a/Source/Engine/Physics/Actors/RigidBody.cpp b/Source/Engine/Physics/Actors/RigidBody.cpp
index 12f4ed0d9..eecce480a 100644
--- a/Source/Engine/Physics/Actors/RigidBody.cpp
+++ b/Source/Engine/Physics/Actors/RigidBody.cpp
@@ -276,7 +276,8 @@ void RigidBody::UpdateMass()
float raiseMassToPower = 0.75f;
// TODO: link physical material or expose density parameter
- PxRigidBodyExt::updateMassAndInertia(*_actor, densityKGPerCubicUU);
+ PxVec3 centerOfMassOffset = C2P(_centerOfMassOffset);
+ PxRigidBodyExt::updateMassAndInertia(*_actor, densityKGPerCubicUU, ¢erOfMassOffset);
// Grab old mass so we can apply new mass while maintaining inertia tensor
const float oldMass = _actor->getMass();
@@ -382,6 +383,15 @@ void RigidBody::OnTriggerExit(PhysicsColliderActor* c)
TriggerExit(c);
}
+void RigidBody::OnColliderChanged(Collider* c)
+{
+ UpdateMass();
+
+ // TODO: maybe wake up only if one ore more shapes attached is active?
+ //if (GetStartAwake())
+ // WakeUp();
+}
+
void RigidBody::CreateActor()
{
ASSERT(_actor == nullptr);
@@ -393,7 +403,7 @@ void RigidBody::CreateActor()
// Setup flags
#if WITH_PVD
- PxActorFlags actorFlags = PxActorFlag::eVISUALIZATION;
+ PxActorFlags actorFlags = PxActorFlag::eVISUALIZATION;
#else
PxActorFlags actorFlags = static_cast(0);
#endif
diff --git a/Source/Engine/Physics/Actors/RigidBody.h b/Source/Engine/Physics/Actors/RigidBody.h
index 84ab304aa..19e22e506 100644
--- a/Source/Engine/Physics/Actors/RigidBody.h
+++ b/Source/Engine/Physics/Actors/RigidBody.h
@@ -14,7 +14,7 @@ class PhysicsColliderActor;
API_CLASS() class FLAXENGINE_API RigidBody : public PhysicsActor
{
DECLARE_SCENE_OBJECT(RigidBody);
-private:
+protected:
PxRigidDynamic* _actor;
Vector3 _cachedScale;
@@ -551,6 +551,9 @@ public:
void OnTriggerEnter(PhysicsColliderActor* c);
void OnTriggerExit(PhysicsColliderActor* c);
+ // Called when collider gets detached from this rigidbody or activated/deactivated. Used to update rigidbody mass.
+ virtual void OnColliderChanged(Collider* c);
+
protected:
///
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
new file mode 100644
index 000000000..558e4f98c
--- /dev/null
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp
@@ -0,0 +1,603 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+#include "WheeledVehicle.h"
+#include "Engine/Physics/Physics.h"
+#include "Engine/Physics/Utilities.h"
+#include "Engine/Level/Scene/Scene.h"
+#include "Engine/Serialization/Serialization.h"
+#if USE_EDITOR
+#include "Engine/Level/Scene/SceneRendering.h"
+#include "Engine/Debug/DebugDraw.h"
+#endif
+#if WITH_VEHICLE
+#include
+#include
+#include
+#include
+#include
+#include
+#endif
+
+#if WITH_VEHICLE
+extern void InitVehicleSDK();
+extern Array WheelVehicles;
+#endif
+
+namespace
+{
+ void FreeDrive(WheeledVehicle::DriveTypes driveType, PxVehicleWheels* drive)
+ {
+ switch (driveType)
+ {
+ case WheeledVehicle::DriveTypes::Drive4W:
+ ((PxVehicleDrive4W*)drive)->free();
+ break;
+ case WheeledVehicle::DriveTypes::DriveNW:
+ ((PxVehicleDriveNW*)drive)->free();
+ break;
+ case WheeledVehicle::DriveTypes::NoDrive:
+ ((PxVehicleNoDrive*)drive)->free();
+ break;
+ }
+ }
+}
+
+WheeledVehicle::WheeledVehicle(const SpawnParams& params)
+ : RigidBody(params)
+{
+ _useCCD = 1;
+}
+
+WheeledVehicle::DriveTypes WheeledVehicle::GetDriveType() const
+{
+ return _driveType;
+}
+
+void WheeledVehicle::SetDriveType(DriveTypes value)
+{
+ if (_driveType == value)
+ return;
+ _driveType = value;
+ Setup();
+}
+
+const Array& WheeledVehicle::GetWheels() const
+{
+ return _wheels;
+}
+
+void WheeledVehicle::SetWheels(const Array& value)
+{
+ _wheels = value;
+ Setup();
+}
+
+WheeledVehicle::EngineSettings WheeledVehicle::GetEngine() const
+{
+ return _engine;
+}
+
+void WheeledVehicle::SetEngine(const EngineSettings& value)
+{
+ _engine = value;
+}
+
+WheeledVehicle::DifferentialSettings WheeledVehicle::GetDifferential() const
+{
+ return _differential;
+}
+
+void WheeledVehicle::SetDifferential(const DifferentialSettings& value)
+{
+ _differential = value;
+}
+
+WheeledVehicle::GearboxSettings WheeledVehicle::GetGearbox() const
+{
+ return _gearbox;
+}
+
+void WheeledVehicle::SetGearbox(const GearboxSettings& value)
+{
+#if WITH_VEHICLE
+ auto& drive = (PxVehicleDrive*&)_drive;
+ if (drive)
+ {
+ drive->mDriveDynData.setUseAutoGears(value.AutoGear);
+ drive->mDriveDynData.setAutoBoxSwitchTime(Math::Max(value.SwitchTime, 0.0f));
+ }
+#endif
+ _gearbox = value;
+}
+
+void WheeledVehicle::SetThrottle(float value)
+{
+ _throttle = Math::Clamp(value, -1.0f, 1.0f);
+}
+
+void WheeledVehicle::SetSteering(float value)
+{
+ _steering = Math::Clamp(value, -1.0f, 1.0f);
+}
+
+void WheeledVehicle::SetBrake(float value)
+{
+ _brake = Math::Saturate(value);
+}
+
+void WheeledVehicle::SetHandbrake(float value)
+{
+ _handBrake = Math::Saturate(value);
+}
+
+void WheeledVehicle::ClearInput()
+{
+ _throttle = 0;
+ _steering = 0;
+ _brake = 0;
+ _handBrake = 0;
+}
+
+float WheeledVehicle::GetForwardSpeed() const
+{
+#if WITH_VEHICLE
+ auto& drive = (const PxVehicleWheels*&)_drive;
+ return drive ? drive->computeForwardSpeed() : 0.0f;
+#else
+ return 0.0f;
+#endif
+}
+
+float WheeledVehicle::GetSidewaysSpeed() const
+{
+#if WITH_VEHICLE
+ auto& drive = (const PxVehicleWheels*&)_drive;
+ return drive ? drive->computeSidewaysSpeed() : 0.0f;
+#else
+ return 0.0f;
+#endif
+}
+
+float WheeledVehicle::GetEngineRotationSpeed() const
+{
+#if WITH_VEHICLE
+ auto& drive = (const PxVehicleDrive*&)_drive;
+ return drive && _driveType != DriveTypes::NoDrive ? RadPerSToRpm(drive->mDriveDynData.getEngineRotationSpeed()) : 0.0f;
+#else
+ return 0.0f;
+#endif
+}
+
+int32 WheeledVehicle::GetCurrentGear() const
+{
+#if WITH_VEHICLE
+ auto& drive = (const PxVehicleDrive*&)_drive;
+ return drive && _driveType != DriveTypes::NoDrive ? (int32)drive->mDriveDynData.getCurrentGear() - 1 : 0;
+#else
+ return 0;
+#endif
+}
+
+void WheeledVehicle::SetCurrentGear(int32 value)
+{
+#if WITH_VEHICLE
+ auto& drive = (PxVehicleDrive*&)_drive;
+ if (drive && _driveType != DriveTypes::NoDrive)
+ {
+ drive->mDriveDynData.forceGearChange((PxU32)(value + 1));
+ }
+#endif
+}
+
+int32 WheeledVehicle::GetTargetGear() const
+{
+#if WITH_VEHICLE
+ auto& drive = (const PxVehicleDrive*&)_drive;
+ return drive && _driveType != DriveTypes::NoDrive ? (int32)drive->mDriveDynData.getTargetGear() - 1 : 0;
+#else
+ return 0;
+#endif
+}
+
+void WheeledVehicle::SetTargetGear(int32 value)
+{
+#if WITH_VEHICLE
+ auto& drive = (PxVehicleDrive*&)_drive;
+ if (drive && _driveType != DriveTypes::NoDrive)
+ {
+ drive->mDriveDynData.startGearChange((PxU32)(value + 1));
+ }
+#endif
+}
+
+void WheeledVehicle::GetWheelState(int32 index, WheelState& result)
+{
+ if (index >= 0 && index < _wheels.Count())
+ {
+ const auto collider = _wheels[index].Collider.Get();
+ for (auto& wheelData : _wheelsData)
+ {
+ if (wheelData.Collider == collider)
+ {
+ result = wheelData.State;
+ return;
+ }
+ }
+ }
+}
+
+void WheeledVehicle::Setup()
+{
+#if WITH_VEHICLE
+ if (!_actor || !IsDuringPlay())
+ return;
+ auto& drive = (PxVehicleWheels*&)_drive;
+
+ // Release previous
+ if (drive)
+ {
+ WheelVehicles.Remove(this);
+ FreeDrive(_driveTypeCurrent, drive);
+ drive = nullptr;
+ }
+
+ // Get wheels
+ Array> wheels;
+ _wheelsData.Clear();
+ for (auto& wheel : _wheels)
+ {
+ if (!wheel.Collider)
+ {
+ LOG(Warning, "Missing wheel collider in vehicle {0}", ToString());
+ continue;
+ }
+ if (wheel.Collider->GetParent() != this)
+ {
+ LOG(Warning, "Invalid wheel collider {1} in vehicle {0} attached to {2} (wheels needs to be added as children to vehicle)", ToString(), wheel.Collider->ToString(), wheel.Collider->GetParent() ? wheel.Collider->GetParent()->ToString() : String::Empty);
+ continue;
+ }
+ if (wheel.Collider->GetIsTrigger())
+ {
+ LOG(Warning, "Invalid wheel collider {1} in vehicle {0} cannot be a trigger", ToString(), wheel.Collider->ToString());
+ continue;
+ }
+ if (wheel.Collider->IsDuringPlay())
+ {
+ wheels.Add(&wheel);
+ }
+ }
+ if (wheels.IsEmpty())
+ {
+ // No wheel, no car
+ // No woman, no cry
+ return;
+ }
+ _wheelsData.Resize(wheels.Count());
+
+ InitVehicleSDK();
+
+ // Get linked shapes for the wheels mapping
+ Array> shapes;
+ shapes.Resize(_actor->getNbShapes());
+ _actor->getShapes(shapes.Get(), shapes.Count(), 0);
+ const PxTransform centerOfMassOffset = _actor->getCMassLocalPose();
+
+ // Initialize wheels simulation data
+ PxVec3 offsets[PX_MAX_NB_WHEELS];
+ for (int32 i = 0; i < wheels.Count(); i++)
+ {
+ Wheel& wheel = *wheels[i];
+ offsets[i] = C2P(wheel.Collider->GetLocalPosition());
+ }
+ PxF32 sprungMasses[PX_MAX_NB_WHEELS];
+ PxVehicleComputeSprungMasses(wheels.Count(), offsets, centerOfMassOffset.p, _actor->getMass(), 1, sprungMasses);
+ PxVehicleWheelsSimData* wheelsSimData = PxVehicleWheelsSimData::allocate(wheels.Count());
+ for (int32 i = 0; i < wheels.Count(); i++)
+ {
+ Wheel& wheel = *wheels[i];
+
+ auto& data = _wheelsData[i];
+ data.Collider = wheel.Collider;
+ data.LocalOrientation = wheel.Collider->GetLocalOrientation();
+
+ PxVehicleSuspensionData suspensionData;
+ const float suspensionFrequency = 7.0f;
+ const float suspensionDampingRatio = 1.0f;
+ suspensionData.mMaxCompression = 10.0f;
+ suspensionData.mMaxDroop = 10.0f;
+ suspensionData.mSprungMass = sprungMasses[i];
+ suspensionData.mSpringStrength = Math::Square(suspensionFrequency) * suspensionData.mSprungMass;
+ suspensionData.mSpringDamperRate = suspensionDampingRatio * 2.0f * Math::Sqrt(suspensionData.mSpringStrength * suspensionData.mSprungMass);
+
+ PxVehicleTireData tire;
+ tire.mType = 0;
+
+ PxVehicleWheelData wheelData;
+ wheelData.mMass = wheel.Mass;
+ wheelData.mRadius = wheel.Radius;
+ wheelData.mWidth = wheel.Width;
+ wheelData.mMOI = 0.5f * wheelData.mMass * Math::Square(wheelData.mRadius);
+ wheelData.mDampingRate = M2ToCm2(wheel.DampingRate);
+ wheelData.mMaxSteer = wheel.MaxSteerAngle * DegreesToRadians;
+ wheelData.mMaxBrakeTorque = M2ToCm2(wheel.MaxBrakeTorque);
+ wheelData.mMaxHandBrakeTorque = M2ToCm2(wheel.MaxHandBrakeTorque);
+
+ PxVec3 centreOffset = centerOfMassOffset.transformInv(offsets[i]);
+ float suspensionForceOffset = 0.0f;
+ PxVec3 forceAppPointOffset(centreOffset.x, centreOffset.y, centreOffset.z + suspensionForceOffset);
+
+ wheelsSimData->setTireData(i, tire);
+ wheelsSimData->setWheelData(i, wheelData);
+ wheelsSimData->setSuspensionData(i, suspensionData);
+ wheelsSimData->setSuspTravelDirection(i, PxVec3(0, -1, 0));
+ wheelsSimData->setWheelCentreOffset(i, centreOffset);
+ wheelsSimData->setSuspForceAppPointOffset(i, forceAppPointOffset);
+ wheelsSimData->setTireForceAppPointOffset(i, forceAppPointOffset);
+
+ PxShape* wheelShape = wheel.Collider->GetPxShape();
+ if (wheel.Collider->IsActiveInHierarchy())
+ {
+ wheelsSimData->setWheelShapeMapping(i, shapes.Find(wheelShape));
+
+ // Setup Vehicle ID inside word3 for suspension raycasts to ignore self
+ PxFilterData filter = wheelShape->getQueryFilterData();
+ filter.word3 = _id.D + 1;
+ wheelShape->setQueryFilterData(filter);
+ wheelShape->setSimulationFilterData(filter);
+ wheelsSimData->setSceneQueryFilterData(i, filter);
+ }
+ else
+ {
+ wheelsSimData->setWheelShapeMapping(i, -1);
+ wheelsSimData->disableWheel(i);
+ }
+ }
+ for (auto child : Children)
+ {
+ auto collider = Cast(child);
+ if (collider && collider->GetAttachedRigidBody() == this)
+ {
+ bool isWheel = false;
+ for (auto& w : wheels)
+ {
+ if (w->Collider == collider)
+ {
+ isWheel = true;
+ break;
+ }
+ }
+ if (!isWheel)
+ {
+ // Setup Vehicle ID inside word3 for suspension raycasts to ignore self
+ PxShape* shape = collider->GetPxShape();
+ PxFilterData filter = shape->getQueryFilterData();
+ filter.word3 = _id.D + 1;
+ shape->setQueryFilterData(filter);
+ shape->setSimulationFilterData(filter);
+ }
+ }
+ }
+
+ // Initialize vehicle drive
+ _driveTypeCurrent = _driveType;
+ switch (_driveType)
+ {
+ case DriveTypes::Drive4W:
+ {
+ PxVehicleDriveSimData4W driveSimData;
+
+ // Differential
+ PxVehicleDifferential4WData diff;
+ diff.mType = (PxVehicleDifferential4WData::Enum)_differential.Type;
+ diff.mFrontRearSplit = _differential.FrontRearSplit;
+ diff.mFrontLeftRightSplit = _differential.FrontLeftRightSplit;
+ diff.mRearLeftRightSplit = _differential.RearLeftRightSplit;
+ diff.mCentreBias = _differential.CentreBias;
+ diff.mFrontBias = _differential.FrontBias;
+ diff.mRearBias = _differential.RearBias;
+ driveSimData.setDiffData(diff);
+
+ // Engine
+ PxVehicleEngineData engine;
+ engine.mMOI = M2ToCm2(_engine.MOI);
+ engine.mPeakTorque = M2ToCm2(_engine.MaxTorque);
+ engine.mMaxOmega = RpmToRadPerS(_engine.MaxRotationSpeed);
+ engine.mDampingRateFullThrottle = M2ToCm2(0.15f);
+ engine.mDampingRateZeroThrottleClutchEngaged = M2ToCm2(2.0f);
+ engine.mDampingRateZeroThrottleClutchDisengaged = M2ToCm2(0.35f);
+ driveSimData.setEngineData(engine);
+
+ // Gears
+ PxVehicleGearsData gears;
+ gears.mSwitchTime = Math::Max(_gearbox.SwitchTime, 0.0f);
+ driveSimData.setGearsData(gears);
+
+ // Auto Box
+ PxVehicleAutoBoxData autoBox;
+ driveSimData.setAutoBoxData(autoBox);
+
+ // Clutch
+ PxVehicleClutchData clutch;
+ clutch.mStrength = M2ToCm2(_gearbox.ClutchStrength);
+ driveSimData.setClutchData(clutch);
+
+ // Ackermann steer accuracy
+ PxVehicleAckermannGeometryData ackermann;
+ ackermann.mAxleSeparation = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).x - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).x);
+ ackermann.mFrontWidth = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_RIGHT).z - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).z);
+ ackermann.mRearWidth = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_RIGHT).z - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).z);
+ driveSimData.setAckermannGeometryData(ackermann);
+
+ // Create vehicle drive
+ auto drive4W = PxVehicleDrive4W::allocate(wheels.Count());
+ drive4W->setup(CPhysX, _actor, *wheelsSimData, driveSimData, Math::Max(wheels.Count() - 4, 0));
+ drive4W->setToRestState();
+ drive4W->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
+ drive4W->mDriveDynData.setUseAutoGears(_gearbox.AutoGear);
+ drive = drive4W;
+ break;
+ }
+ case DriveTypes::DriveNW:
+ {
+ PxVehicleDriveSimDataNW driveSimData;
+
+ // Differential
+ PxVehicleDifferentialNWData diff;
+ for (int32 i = 0; i < wheels.Count(); i++)
+ diff.setDrivenWheel(i, true);
+ driveSimData.setDiffData(diff);
+
+ // Engine
+ PxVehicleEngineData engine;
+ engine.mMOI = M2ToCm2(_engine.MOI);
+ engine.mPeakTorque = M2ToCm2(_engine.MaxTorque);
+ engine.mMaxOmega = RpmToRadPerS(_engine.MaxRotationSpeed);
+ engine.mDampingRateFullThrottle = M2ToCm2(0.15f);
+ engine.mDampingRateZeroThrottleClutchEngaged = M2ToCm2(2.0f);
+ engine.mDampingRateZeroThrottleClutchDisengaged = M2ToCm2(0.35f);
+ driveSimData.setEngineData(engine);
+
+ // Gears
+ PxVehicleGearsData gears;
+ gears.mSwitchTime = Math::Max(_gearbox.SwitchTime, 0.0f);
+ driveSimData.setGearsData(gears);
+
+ // Auto Box
+ PxVehicleAutoBoxData autoBox;
+ driveSimData.setAutoBoxData(autoBox);
+
+ // Clutch
+ PxVehicleClutchData clutch;
+ clutch.mStrength = M2ToCm2(_gearbox.ClutchStrength);
+ driveSimData.setClutchData(clutch);
+
+ // Create vehicle drive
+ auto driveNW = PxVehicleDriveNW::allocate(wheels.Count());
+ driveNW->setup(CPhysX, _actor, *wheelsSimData, driveSimData, wheels.Count());
+ driveNW->setToRestState();
+ driveNW->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
+ driveNW->mDriveDynData.setUseAutoGears(_gearbox.AutoGear);
+ drive = driveNW;
+ break;
+ }
+ case DriveTypes::NoDrive:
+ {
+ // Create vehicle drive
+ auto driveNo = PxVehicleNoDrive::allocate(wheels.Count());
+ driveNo->setup(CPhysX, _actor, *wheelsSimData);
+ driveNo->setToRestState();
+ drive = driveNo;
+ break;
+ }
+ default:
+ CRASH;
+ }
+
+ WheelVehicles.Add(this);
+ wheelsSimData->free();
+ _actor->setSolverIterationCounts(12, 4);
+
+#else
+ LOG(Fatal, "PhysX Vehicle SDK is not supported.");
+#endif
+}
+
+#if USE_EDITOR
+
+void WheeledVehicle::DrawPhysicsDebug(RenderView& view)
+{
+ // Wheels shapes
+ for (auto& wheel : _wheels)
+ {
+ if (wheel.Collider && wheel.Collider->GetParent() == this && !wheel.Collider->GetIsTrigger())
+ {
+ DEBUG_DRAW_WIRE_CYLINDER(wheel.Collider->GetPosition(), wheel.Collider->GetOrientation(), wheel.Radius, wheel.Width, Color::Red * 0.8f, 0, true);
+ }
+ }
+}
+
+void WheeledVehicle::OnDebugDrawSelected()
+{
+ // Wheels shapes
+ for (auto& wheel : _wheels)
+ {
+ if (wheel.Collider && wheel.Collider->GetParent() == this && !wheel.Collider->GetIsTrigger())
+ {
+ DEBUG_DRAW_WIRE_CYLINDER(wheel.Collider->GetPosition(), wheel.Collider->GetOrientation(), wheel.Radius, wheel.Width, Color::Red * 0.4f, 0, false);
+ }
+ }
+
+ // Center of mass
+ DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(_transform.LocalToWorld(_centerOfMassOffset), 10.0f), Color::Blue, 0, false);
+
+ RigidBody::OnDebugDrawSelected();
+}
+
+#endif
+
+void WheeledVehicle::Serialize(SerializeStream& stream, const void* otherObj)
+{
+ RigidBody::Serialize(stream, otherObj);
+
+ SERIALIZE_GET_OTHER_OBJ(WheeledVehicle);
+
+ SERIALIZE_MEMBER(DriveType, _driveType);
+ SERIALIZE_MEMBER(Wheels, _wheels);
+ SERIALIZE(UseReverseAsBrake);
+ SERIALIZE_MEMBER(Engine, _engine);
+ SERIALIZE_MEMBER(Differential, _differential);
+ SERIALIZE_MEMBER(Gearbox, _gearbox);
+}
+
+void WheeledVehicle::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
+{
+ RigidBody::Deserialize(stream, modifier);
+
+ DESERIALIZE_MEMBER(DriveType, _driveType);
+ DESERIALIZE_MEMBER(Wheels, _wheels);
+ DESERIALIZE(UseReverseAsBrake);
+ DESERIALIZE_MEMBER(Engine, _engine);
+ DESERIALIZE_MEMBER(Differential, _differential);
+ DESERIALIZE_MEMBER(Gearbox, _gearbox);
+}
+
+void WheeledVehicle::OnColliderChanged(Collider* c)
+{
+ RigidBody::OnColliderChanged(c);
+
+ // Rebuild vehicle when someone adds/removed wheels
+ Setup();
+}
+
+void WheeledVehicle::BeginPlay(SceneBeginData* data)
+{
+ RigidBody::BeginPlay(data);
+
+#if WITH_VEHICLE
+ Setup();
+#endif
+
+#if USE_EDITOR
+ GetSceneRendering()->AddPhysicsDebug(this);
+#endif
+}
+
+void WheeledVehicle::EndPlay()
+{
+#if USE_EDITOR
+ GetSceneRendering()->RemovePhysicsDebug(this);
+#endif
+
+#if WITH_VEHICLE
+ auto& drive = (PxVehicleWheels*&)_drive;
+ if (drive)
+ {
+ // Parkway Drive
+ WheelVehicles.Remove(this);
+ FreeDrive(_driveTypeCurrent, drive);
+ drive = nullptr;
+ }
+#endif
+
+ RigidBody::EndPlay();
+}
diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h
new file mode 100644
index 000000000..bb947d68d
--- /dev/null
+++ b/Source/Engine/Physics/Actors/WheeledVehicle.h
@@ -0,0 +1,428 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+#pragma once
+
+#include "Engine/Physics/Actors/RigidBody.h"
+#include "Engine/Physics/Colliders/Collider.h"
+#include "Engine/Scripting/ScriptingObjectReference.h"
+
+class Physics;
+
+///
+/// Representation of the car vehicle that uses wheels. Built on top of the RigidBody with collider representing its chassis shape and wheels.
+///
+///
+API_CLASS() class FLAXENGINE_API WheeledVehicle : public RigidBody
+{
+ friend Physics;
+DECLARE_SCENE_OBJECT(WheeledVehicle);
+public:
+
+ ///
+ /// Vehicle driving mode types.
+ ///
+ API_ENUM() enum class DriveTypes
+ {
+ // Four-wheel drive. Any additional wheels are non-drivable. Optimized for 4-wheel cars.
+ Drive4W,
+ // N-wheel drive. Up to 20 drivable wheels. Suits generic wheels configurations.
+ DriveNW,
+ // Non-drivable vehicle.
+ NoDrive,
+ };
+
+ ///
+ /// Vehicle engine settings.
+ ///
+ API_STRUCT() struct EngineSettings : ISerializable
+ {
+ DECLARE_SCRIPTING_TYPE_MINIMAL(EngineSettings);
+ API_AUTO_SERIALIZATION();
+
+ ///
+ /// Moment of inertia of the engine around the axis of rotation. Specified in kilograms metres-squared (kg m^2).
+ ///
+ API_FIELD() float MOI = 1.0f;
+
+ ///
+ /// Maximum torque available to apply to the engine when the accelerator pedal is at maximum. Specified in kilograms metres-squared per second-squared (kg m^2 s^-2).
+ ///
+ API_FIELD() float MaxTorque = 500.0f;
+
+ ///
+ /// Maximum rotation speed of the engine (Revolutions Per Minute is the number of turns in one minute).
+ ///
+ API_FIELD() float MaxRotationSpeed = 6000.0f;
+ };
+
+ ///
+ /// Vehicle differential types.
+ ///
+ API_ENUM() enum class DifferentialTypes
+ {
+ // Limited slip differential for car with 4 driven wheels.
+ LimitedSlip4W,
+ // Limited slip differential for car with front-wheel drive.
+ LimitedSlipFrontDrive,
+ // Limited slip differential for car with rear-wheel drive.
+ LimitedSlipRearDrive,
+ // Open differential for car with 4 driven wheels.
+ Open4W,
+ // Open differential for car with front-wheel drive.
+ OpenFrontDrive,
+ // Open differential for car with rear-wheel drive.
+ OpenRearDrive,
+ };
+
+ ///
+ /// Vehicle differential settings.
+ ///
+ API_STRUCT() struct DifferentialSettings : ISerializable
+ {
+ DECLARE_SCRIPTING_TYPE_MINIMAL(DifferentialSettings);
+ API_AUTO_SERIALIZATION();
+
+ ///
+ /// Type of differential.
+ ///
+ API_FIELD() DifferentialTypes Type = DifferentialTypes::LimitedSlip4W;
+
+ ///
+ /// Ratio of torque split between front and rear (higher then 0.5 means more to front, smaller than 0.5 means more to rear). Only applied to LimitedSlip4W and Open4W.
+ ///
+ API_FIELD(Attributes="Limit(0, 1)") float FrontRearSplit = 0.45f;
+
+ ///
+ /// Ratio of torque split between front-left and front-right (higher then 0.5 means more to front-left, smaller than 0.5 means more to front-right). Only applied to LimitedSlip4W and Open4W and LimitedSlipFrontDrive.
+ ///
+ API_FIELD(Attributes="Limit(0, 1)") float FrontLeftRightSplit = 0.5f;
+
+ ///
+ /// Ratio of torque split between rear-left and rear-right (higher then 0.5 means more to rear-left, smaller than 0.5 means more to rear-right). Only applied to LimitedSlip4W and Open4W and LimitedSlipRearDrive.
+ ///
+ API_FIELD(Attributes="Limit(0, 1)") float RearLeftRightSplit = 0.5f;
+
+ ///
+ /// Maximum allowed ratio of average front wheel rotation speed and rear wheel rotation speeds. The differential will divert more torque to the slower wheels when the bias is exceeded. Only applied to LimitedSlip4W.
+ ///
+ API_FIELD(Attributes="Limit(1)") float CentreBias = 1.3f;
+
+ ///
+ /// Maximum allowed ratio of front-left and front-right wheel rotation speeds. The differential will divert more torque to the slower wheel when the bias is exceeded. Only applied to LimitedSlip4W and LimitedSlipFrontDrive.
+ ///
+ API_FIELD(Attributes="Limit(1)") float FrontBias = 1.3f;
+
+ ///
+ /// Maximum allowed ratio of rear-left and rear-right wheel rotation speeds. The differential will divert more torque to the slower wheel when the bias is exceeded. Only applied to LimitedSlip4W and LimitedSlipRearDrive.
+ ///
+ API_FIELD(Attributes="Limit(1)") float RearBias = 1.3f;
+ };
+
+ ///
+ /// Vehicle gearbox settings.
+ ///
+ API_STRUCT() struct GearboxSettings : ISerializable
+ {
+ DECLARE_SCRIPTING_TYPE_MINIMAL(GearboxSettings);
+ API_AUTO_SERIALIZATION();
+
+ ///
+ /// If enabled the vehicle gears will be changes automatically, otherwise it's fully manual.
+ ///
+ API_FIELD() bool AutoGear = true;
+
+ ///
+ /// Time it takes to switch gear. Specified in seconds (s).
+ ///
+ API_FIELD(Attributes="Limit(0)") float SwitchTime = 0.5f;
+
+ ///
+ /// Strength of clutch. A stronger clutch more strongly couples the engine to the wheels, while a clutch of strength zero completely decouples the engine from the wheels.
+ /// Stronger clutches more quickly bring the wheels and engine into equilibrium, while weaker clutches take longer, resulting in periods of clutch slip and delays in power transmission from the engine to the wheels.
+ /// Specified in kilograms metres-squared per second (kg m^2 s^-1).
+ ///
+ API_FIELD(Attributes="Limit(0)") float ClutchStrength = 10.0f;
+ };
+
+ ///
+ /// Vehicle wheel types.
+ ///
+ API_ENUM() enum class WheelTypes
+ {
+ // Left wheel of the front axle.
+ FrontLeft,
+ // Right wheel of the front axle.
+ FrontRight,
+ // Left wheel of the rear axle.
+ RearLeft,
+ // Right wheel of the rear axle.
+ ReadRight,
+ // Non-drivable wheel.
+ NoDrive,
+ };
+
+ ///
+ /// Vehicle wheel settings.
+ ///
+ API_STRUCT() struct Wheel : ISerializable
+ {
+ DECLARE_SCRIPTING_TYPE_MINIMAL(Wheel);
+ API_AUTO_SERIALIZATION();
+
+ ///
+ /// Wheel placement type.
+ ///
+ API_FIELD() WheelTypes Type = WheelTypes::FrontLeft;
+
+ ///
+ /// Combined mass of the wheel and the tire in kg. Typically, a wheel has mass between 20Kg and 80Kg but can be lower and higher depending on the vehicle.
+ ///
+ API_FIELD() float Mass = 20.0f;
+
+ ///
+ /// Distance in metres between the center of the wheel and the outside rim of the tire. It is important that the value of the radius closely matches the radius of the render mesh of the wheel. Any mismatch will result in the wheels either hovering above the ground or intersecting the ground.
+ ///
+ API_FIELD() float Radius = 50.0f;
+
+ ///
+ /// Full width of the wheel in metres. This parameter has no bearing on the handling but is a very useful parameter to have when trying to render debug data relating to the wheel/tire/suspension.
+ ///
+ API_FIELD() float Width = 20.0f;
+
+ ///
+ /// Max steer angle that can be achieved by the wheel (in degrees).
+ ///
+ API_FIELD(Attributes="Limit(0)") float MaxSteerAngle = 0.0f;
+
+ ///
+ /// Damping rate applied to wheel. Specified in kilograms metres-squared per second (kg m^2 s^-1).
+ ///
+ API_FIELD(Attributes="Limit(0)") float DampingRate = 0.25f;
+
+ ///
+ /// Max brake torque that can be applied to wheel. Specified in kilograms metres-squared per second-squared (kg m^2 s^-2)
+ ///
+ API_FIELD(Attributes="Limit(0)") float MaxBrakeTorque = 1500.0f;
+
+ ///
+ /// Max handbrake torque that can be applied to wheel. Specified in kilograms metres-squared per second-squared (kg m^2 s^-2)
+ ///
+ API_FIELD(Attributes="Limit(0)") float MaxHandBrakeTorque = 2000.0f;
+
+ ///
+ /// Collider that represents the wheel shape and it's placement. Has to be attached as a child to the vehicle. Triangle mesh collider is not supported (use convex mesh or basic shapes).
+ ///
+ API_FIELD() ScriptingObjectReference Collider;
+ };
+
+ ///
+ /// Vehicle wheel dynamic simulation state container.
+ ///
+ API_STRUCT() struct WheelState
+ {
+ DECLARE_SCRIPTING_TYPE_MINIMAL(WheelState);
+
+ ///
+ /// True if suspension travel limits forbid the wheel from touching the drivable surface.
+ ///
+ API_FIELD() bool IsInAir = false;
+
+ ///
+ /// The wheel is not in the air then it's set to the collider of the driving surface under the corresponding vehicle wheel.
+ ///
+ API_FIELD() PhysicsColliderActor* TireContactCollider = nullptr;
+
+ ///
+ /// The wheel is not in the air then it's set to the point on the drivable surface hit by the tire.
+ ///
+ API_FIELD() Vector3 TireContactPoint = Vector3::Zero;
+
+ ///
+ /// The wheel is not in the air then it's set to the normal on the drivable surface hit by the tire.
+ ///
+ API_FIELD() Vector3 TireContactNormal = Vector3::Zero;
+
+ ///
+ /// The friction experienced by the tire for the combination of tire type and surface type after accounting.
+ ///
+ API_FIELD() float TireFriction = 0.0f;
+ };
+
+private:
+
+ struct WheelData
+ {
+ Collider* Collider;
+ Quaternion LocalOrientation;
+ WheelState State;
+ };
+
+ void* _drive = nullptr;
+ DriveTypes _driveType = DriveTypes::Drive4W, _driveTypeCurrent;
+ Array> _wheelsData;
+ float _throttle = 0.0f, _steering = 0.0f, _brake = 0.0f, _handBrake = 0.0f;
+ Array _wheels;
+ EngineSettings _engine;
+ DifferentialSettings _differential;
+ GearboxSettings _gearbox;
+
+public:
+
+ ///
+ /// If checked, the negative throttle value will be used as brake and reverse to behave in a more arcade style where holding reverse also functions as brake. Disable it for more realistic driving controls.
+ ///
+ API_FIELD(Attributes="EditorOrder(0), EditorDisplay(\"Vehicle\")")
+ bool UseReverseAsBrake = true;
+
+ ///
+ /// Gets the vehicle driving model type.
+ ///
+ API_PROPERTY(Attributes="EditorOrder(1), EditorDisplay(\"Vehicle\")") DriveTypes GetDriveType() const;
+
+ ///
+ /// Sets the vehicle driving model type.
+ ///
+ API_PROPERTY() void SetDriveType(DriveTypes value);
+
+ ///
+ /// Gets the vehicle wheels settings.
+ ///
+ API_PROPERTY(Attributes="EditorOrder(2), EditorDisplay(\"Vehicle\")") const Array& GetWheels() const;
+
+ ///
+ /// Sets the vehicle wheels settings.
+ ///
+ API_PROPERTY() void SetWheels(const Array& value);
+
+ ///
+ /// Gets the vehicle engine settings.
+ ///
+ API_PROPERTY(Attributes="EditorOrder(3), EditorDisplay(\"Vehicle\")") EngineSettings GetEngine() const;
+
+ ///
+ /// Sets the vehicle engine settings.
+ ///
+ API_PROPERTY() void SetEngine(const EngineSettings& value);
+
+ ///
+ /// Gets the vehicle differential settings.
+ ///
+ API_PROPERTY(Attributes="EditorOrder(4), EditorDisplay(\"Vehicle\")") DifferentialSettings GetDifferential() const;
+
+ ///
+ /// Sets the vehicle differential settings.
+ ///
+ API_PROPERTY() void SetDifferential(const DifferentialSettings& value);
+
+ ///
+ /// Gets the vehicle gearbox settings.
+ ///
+ API_PROPERTY(Attributes="EditorOrder(5), EditorDisplay(\"Vehicle\")") GearboxSettings GetGearbox() const;
+
+ ///
+ /// Sets the vehicle gearbox settings.
+ ///
+ API_PROPERTY() void SetGearbox(const GearboxSettings& value);
+
+public:
+
+ ///
+ /// Sets the input for vehicle throttle. It is the analog accelerator pedal value in range (0,1) where 1 represents the pedal fully pressed and 0 represents the pedal in its rest state.
+ ///
+ /// The value (-1,1 range). When using UseReverseAsBrake it can be negative and will be used as brake and backward driving.
+ API_FUNCTION() void SetThrottle(float value);
+
+ ///
+ /// Sets the input for vehicle steering. Steer is the analog steer value in range (-1,1) where -1 represents the steering wheel at left lock and +1 represents the steering wheel at right lock.
+ ///
+ /// The value (-1,1 range).
+ API_FUNCTION() void SetSteering(float value);
+
+ ///
+ /// Sets the input for vehicle brakes. Brake is the analog brake pedal value in range (0,1) where 1 represents the pedal fully pressed and 0 represents the pedal in its rest state.
+ ///
+ /// The value (0,1 range).
+ API_FUNCTION() void SetBrake(float value);
+
+ ///
+ /// Sets the input for vehicle handbrake. Handbrake is the analog handbrake value in range (0,1) where 1 represents the handbrake fully engaged and 0 represents the handbrake in its rest state.
+ ///
+ /// The value (0,1 range).
+ API_FUNCTION() void SetHandbrake(float value);
+
+ ///
+ /// Clears all the vehicle control inputs to the default values (throttle, steering, breaks).
+ ///
+ API_FUNCTION() void ClearInput();
+
+public:
+
+ ///
+ /// Gets the current forward vehicle movement speed (along forward vector of the actor transform).
+ ///
+ API_PROPERTY() float GetForwardSpeed() const;
+
+ ///
+ /// Gets the current sideways vehicle movement speed (along right vector of the actor transform).
+ ///
+ API_PROPERTY() float GetSidewaysSpeed() const;
+
+ ///
+ /// Gets the current engine rotation speed (Revolutions Per Minute is the number of turns in one minute).
+ ///
+ API_PROPERTY() float GetEngineRotationSpeed() const;
+
+ ///
+ /// Gets the current gear number. Neutral gears is 0, reverse gears is -1, forward gears are 1 and higher.
+ ///
+ API_PROPERTY(Attributes="HideInEditor") int32 GetCurrentGear() const;
+
+ ///
+ /// Sets the current gear number. The gear change is instant. Neutral gears is 0, reverse gears is -1, forward gears are 1 and higher.
+ ///
+ API_PROPERTY() void SetCurrentGear(int32 value);
+
+ ///
+ /// Gets the target gear number. Neutral gears is 0, reverse gears is -1, forward gears are 1 and higher.
+ ///
+ API_PROPERTY(Attributes="HideInEditor") int32 GetTargetGear() const;
+
+ ///
+ /// Sets the target gear number. Gearbox will change the current gear to the target. Neutral gears is 0, reverse gears is -1, forward gears are 1 and higher.
+ ///
+ API_PROPERTY() void SetTargetGear(int32 value);
+
+ ///
+ /// Gets the current state of the wheel.
+ ///
+ /// The index of the wheel.
+ /// The current state.
+ API_FUNCTION() void GetWheelState(int32 index, API_PARAM(Out) WheelState& result);
+
+ ///
+ /// Rebuilds the vehicle. Call it after modifying vehicle settings (eg. engine options).
+ ///
+ API_FUNCTION() void Setup();
+
+private:
+
+#if USE_EDITOR
+ void DrawPhysicsDebug(RenderView& view);
+#endif
+
+public:
+
+ // [Vehicle]
+#if USE_EDITOR
+ void OnDebugDrawSelected() override;
+#endif
+ void Serialize(SerializeStream& stream, const void* otherObj) override;
+ void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
+ void OnColliderChanged(Collider* c) override;
+
+protected:
+
+ // [Vehicle]
+ void BeginPlay(SceneBeginData* data) override;
+ void EndPlay() override;
+};
diff --git a/Source/Engine/Physics/Colliders/Collider.cpp b/Source/Engine/Physics/Colliders/Collider.cpp
index a1a84a523..acf6af5d1 100644
--- a/Source/Engine/Physics/Colliders/Collider.cpp
+++ b/Source/Engine/Physics/Colliders/Collider.cpp
@@ -170,19 +170,7 @@ bool Collider::ComputePenetration(const Collider* colliderA, const Collider* col
const PxTransform poseA(C2P(colliderA->GetPosition()), C2P(colliderA->GetOrientation()));
const PxTransform poseB(C2P(colliderB->GetPosition()), C2P(colliderB->GetOrientation()));
- return PxGeometryQuery::computePenetration(
- C2P(direction),
- distance,
- shapeA->getGeometry().any(),
- poseA,
- shapeB->getGeometry().any(),
- poseB
- );
-}
-
-bool Collider::IsAttached() const
-{
- return _shape && _shape->getActor() != nullptr;
+ return PxGeometryQuery::computePenetration(C2P(direction), distance, shapeA->getGeometry().any(), poseA, shapeB->getGeometry().any(), poseB);
}
bool Collider::CanAttach(RigidBody* rigidBody) const
@@ -350,6 +338,9 @@ void Collider::CreateStaticActor()
_staticActor = CPhysX->createRigidStatic(trans);
ASSERT(_staticActor);
_staticActor->userData = this;
+#if WITH_PVD
+ _staticActor->setActorFlag(PxActorFlag::eVISUALIZATION, true);
+#endif
// Reset local pos of the shape and link it to the actor
_shape->setLocalPose(PxTransform(C2P(_center)));
@@ -439,15 +430,18 @@ void Collider::BeginPlay(SceneBeginData* data)
void Collider::EndPlay()
{
+ // Base
+ PhysicsColliderActor::EndPlay();
+
if (_shape)
{
// Detach from the actor
auto actor = _shape->getActor();
if (actor)
actor->detachShape(*_shape);
-
- // Check if was using a static actor and cleanup it
- if (_staticActor)
+ if (actor && actor->is())
+ static_cast(actor->userData)->OnColliderChanged(this);
+ else if (_staticActor)
{
RemoveStaticActor();
}
@@ -457,9 +451,6 @@ void Collider::EndPlay()
_shape->release();
_shape = nullptr;
}
-
- // Base
- PhysicsColliderActor::EndPlay();
}
void Collider::OnActiveInTreeChanged()
@@ -476,11 +467,7 @@ void Collider::OnActiveInTreeChanged()
auto rigidBody = GetAttachedRigidBody();
if (rigidBody)
{
- rigidBody->UpdateMass();
-
- // TODO: maybe wake up only if one ore more shapes attached is active?
- //if (rigidBody->GetStartAwake())
- // rigidBody->WakeUp();
+ rigidBody->OnColliderChanged(this);
}
}
}
@@ -497,6 +484,8 @@ void Collider::OnParentChanged()
auto actor = _shape->getActor();
if (actor)
actor->detachShape(*_shape);
+ if (actor && actor->is())
+ static_cast(actor->userData)->OnColliderChanged(this);
// Check if the new parent is a rigidbody
const auto rigidBody = dynamic_cast(GetParent());
diff --git a/Source/Engine/Physics/Colliders/Collider.h b/Source/Engine/Physics/Colliders/Collider.h
index 3e7b5ecfd..ca88ea66c 100644
--- a/Source/Engine/Physics/Colliders/Collider.h
+++ b/Source/Engine/Physics/Colliders/Collider.h
@@ -149,12 +149,6 @@ public:
public:
- ///
- /// Determines whether this collider is attached to the body.
- ///
- /// true if this instance is attached; otherwise, false.
- API_PROPERTY() bool IsAttached() const;
-
///
/// Determines whether this collider can be attached the specified rigid body.
///
diff --git a/Source/Engine/Physics/Colliders/MeshCollider.cpp b/Source/Engine/Physics/Colliders/MeshCollider.cpp
index 7ba76f963..85536bc7f 100644
--- a/Source/Engine/Physics/Colliders/MeshCollider.cpp
+++ b/Source/Engine/Physics/Colliders/MeshCollider.cpp
@@ -5,6 +5,9 @@
#include "Engine/Serialization/Serialization.h"
#include "Engine/Physics/Utilities.h"
#include "Engine/Physics/Physics.h"
+#if USE_EDITOR
+#include "Engine/Debug/DebugLog.h"
+#endif
MeshCollider::MeshCollider(const SpawnParams& params)
: Collider(params)
@@ -39,6 +42,12 @@ bool MeshCollider::CanAttach(RigidBody* rigidBody) const
CollisionDataType type = CollisionDataType::None;
if (CollisionData && CollisionData->IsLoaded())
type = CollisionData->GetOptions().Type;
+#if USE_EDITOR
+ if (type == CollisionDataType::TriangleMesh)
+ {
+ LOG(Warning, "Cannot attach {0} using Triangle Mesh collider {1} to RigidBody (not supported)", GetNamePath(), CollisionData->ToString());
+ }
+#endif
return type != CollisionDataType::TriangleMesh;
}
diff --git a/Source/Engine/Physics/CollisionCooking.cpp b/Source/Engine/Physics/CollisionCooking.cpp
index 9076d979e..5af787c5e 100644
--- a/Source/Engine/Physics/CollisionCooking.cpp
+++ b/Source/Engine/Physics/CollisionCooking.cpp
@@ -5,6 +5,7 @@
#include "CollisionCooking.h"
#include "Engine/Threading/Task.h"
#include "Engine/Graphics/Async/GPUTask.h"
+#include "Engine/Graphics/Models/MeshBase.h"
#include "Engine/Core/Log.h"
#include "Physics.h"
#include
@@ -117,15 +118,14 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
for (int32 i = 0; i < meshesCount; i++)
{
const auto mesh = lod->Meshes[i];
+ if ((arg.MaterialSlotsMask & (1 << mesh->MaterialSlotIndex)) == 0)
+ continue;
vCount += mesh->Positions.Count();
-
if (needIndexBuffer)
- {
iCount += mesh->Indices.Count() * 3;
- }
}
- if (meshesCount == 1)
+ if (meshesCount == 1 && vCount != 0)
{
// Link a single mesh
const auto mesh = lod->Meshes[0];
@@ -144,6 +144,8 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
for (int32 i = 0; i < meshesCount; i++)
{
const auto mesh = lod->Meshes[i];
+ if ((arg.MaterialSlotsMask & (1 << mesh->MaterialSlotIndex)) == 0)
+ continue;
const int32 firstVertexIndex = vertexCounter;
const int32 vertexCount = mesh->Positions.Count();
@@ -186,14 +188,15 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
}
// Pick a proper model LOD
- const int32 lodIndex = Math::Clamp(arg.ModelLodIndex, 0, arg.Model->LODs.Count());
- auto lod = &arg.Model->LODs[lodIndex];
+ const int32 lodIndex = Math::Clamp(arg.ModelLodIndex, 0, arg.Model->GetLODsCount());
+ Array meshes;
+ arg.Model->GetMeshes(meshes, lodIndex);
// Download model LOD data from the GPU.
// It's easier than reading internal, versioned mesh storage format.
// Also it works with virtual assets that have no dedicated storage.
// Note: request all meshes data at once and wait for the tasks to be done.
- const int32 meshesCount = lod->Meshes.Count();
+ const int32 meshesCount = meshes.Count();
Array vertexBuffers;
Array indexBuffers;
vertexBuffers.Resize(meshesCount);
@@ -205,9 +208,11 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
Array tasks(meshesCount + meshesCount);
for (int32 i = 0; i < meshesCount; i++)
{
- const auto& mesh = lod->Meshes[i];
+ const auto& mesh = *meshes[i];
+ if ((arg.MaterialSlotsMask & (1 << mesh.GetMaterialSlotIndex())) == 0)
+ continue;
- auto task = mesh.ExtractDataAsync(MeshBufferType::Vertex0, vertexBuffers[i]);
+ auto task = mesh.DownloadDataGPUAsync(MeshBufferType::Vertex0, vertexBuffers[i]);
if (task == nullptr)
return true;
task->Start();
@@ -216,7 +221,7 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
if (needIndexBuffer)
{
- task = mesh.ExtractDataAsync(MeshBufferType::Index, indexBuffers[i]);
+ task = mesh.DownloadDataGPUAsync(MeshBufferType::Index, indexBuffers[i]);
if (task == nullptr)
return true;
task->Start();
@@ -236,7 +241,9 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
int32 vertexCounter = 0, indexCounter = 0;
for (int32 i = 0; i < meshesCount; i++)
{
- const auto& mesh = lod->Meshes[i];
+ const auto& mesh = *meshes[i];
+ if ((arg.MaterialSlotsMask & (1 << mesh.GetMaterialSlotIndex())) == 0)
+ continue;
const auto& vData = vertexBuffers[i];
const int32 firstVertexIndex = vertexCounter;
@@ -251,7 +258,7 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
if (mesh.Use16BitIndexBuffer())
{
auto dst = finalIndexData.Get() + indexCounter;
- auto src = (uint16*)iData.Get();
+ auto src = iData.Get();
for (int32 j = 0; j < indexCount; j++)
{
*dst++ = firstVertexIndex + *src++;
@@ -261,7 +268,7 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
else
{
auto dst = finalIndexData.Get() + indexCounter;
- auto src = (uint32*)iData.Get();
+ auto src = iData.Get();
for (int32 j = 0; j < indexCount; j++)
{
*dst++ = firstVertexIndex + *src++;
diff --git a/Source/Engine/Physics/CollisionCooking.h b/Source/Engine/Physics/CollisionCooking.h
index 658f88428..992038224 100644
--- a/Source/Engine/Physics/CollisionCooking.h
+++ b/Source/Engine/Physics/CollisionCooking.h
@@ -7,7 +7,7 @@
#include "Engine/Core/Types/DataContainer.h"
#include "Engine/Physics/CollisionData.h"
#include "Engine/Graphics/Models/ModelData.h"
-#include "Engine/Content/Assets/Model.h"
+#include "Engine/Content/Assets/ModelBase.h"
namespace physx
{
@@ -40,8 +40,9 @@ public:
{
CollisionDataType Type = CollisionDataType::None;
ModelData* OverrideModelData = nullptr;
- AssetReference Model;
+ AssetReference Model;
int32 ModelLodIndex = 0;
+ uint32 MaterialSlotsMask = MAX_uint32;
ConvexMeshGenerationFlags ConvexFlags = ConvexMeshGenerationFlags::None;
int32 ConvexVertexLimit = 255;
};
diff --git a/Source/Engine/Physics/CollisionData.cpp b/Source/Engine/Physics/CollisionData.cpp
index 8de5bfcaa..63822539d 100644
--- a/Source/Engine/Physics/CollisionData.cpp
+++ b/Source/Engine/Physics/CollisionData.cpp
@@ -23,7 +23,7 @@ CollisionData::CollisionData(const SpawnParams& params, const AssetInfo* info)
#if COMPILE_WITH_PHYSICS_COOKING
-bool CollisionData::CookCollision(CollisionDataType type, Model* modelObj, int32 modelLodIndex, ConvexMeshGenerationFlags convexFlags, int32 convexVertexLimit)
+bool CollisionData::CookCollision(CollisionDataType type, ModelBase* modelObj, int32 modelLodIndex, uint32 materialSlotsMask, ConvexMeshGenerationFlags convexFlags, int32 convexVertexLimit)
{
// Validate state
if (!IsVirtual())
@@ -37,6 +37,7 @@ bool CollisionData::CookCollision(CollisionDataType type, Model* modelObj, int32
arg.Type = type;
arg.Model = modelObj;
arg.ModelLodIndex = modelLodIndex;
+ arg.MaterialSlotsMask = materialSlotsMask;
arg.ConvexFlags = convexFlags;
arg.ConvexVertexLimit = convexVertexLimit;
diff --git a/Source/Engine/Physics/CollisionData.h b/Source/Engine/Physics/CollisionData.h
index d3621f8d9..c2ff38815 100644
--- a/Source/Engine/Physics/CollisionData.h
+++ b/Source/Engine/Physics/CollisionData.h
@@ -4,11 +4,17 @@
#include "Engine/Content/BinaryAsset.h"
#include "Engine/Core/Math/BoundingBox.h"
-#include "Engine/Physics/Types.h"
class Model;
+class ModelBase;
class ModelData;
+namespace physx
+{
+ class PxConvexMesh;
+ class PxTriangleMesh;
+}
+
///
/// A storage data type.
///
@@ -156,8 +162,8 @@ public:
private:
CollisionDataOptions _options;
- PxConvexMesh* _convexMesh;
- PxTriangleMesh* _triangleMesh;
+ physx::PxConvexMesh* _convexMesh;
+ physx::PxTriangleMesh* _triangleMesh;
public:
@@ -173,8 +179,7 @@ public:
///
/// Gets the convex mesh object (valid only if asset is loaded and has cooked convex data).
///
- /// The convex mesh
- FORCE_INLINE PxConvexMesh* GetConvex() const
+ FORCE_INLINE physx::PxConvexMesh* GetConvex() const
{
return _convexMesh;
}
@@ -182,8 +187,7 @@ public:
///
/// Gets the triangle mesh object (valid only if asset is loaded and has cooked triangle data).
///
- /// The triangle mesh
- FORCE_INLINE PxTriangleMesh* GetTriangle() const
+ FORCE_INLINE physx::PxTriangleMesh* GetTriangle() const
{
return _triangleMesh;
}
@@ -201,9 +205,10 @@ public:
/// The collision data type.
/// The source model.
/// The source model LOD index.
+ /// The source model material slots mask. One bit per-slot. Can be sued to exclude particular material slots from collision cooking.
/// The convex mesh generation flags.
/// The convex mesh vertex limit. Use values in range [8;255]
- API_FUNCTION() bool CookCollision(CollisionDataType type, Model* model, int32 modelLodIndex = 0, ConvexMeshGenerationFlags convexFlags = ConvexMeshGenerationFlags::None, int32 convexVertexLimit = 255);
+ API_FUNCTION() bool CookCollision(CollisionDataType type, ModelBase* model, int32 modelLodIndex = 0, uint32 materialSlotsMask = MAX_uint32, ConvexMeshGenerationFlags convexFlags = ConvexMeshGenerationFlags::None, int32 convexVertexLimit = 255);
///
/// Cooks the mesh collision data and updates the virtual asset. action cannot be performed on a main thread.
diff --git a/Source/Engine/Physics/Physics.Queries.cpp b/Source/Engine/Physics/Physics.Queries.cpp
index 6cf3c786d..27171414b 100644
--- a/Source/Engine/Physics/Physics.Queries.cpp
+++ b/Source/Engine/Physics/Physics.Queries.cpp
@@ -425,11 +425,11 @@ bool Physics::CheckSphere(const Vector3& center, const float radius, uint32 laye
return GetScene()->overlap(geometry, pose, buffer, filterData, GetQueryFilterCallback());
}
-bool Physics::CheckCapsule(const Vector3& center, const float radius, const float height, uint32 layerMask, bool hitTriggers)
+bool Physics::CheckCapsule(const Vector3& center, const float radius, const float height, const Quaternion& rotation, uint32 layerMask, bool hitTriggers)
{
// Prepare data
SCENE_QUERY_SETUP_OVERLAP_1();
- const PxTransform pose(C2P(center));
+ const PxTransform pose(C2P(center), C2P(rotation));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
// Perform overlap test
@@ -470,11 +470,11 @@ bool Physics::OverlapSphere(const Vector3& center, const float radius, Array& results, uint32 layerMask, bool hitTriggers)
+bool Physics::OverlapCapsule(const Vector3& center, const float radius, const float height, Array& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers)
{
// Prepare data
SCENE_QUERY_SETUP_OVERLAP();
- const PxTransform pose(C2P(center));
+ const PxTransform pose(C2P(center), C2P(rotation));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
// Perform overlap test
@@ -521,11 +521,11 @@ bool Physics::OverlapSphere(const Vector3& center, const float radius, Array& results, uint32 layerMask, bool hitTriggers)
+bool Physics::OverlapCapsule(const Vector3& center, const float radius, const float height, Array& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers)
{
// Prepare data
SCENE_QUERY_SETUP_OVERLAP();
- const PxTransform pose(C2P(center));
+ const PxTransform pose(C2P(center), C2P(rotation));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
// Perform overlap test
diff --git a/Source/Engine/Physics/Physics.cpp b/Source/Engine/Physics/Physics.cpp
index 98237948f..333b21e99 100644
--- a/Source/Engine/Physics/Physics.cpp
+++ b/Source/Engine/Physics/Physics.cpp
@@ -9,6 +9,9 @@
#include "Utilities.h"
#include "PhysicsStepper.h"
#include "SimulationEventCallback.h"
+#if WITH_VEHICLE
+#include "Actors/WheeledVehicle.h"
+#endif
#include "Engine/Level/Level.h"
#include "Actors/PhysicsActor.h"
#include "Engine/Profiler/ProfilerCPU.h"
@@ -18,6 +21,9 @@
#include "Engine/Engine/Time.h"
#include
#include
+#if WITH_VEHICLE
+#include
+#endif
#if WITH_PVD
#include
#endif
@@ -61,7 +67,7 @@ public:
}
};
-PxFilterFlags PhysiXFilterShader(
+PxFilterFlags FilterShader(
PxFilterObjectAttributes attributes0, PxFilterData filterData0,
PxFilterObjectAttributes attributes1, PxFilterData filterData1,
PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
@@ -146,8 +152,22 @@ namespace
PxMaterial* DefaultMaterial = nullptr;
PxControllerManager* ControllerManager = nullptr;
PxCpuDispatcher* CpuDispatcher = nullptr;
+ float LastDeltaTime = 0.0f;
+#if WITH_VEHICLE
+ bool VehicleSDKInitialized = false;
+ Array WheelVehiclesCache;
+ Array WheelQueryResults;
+ Array WheelHitResults;
+ Array WheelVehiclesResultsPerWheel;
+ Array WheelVehiclesResultsPerVehicle;
+ PxBatchQuery* WheelRaycastBatchQuery = nullptr;
+ PxVehicleDrivableSurfaceToTireFrictionPairs* WheelTireFrictions = nullptr;
+#endif
}
+#if WITH_VEHICLE
+Array WheelVehicles;
+#endif
bool Physics::AutoSimulation = true;
uint32 Physics::LayerMasks[32];
@@ -172,7 +192,7 @@ PhysicsService PhysicsServiceInstance;
PxShapeFlags GetShapeFlags(bool isTrigger, bool isEnabled)
{
#if WITH_PVD
- PxShapeFlags flags = PxShapeFlag::eVISUALIZATION;
+ PxShapeFlags flags = PxShapeFlag::eVISUALIZATION;
#else
PxShapeFlags flags = static_cast(0);
#endif
@@ -194,6 +214,38 @@ PxShapeFlags GetShapeFlags(bool isTrigger, bool isEnabled)
return flags;
}
+#if WITH_VEHICLE
+
+void InitVehicleSDK()
+{
+ if (!VehicleSDKInitialized)
+ {
+ VehicleSDKInitialized = true;
+ PxInitVehicleSDK(*CPhysX);
+ PxVehicleSetBasisVectors(PxVec3(0, 1, 0), PxVec3(1, 0, 0));
+ PxVehicleSetUpdateMode(PxVehicleUpdateMode::eVELOCITY_CHANGE);
+ }
+}
+
+static PxQueryHitType::Enum WheelRaycastPreFilter(PxFilterData filterData0, PxFilterData filterData1, const void* constantBlock, PxU32 constantBlockSize, PxHitFlags& queryFlags)
+{
+ // Hardcoded id for vehicle shapes masking
+ if (filterData0.word3 == filterData1.word3)
+ {
+ return PxQueryHitType::eNONE;
+ }
+
+ // Collide for pairs (A,B) where the filtermask of A contains the ID of B and vice versa
+ if ((filterData0.word0 & filterData1.word1) && (filterData1.word0 & filterData0.word1))
+ {
+ return PxQueryHitType::eBLOCK;
+ }
+
+ return PxQueryHitType::eNONE;
+}
+
+#endif
+
void PhysicsSettings::Apply()
{
Time::_physicsMaxDeltaTime = MaxDeltaTime;
@@ -317,13 +369,6 @@ bool PhysicsService::Init()
_foundation = PxCreateFoundation(PX_PHYSICS_VERSION, PhysXAllocatorCallback, PhysXErrorCallback);
CHECK_INIT(_foundation, "PxCreateFoundation failed!");
- // Recording memory allocations is necessary if you want to
- // use the memory facilities in PVD effectively. Since PVD isn't necessarily connected
- // right away, we add a mechanism that records all outstanding memory allocations and
- // forwards them to PVD when it does connect.
- // This certainly has a performance and memory profile effect and thus should be used
- // only in non-production builds.
-
#if PHYSX_MEMORY_STATS
_foundation->setReportAllocationNames(true);
#endif
@@ -334,64 +379,56 @@ bool PhysicsService::Init()
PxPvd* pvd = nullptr;
#if WITH_PVD
- {
- // Connection parameters
- const char* pvd_host_ip = "127.0.0.1"; // IP of the PC which is running PVD
- int port = 5425; // TCP port to connect to, where PVD is listening
- unsigned int timeout = 100; // Timeout in milliseconds to wait for PVD to respond, consoles and remote PCs need a higher timeout.
-
- // Init PVD
- pvd = PxCreatePvd(*_foundation);
- PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(pvd_host_ip, port, timeout);
- const bool isConnected = pvd->connect(*transport, PxPvdInstrumentationFlag::eALL);
- if (isConnected)
- {
- LOG(Info, "Connected to PhysX Visual Debugger (PVD)"));
- }
-
- CPVD = pvd;
- }
+ {
+ // Init PVD
+ pvd = PxCreatePvd(*_foundation);
+ PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate("127.0.0.1", 5425, 100);
+ //PxPvdTransport* transport = PxDefaultPvdFileTransportCreate("D:\\physx_sample.pxd2");
+ if (transport)
+ {
+ const bool isConnected = pvd->connect(*transport, PxPvdInstrumentationFlag::eALL);
+ if (isConnected)
+ {
+ LOG(Info, "Connected to PhysX Visual Debugger (PVD)");
+ }
+ }
+ CPVD = pvd;
+ }
#endif
- // Init top-level PhysX objects
+ // Init PhysX
CPhysX = PxCreatePhysics(PX_PHYSICS_VERSION, *_foundation, ToleranceScale, false, pvd);
CHECK_INIT(CPhysX, "PxCreatePhysics failed!");
- // Init Extensions
+ // Init extensions
const bool extensionsInit = PxInitExtensions(*CPhysX, pvd);
CHECK_INIT(extensionsInit, "PxInitExtensions failed!");
-#if WITH_VEHICLE
- PxInitVehicleSDK(*Physics);
-#endif
+ // Init collision cooking
#if COMPILE_WITH_PHYSICS_COOKING
-
#if !USE_EDITOR
if (settings.SupportCookingAtRuntime)
#endif
{
- // Init cooking
PxCookingParams cookingParams(ToleranceScale);
cookingParams.meshWeldTolerance = 0.1f; // Weld to 1mm precision
cookingParams.meshPreprocessParams = PxMeshPreprocessingFlags(PxMeshPreprocessingFlag::eWELD_VERTICES);
Cooking = PxCreateCooking(PX_PHYSICS_VERSION, *_foundation, cookingParams);
CHECK_INIT(Cooking, "PxCreateCooking failed!");
}
-
#endif
// Create scene description
PxSceneDesc sceneDesc(CPhysX->getTolerancesScale());
sceneDesc.gravity = C2P(settings.DefaultGravity);
sceneDesc.flags |= PxSceneFlag::eENABLE_ACTIVE_ACTORS;
- //sceneDesc.flags |= PxSceneFlag::eEXCLUDE_KINEMATICS_FROM_ACTIVE_ACTORS; // TODO: set it?
if (!settings.DisableCCD)
sceneDesc.flags |= PxSceneFlag::eENABLE_CCD;
if (settings.EnableAdaptiveForce)
sceneDesc.flags |= PxSceneFlag::eADAPTIVE_FORCE;
sceneDesc.simulationEventCallback = &EventsCallback;
- sceneDesc.filterShader = PhysiXFilterShader;
+ sceneDesc.filterShader = FilterShader;
sceneDesc.bounceThresholdVelocity = settings.BounceThresholdVelocity;
if (sceneDesc.cpuDispatcher == nullptr)
{
@@ -407,6 +444,17 @@ bool PhysicsService::Init()
// Create scene
PhysicsScene = CPhysX->createScene(sceneDesc);
CHECK_INIT(PhysicsScene, "createScene failed!");
+#if WITH_PVD
+ auto pvdClient = PhysicsScene->getScenePvdClient();
+ if (pvdClient)
+ {
+ pvdClient->setScenePvdFlags(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS | PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES | PxPvdSceneFlag::eTRANSMIT_CONTACTS);
+ }
+ else
+ {
+ LOG(Info, "Missing PVD client scene.");
+ }
+#endif
// Init characters controller
ControllerManager = PxCreateControllerManager(*PhysicsScene);
@@ -428,10 +476,24 @@ void PhysicsService::Dispose()
{
// Ensure to finish (wait for simulation end)
Physics::CollectResults();
-
- // Cleanup
if (CPhysX)
Physics::FlushRequests();
+
+#if WITH_VEHICLE
+ if (VehicleSDKInitialized)
+ {
+ VehicleSDKInitialized = false;
+ PxCloseVehicleSDK();
+ }
+ RELEASE_PHYSX(WheelRaycastBatchQuery);
+ RELEASE_PHYSX(WheelTireFrictions);
+ WheelQueryResults.Resize(0);
+ WheelHitResults.Resize(0);
+ WheelVehiclesResultsPerWheel.Resize(0);
+ WheelVehiclesResultsPerVehicle.Resize(0);
+#endif
+
+ // Cleanup
RELEASE_PHYSX(DefaultMaterial);
SAFE_DELETE(Stepper);
Allocator::Free(ScratchMemory);
@@ -463,15 +525,12 @@ void PhysicsService::Dispose()
if (CPhysX)
{
-#if WITH_VEHICLE
- PxCloseVehicleSDK();
-#endif
PxCloseExtensions();
}
RELEASE_PHYSX(CPhysX);
#if WITH_PVD
- RELEASE_PHYSX(CPVD);
+ RELEASE_PHYSX(CPVD);
#endif
RELEASE_PHYSX(_foundation);
}
@@ -571,6 +630,7 @@ void Physics::Simulate(float dt)
if (Stepper->advance(PhysicsScene, dt, ScratchMemory, SCRATCH_BLOCK_SIZE) == false)
return;
EventsCallback.Clear();
+ LastDeltaTime = dt;
// TODO: move this call after rendering done
Stepper->renderDone();
@@ -590,6 +650,210 @@ void Physics::CollectResults()
Stepper->wait(PhysicsScene);
}
+#if WITH_VEHICLE
+ if (WheelVehicles.HasItems())
+ {
+ PROFILE_CPU_NAMED("Physics.Vehicles");
+
+ // Update vehicles steering
+ WheelVehiclesCache.Clear();
+ WheelVehiclesCache.EnsureCapacity(WheelVehicles.Count());
+ int32 wheelsCount = 0;
+ for (auto wheelVehicle : WheelVehicles)
+ {
+ auto drive = (PxVehicleWheels*)wheelVehicle->_drive;
+ ASSERT(drive);
+ WheelVehiclesCache.Add(drive);
+ wheelsCount += drive->mWheelsSimData.getNbWheels();
+
+ float throttle = wheelVehicle->_throttle;
+ float brake = wheelVehicle->_brake;
+ if (wheelVehicle->UseReverseAsBrake)
+ {
+ const float invalidDirectionThreshold = 80.0f;
+ const float breakThreshold = 8.0f;
+ const float forwardSpeed = wheelVehicle->GetForwardSpeed();
+
+ // Automatic gear change when changing driving direction
+ if (Math::Abs(forwardSpeed) < invalidDirectionThreshold)
+ {
+ if (throttle < -ZeroTolerance && wheelVehicle->GetCurrentGear() >= 0 && wheelVehicle->GetTargetGear() >= 0)
+ {
+ wheelVehicle->SetCurrentGear(-1);
+ }
+ else if (throttle > ZeroTolerance && wheelVehicle->GetCurrentGear() <= 0 && wheelVehicle->GetTargetGear() <= 0)
+ {
+ wheelVehicle->SetCurrentGear(1);
+ }
+ }
+
+ // Automatic break when changing driving direction
+ if (throttle > 0.0f)
+ {
+ if (forwardSpeed < -invalidDirectionThreshold)
+ {
+ brake = 1.0f;
+ }
+ }
+ else if (throttle < 0.0f)
+ {
+ if (forwardSpeed > invalidDirectionThreshold)
+ {
+ brake = 1.0f;
+ }
+ }
+ else
+ {
+ if (forwardSpeed < breakThreshold && forwardSpeed > -breakThreshold)
+ {
+ brake = 1.0f;
+ }
+ }
+
+ // Block throttle if user is changing driving direction
+ if ((throttle > 0.0f && wheelVehicle->GetTargetGear() < 0) || (throttle < 0.0f && wheelVehicle->GetTargetGear() > 0))
+ {
+ throttle = 0.0f;
+ }
+
+ throttle = Math::Abs(throttle);
+ }
+ else
+ {
+ throttle = Math::Max(throttle, 0.0f);
+ }
+ // @formatter:off
+ // Reference: PhysX SDK docs
+ // TODO: expose input control smoothing data
+ static constexpr PxVehiclePadSmoothingData padSmoothing =
+ {
+ {
+ 6.0f, // rise rate eANALOG_INPUT_ACCEL
+ 6.0f, // rise rate eANALOG_INPUT_BRAKE
+ 12.0f, // rise rate eANALOG_INPUT_HANDBRAKE
+ 2.5f, // rise rate eANALOG_INPUT_STEER_LEFT
+ 2.5f, // rise rate eANALOG_INPUT_STEER_RIGHT
+ },
+ {
+ 10.0f, // fall rate eANALOG_INPUT_ACCEL
+ 10.0f, // fall rate eANALOG_INPUT_BRAKE
+ 12.0f, // fall rate eANALOG_INPUT_HANDBRAKE
+ 5.0f, // fall rate eANALOG_INPUT_STEER_LEFT
+ 5.0f, // fall rate eANALOG_INPUT_STEER_RIGHT
+ }
+ };
+ // Reference: PhysX SDK docs
+ // TODO: expose steer vs forward curve into per-vehicle (up to 8 points, values clamped into 0/1 range)
+ static constexpr PxF32 steerVsForwardSpeedData[] =
+ {
+ 0.0f, 1.0f,
+ 20.0f, 0.9f,
+ 65.0f, 0.8f,
+ 120.0f, 0.7f,
+ PX_MAX_F32, PX_MAX_F32,
+ PX_MAX_F32, PX_MAX_F32,
+ PX_MAX_F32, PX_MAX_F32,
+ PX_MAX_F32, PX_MAX_F32,
+ };
+ const PxFixedSizeLookupTable<8> steerVsForwardSpeed(steerVsForwardSpeedData, 4);
+ // @formatter:on
+ switch (wheelVehicle->_driveTypeCurrent)
+ {
+ case WheeledVehicle::DriveTypes::Drive4W:
+ {
+ PxVehicleDrive4WRawInputData rawInputData;
+ rawInputData.setAnalogAccel(throttle);
+ rawInputData.setAnalogBrake(brake);
+ rawInputData.setAnalogSteer(wheelVehicle->_steering);
+ rawInputData.setAnalogHandbrake(wheelVehicle->_handBrake);
+ PxVehicleDrive4WSmoothAnalogRawInputsAndSetAnalogInputs(padSmoothing, steerVsForwardSpeed, rawInputData, LastDeltaTime, false, *(PxVehicleDrive4W*)drive);
+ break;
+ }
+ case WheeledVehicle::DriveTypes::DriveNW:
+ {
+ PxVehicleDriveNWRawInputData rawInputData;
+ rawInputData.setAnalogAccel(throttle);
+ rawInputData.setAnalogBrake(brake);
+ rawInputData.setAnalogSteer(wheelVehicle->_steering);
+ rawInputData.setAnalogHandbrake(wheelVehicle->_handBrake);
+ PxVehicleDriveNWSmoothAnalogRawInputsAndSetAnalogInputs(padSmoothing, steerVsForwardSpeed, rawInputData, LastDeltaTime, false, *(PxVehicleDriveNW*)drive);
+ break;
+ }
+ }
+ }
+
+ // Update batches queries cache
+ if (wheelsCount > WheelQueryResults.Count())
+ {
+ if (WheelRaycastBatchQuery)
+ WheelRaycastBatchQuery->release();
+ WheelQueryResults.Resize(wheelsCount);
+ WheelQueryResults.Resize(WheelQueryResults.Capacity());
+ PxBatchQueryDesc desc(wheelsCount, 0, 0);
+ desc.queryMemory.userRaycastResultBuffer = WheelQueryResults.Get();
+ desc.queryMemory.userRaycastTouchBuffer = WheelHitResults.Get();
+ desc.queryMemory.raycastTouchBufferSize = wheelsCount;
+ desc.preFilterShader = WheelRaycastPreFilter;
+ WheelRaycastBatchQuery = PhysicsScene->createBatchQuery(desc);
+ }
+
+ // TODO: expose vehicle tires configuration
+ if (!WheelTireFrictions)
+ {
+ PxVehicleDrivableSurfaceType surfaceTypes[1];
+ surfaceTypes[0].mType = 0;
+ const PxMaterial* surfaceMaterials[1];
+ surfaceMaterials[0] = DefaultMaterial;
+ WheelTireFrictions = PxVehicleDrivableSurfaceToTireFrictionPairs::allocate(1, 1);
+ WheelTireFrictions->setup(1, 1, surfaceMaterials, surfaceTypes);
+ WheelTireFrictions->setTypePairFriction(0, 0, 5.0f);
+ }
+
+ // Setup cache for wheel states
+ WheelVehiclesResultsPerVehicle.Resize(WheelVehicles.Count(), false);
+ WheelVehiclesResultsPerWheel.Resize(wheelsCount, false);
+ wheelsCount = 0;
+ for (int32 i = 0; i < WheelVehicles.Count(); i++)
+ {
+ auto drive = (PxVehicleWheels*)WheelVehicles[i]->_drive;
+ auto& perVehicle = WheelVehiclesResultsPerVehicle[i];
+ perVehicle.nbWheelQueryResults = drive->mWheelsSimData.getNbWheels();
+ perVehicle.wheelQueryResults = WheelVehiclesResultsPerWheel.Get() + wheelsCount;
+ wheelsCount += perVehicle.nbWheelQueryResults;
+ }
+
+ // Update vehicles
+ PxVehicleSuspensionRaycasts(WheelRaycastBatchQuery, WheelVehiclesCache.Count(), WheelVehiclesCache.Get(), WheelQueryResults.Count(), WheelQueryResults.Get());
+ PxVehicleUpdates(LastDeltaTime, PhysicsScene->getGravity(), *WheelTireFrictions, WheelVehiclesCache.Count(), WheelVehiclesCache.Get(), WheelVehiclesResultsPerVehicle.Get());
+
+ // Synchronize state
+ for (int32 i = 0; i < WheelVehicles.Count(); i++)
+ {
+ auto wheelVehicle = WheelVehicles[i];
+ auto drive = WheelVehiclesCache[i];
+ auto& perVehicle = WheelVehiclesResultsPerVehicle[i];
+
+ // Update wheels
+ for (int32 j = 0; j < wheelVehicle->_wheelsData.Count(); j++)
+ {
+ auto& wheelData = wheelVehicle->_wheelsData[j];
+ auto& perWheel = perVehicle.wheelQueryResults[j];
+
+ auto& state = wheelData.State;
+ state.IsInAir = perWheel.isInAir;
+ state.TireContactCollider = perWheel.tireContactShape ? static_cast(perWheel.tireContactShape->userData) : nullptr;
+ state.TireContactPoint = P2C(perWheel.tireContactPoint);
+ state.TireContactNormal = P2C(perWheel.tireContactNormal);
+ state.TireFriction = perWheel.tireFriction;
+
+ const float wheelRotationAngle = -RadiansToDegrees * drive->mWheelsDynData.getWheelRotationAngle(j);
+ const float wheelSteerAngle = RadiansToDegrees * perWheel.steerAngle;
+ wheelData.Collider->SetLocalOrientation(Quaternion::Euler(0, wheelSteerAngle, wheelRotationAngle) * wheelData.LocalOrientation);
+ }
+ }
+ }
+#endif
+
{
PROFILE_CPU_NAMED("Physics.FlushActiveTransforms");
diff --git a/Source/Engine/Physics/Physics.h b/Source/Engine/Physics/Physics.h
index 71e172699..8aac37a2e 100644
--- a/Source/Engine/Physics/Physics.h
+++ b/Source/Engine/Physics/Physics.h
@@ -67,9 +67,8 @@ API_CLASS(Static) class FLAXENGINE_API Physics
DECLARE_SCRIPTING_TYPE_NO_SPAWN(Physics);
///
- /// Gets master physics object
+ /// Gets the master physics object.
///
- /// Physics object
static PxPhysics* GetPhysics();
#if COMPILE_WITH_PHYSICS_COOKING
@@ -77,7 +76,6 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(Physics);
///
/// Gets physics cooking object
///
- /// Physics cooking object
static PxCooking* GetCooking();
#endif
@@ -85,37 +83,31 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(Physics);
///
/// Gets PhysX scene object
///
- /// Scene object
static PxScene* GetScene();
///
/// Gets PhysX characters controller manager object
///
- /// Controller manager object
static PxControllerManager* GetControllerManager();
///
/// Gets the physics tolerances scale.
///
- /// The tolerances scale.
static PxTolerancesScale* GetTolerancesScale();
///
/// Gets the default query filter callback used for the scene queries.
///
- /// The query filter callback.
static PxQueryFilterCallback* GetQueryFilterCallback();
///
/// Gets the default query filter callback used for the character controller collisions detection.
///
- /// The query filter callback.
static PxQueryFilterCallback* GetCharacterQueryFilterCallback();
///
/// Gets the default physical material.
///
- /// The native material resource.
static PxMaterial* GetDefaultMaterial();
public:
@@ -347,10 +339,11 @@ public:
/// The capsule center.
/// The radius of the capsule.
/// The height of the capsule, excluding the top and bottom spheres.
+ /// The capsule rotation.
/// The layer mask used to filter the results.
/// If set to true triggers will be hit, otherwise will skip them.
/// True if capsule overlaps any matching object, otherwise false.
- API_FUNCTION() static bool CheckCapsule(const Vector3& center, float radius, float height, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
+ API_FUNCTION() static bool CheckCapsule(const Vector3& center, float radius, float height, const Quaternion& rotation = Quaternion::Identity, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
///
/// Finds all colliders touching or inside of the given box.
@@ -382,10 +375,11 @@ public:
/// The radius of the capsule.
/// The height of the capsule, excluding the top and bottom spheres.
/// The result colliders that overlap with the given sphere. Valid only when method returns true.
+ /// The capsule rotation.
/// The layer mask used to filter the results.
/// If set to true triggers will be hit, otherwise will skip them.
/// True if capsule overlaps any matching object, otherwise false.
- API_FUNCTION() static bool OverlapCapsule(const Vector3& center, float radius, float height, API_PARAM(Out) Array& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
+ API_FUNCTION() static bool OverlapCapsule(const Vector3& center, float radius, float height, API_PARAM(Out) Array& results, const Quaternion& rotation = Quaternion::Identity, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
///
/// Finds all colliders touching or inside of the given box.
@@ -417,10 +411,11 @@ public:
/// The radius of the capsule.
/// The height of the capsule, excluding the top and bottom spheres.
/// The result colliders that overlap with the given sphere. Valid only when method returns true.
+ /// The capsule rotation.
/// The layer mask used to filter the results.
/// If set to true triggers will be hit, otherwise will skip them.
/// True if capsule overlaps any matching object, otherwise false.
- API_FUNCTION() static bool OverlapCapsule(const Vector3& center, float radius, float height, API_PARAM(Out) Array& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
+ API_FUNCTION() static bool OverlapCapsule(const Vector3& center, float radius, float height, API_PARAM(Out) Array& results, const Quaternion& rotation = Quaternion::Identity, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
public:
diff --git a/Source/Engine/Physics/Utilities.h b/Source/Engine/Physics/Utilities.h
index 34ee7f66d..b2c3eb0e3 100644
--- a/Source/Engine/Physics/Utilities.h
+++ b/Source/Engine/Physics/Utilities.h
@@ -74,4 +74,24 @@ inline Vector3 P2C(const PxExtendedVec3& v)
#endif
}
+inline float M2ToCm2(float v)
+{
+ return v * (100.0f * 100.0f);
+}
+
+inline float Cm2ToM2(float v)
+{
+ return v / (100.0f * 100.0f);
+}
+
+inline float RpmToRadPerS(float v)
+{
+ return v * (PI / 30.0f);
+}
+
+inline float RadPerSToRpm(float v)
+{
+ return v * (30.0f / PI);
+}
+
extern PxShapeFlags GetShapeFlags(bool isTrigger, bool isEnabled);
diff --git a/Source/Engine/Platform/Base/FileBase.cpp b/Source/Engine/Platform/Base/FileBase.cpp
index d7308b0fd..9ff9149db 100644
--- a/Source/Engine/Platform/Base/FileBase.cpp
+++ b/Source/Engine/Platform/Base/FileBase.cpp
@@ -5,6 +5,7 @@
#include "Engine/Core/Types/String.h"
#include "Engine/Core/Types/StringBuilder.h"
#include "Engine/Core/Types/DataContainer.h"
+#include "Engine/Core/Log.h"
bool FileBase::ReadAllBytes(const StringView& path, byte* data, int32 length)
{
@@ -36,16 +37,23 @@ bool FileBase::ReadAllBytes(const StringView& path, Array& data)
auto file = File::Open(path, FileMode::OpenExisting, FileAccess::Read, FileShare::All);
if (file)
{
- uint32 size = file->GetSize();
- data.Resize(size, false);
- if (size > 0)
+ const uint32 size = file->GetSize();
+ if (size < MAX_int32)
{
- result = file->Read(data.Get(), size) != 0;
+ data.Resize(size, false);
+ if (size > 0)
+ {
+ result = file->Read(data.Get(), size) != 0;
+ }
+ else
+ {
+ data.Resize(0, false);
+ result = false;
+ }
}
else
{
- data.Resize(0, false);
- result = false;
+ LOG(Error, "Failed to load file {0}. It's too big. Size: {1} MB", path, size / (1024 * 1024));
}
Delete(file);
@@ -61,16 +69,23 @@ bool FileBase::ReadAllBytes(const StringView& path, DataContainer& data)
auto file = File::Open(path, FileMode::OpenExisting, FileAccess::Read, FileShare::All);
if (file)
{
- uint32 size = file->GetSize();
- data.Allocate(size);
- if (size > 0)
+ const uint32 size = file->GetSize();
+ if (size < MAX_int32)
{
- result = file->Read(data.Get(), size) != 0;
+ data.Allocate(size);
+ if (size > 0)
+ {
+ result = file->Read(data.Get(), size) != 0;
+ }
+ else
+ {
+ data.Release();
+ result = false;
+ }
}
else
{
- data.Release();
- result = false;
+ LOG(Error, "Failed to load file {0}. It's too big. Size: {1} MB", path, size / (1024 * 1024));
}
Delete(file);
diff --git a/Source/Engine/Platform/Base/PlatformBase.cpp b/Source/Engine/Platform/Base/PlatformBase.cpp
index 5ffb85a9a..e33ae1499 100644
--- a/Source/Engine/Platform/Base/PlatformBase.cpp
+++ b/Source/Engine/Platform/Base/PlatformBase.cpp
@@ -163,6 +163,19 @@ void PlatformBase::Exit()
{
}
+void* PlatformBase::AllocatePages(uint64 numPages, uint64 pageSize)
+{
+ // Fallback to the default memory allocation
+ const uint64 numBytes = numPages * pageSize;
+ return Platform::Allocate(numBytes, pageSize);
+}
+
+void PlatformBase::FreePages(void* ptr)
+{
+ // Fallback to free
+ Platform::Free(ptr);
+}
+
PlatformType PlatformBase::GetPlatformType()
{
return PLATFORM_TYPE;
@@ -407,6 +420,11 @@ ScreenOrientationType PlatformBase::GetScreenOrientationType()
return ScreenOrientationType::Unknown;
}
+bool PlatformBase::GetIsPaused()
+{
+ return false;
+}
+
void PlatformBase::CreateGuid(Guid& result)
{
static uint16 guidCounter = 0;
@@ -534,6 +552,8 @@ const Char* ToString(PlatformType type)
return TEXT("Xbox Scarlett");
case PlatformType::Android:
return TEXT("Android");
+ case PlatformType::Switch:
+ return TEXT("Switch");
default:
return TEXT("");
}
diff --git a/Source/Engine/Platform/Base/PlatformBase.h b/Source/Engine/Platform/Base/PlatformBase.h
index a91b5b690..0d972f412 100644
--- a/Source/Engine/Platform/Base/PlatformBase.h
+++ b/Source/Engine/Platform/Base/PlatformBase.h
@@ -322,13 +322,13 @@ public:
/// The number of pages to allocate.
/// The size of single page. Use Platform::GetCPUInfo().PageSize or provide compatible, custom size.
/// The pointer to the allocated pages in memory.
- static void* AllocatePages(uint64 numPages, uint64 pageSize) = delete;
+ static void* AllocatePages(uint64 numPages, uint64 pageSize);
///
/// Frees allocated pages memory block.
///
/// The pointer to the pages to deallocate.
- static void FreePages(void* ptr) = delete;
+ static void FreePages(void* ptr);
public:
@@ -616,10 +616,7 @@ public:
///
/// Returns true if app is paused. Engine ticking (update/physics/drawing) is disabled in that state, only platform is updated until app end or resume.
///
- static bool GetIsPaused()
- {
- return false;
- }
+ static bool GetIsPaused();
///
/// Creates the unique identifier.
diff --git a/Source/Engine/Platform/Base/WindowsManager.cpp b/Source/Engine/Platform/Base/WindowsManager.cpp
index 75082c4f9..ef2d50b71 100644
--- a/Source/Engine/Platform/Base/WindowsManager.cpp
+++ b/Source/Engine/Platform/Base/WindowsManager.cpp
@@ -3,7 +3,6 @@
#include "../WindowsManager.h"
#include "Engine/Engine/Time.h"
#include "Engine/Profiler/ProfilerCPU.h"
-#include "Engine/Core/ObjectsRemovalService.h"
#include "Engine/Engine/EngineService.h"
class WindowsManagerService : public EngineService
@@ -41,11 +40,6 @@ Window* WindowsManager::GetByNativePtr(void* handle)
return result;
}
-Vector2 WindowsManager::CalcCenteredWinPos(const Vector2& size)
-{
- return (Platform::GetDesktopSize() - size) * 0.5f;
-}
-
void WindowsManager::Register(Window* win)
{
WindowsLocker.Lock();
diff --git a/Source/Engine/Platform/Clipboard.h b/Source/Engine/Platform/Clipboard.h
index 5c84d5d9e..6ad8e7bc5 100644
--- a/Source/Engine/Platform/Clipboard.h
+++ b/Source/Engine/Platform/Clipboard.h
@@ -14,6 +14,8 @@
#include "Base/ClipboardBase.h"
#elif PLATFORM_ANDROID
#include "Base/ClipboardBase.h"
+#elif PLATFORM_SWITCH
+#include "Base/ClipboardBase.h"
#else
#error Missing Clipboard implementation!
#endif
diff --git a/Source/Engine/Platform/ConditionVariable.h b/Source/Engine/Platform/ConditionVariable.h
index 0ebaecd92..1704cc361 100644
--- a/Source/Engine/Platform/ConditionVariable.h
+++ b/Source/Engine/Platform/ConditionVariable.h
@@ -14,6 +14,8 @@
#include "Win32/Win32ConditionVariable.h"
#elif PLATFORM_ANDROID
#include "Unix/UnixConditionVariable.h"
+#elif PLATFORM_SWITCH
+#include "Platforms/Switch/Engine/Platform/SwitchConditionVariable.h"
#else
#error Missing Condition Variable implementation!
#endif
diff --git a/Source/Engine/Platform/CriticalSection.h b/Source/Engine/Platform/CriticalSection.h
index d2d57a997..85f4e464c 100644
--- a/Source/Engine/Platform/CriticalSection.h
+++ b/Source/Engine/Platform/CriticalSection.h
@@ -14,6 +14,8 @@
#include "Win32/Win32CriticalSection.h"
#elif PLATFORM_ANDROID
#include "Unix/UnixCriticalSection.h"
+#elif PLATFORM_SWITCH
+#include "Platforms/Switch/Engine/Platform/SwitchCriticalSection.h"
#else
#error Missing Critical Section implementation!
#endif
diff --git a/Source/Engine/Platform/Defines.h b/Source/Engine/Platform/Defines.h
index ac45ba1c9..9064fb13a 100644
--- a/Source/Engine/Platform/Defines.h
+++ b/Source/Engine/Platform/Defines.h
@@ -43,6 +43,11 @@ API_ENUM() enum class PlatformType
/// Running on Android.
///
Android = 7,
+
+ ///
+ /// Running on Switch.
+ ///
+ Switch = 8,
};
///
@@ -113,6 +118,9 @@ API_ENUM() enum class ArchitectureType
#if !defined(PLATFORM_IOS)
#define PLATFORM_IOS 0
#endif
+#if !defined(PLATFORM_SWITCH)
+#define PLATFORM_SWITCH 0
+#endif
#if PLATFORM_WINDOWS
#include "Windows/WindowsDefines.h"
@@ -126,6 +134,8 @@ API_ENUM() enum class ArchitectureType
#include "Platforms/XboxScarlett/Engine/Platform/XboxScarlettDefines.h"
#elif PLATFORM_ANDROID
#include "Android/AndroidDefines.h"
+#elif PLATFORM_SWITCH
+#include "Platforms/Switch/Engine/Platform/SwitchDefines.h"
#else
#error Missing Defines implementation!
#endif
diff --git a/Source/Engine/Platform/File.h b/Source/Engine/Platform/File.h
index 44ea82f15..4988203b7 100644
--- a/Source/Engine/Platform/File.h
+++ b/Source/Engine/Platform/File.h
@@ -14,6 +14,8 @@
#include "Win32/Win32File.h"
#elif PLATFORM_ANDROID
#include "Android/AndroidFile.h"
+#elif PLATFORM_SWITCH
+#include "Platforms/Switch/Engine/Platform/SwitchFile.h"
#else
#error Missing File implementation!
#endif
diff --git a/Source/Engine/Platform/FileSystem.h b/Source/Engine/Platform/FileSystem.h
index 5d38c7c00..20d3c05e5 100644
--- a/Source/Engine/Platform/FileSystem.h
+++ b/Source/Engine/Platform/FileSystem.h
@@ -14,6 +14,8 @@
#include "Platforms/XboxScarlett/Engine/Platform/XboxScarlettFileSystem.h"
#elif PLATFORM_ANDROID
#include "Android/AndroidFileSystem.h"
+#elif PLATFORM_SWITCH
+#include "Platforms/Switch/Engine/Platform/SwitchFileSystem.h"
#else
#error Missing File System implementation!
#endif
diff --git a/Source/Engine/Platform/FileSystemWatcher.h b/Source/Engine/Platform/FileSystemWatcher.h
index 3c74ad627..bd14f4241 100644
--- a/Source/Engine/Platform/FileSystemWatcher.h
+++ b/Source/Engine/Platform/FileSystemWatcher.h
@@ -14,6 +14,8 @@
#include "Base/FileSystemWatcherBase.h"
#elif PLATFORM_ANDROID
#include "Base/FileSystemWatcherBase.h"
+#elif PLATFORM_SWITCH
+#include "Base/FileSystemWatcherBase.h"
#else
#error Missing File System Watcher implementation!
#endif
diff --git a/Source/Engine/Platform/IGuiData.h b/Source/Engine/Platform/IGuiData.h
index a285d62cb..05cc3c6f8 100644
--- a/Source/Engine/Platform/IGuiData.h
+++ b/Source/Engine/Platform/IGuiData.h
@@ -3,6 +3,7 @@
#pragma once
#include "Engine/Core/Types/String.h"
+#include "Engine/Core/Collections/Array.h"
///
/// Interface for GUI data object container.
diff --git a/Source/Engine/Platform/Linux/LinuxPlatform.cpp b/Source/Engine/Platform/Linux/LinuxPlatform.cpp
index 95426b70a..8c212314c 100644
--- a/Source/Engine/Platform/Linux/LinuxPlatform.cpp
+++ b/Source/Engine/Platform/Linux/LinuxPlatform.cpp
@@ -1382,6 +1382,7 @@ DragDropEffect LinuxWindow::DoDragDrop(const StringView& data)
X11::Window previousWindow = 0;
DragDropEffect result = DragDropEffect::None;
float lastDraw = Platform::GetTimeSeconds();
+ float startTime = lastDraw;
while (true)
{
X11::XNextEvent(xDisplay, &event);
@@ -1559,7 +1560,7 @@ DragDropEffect LinuxWindow::DoDragDrop(const StringView& data)
if (!(event.xclient.data.l[1]&1) && status != Unaware)
status = Unreceptive;
}
- else if (event.type == ButtonRelease && event.xbutton.button == 1)
+ else if (event.type == ButtonRelease && event.xbutton.button == Button1)
{
if (status == CanDrop)
{
@@ -1597,11 +1598,46 @@ DragDropEffect LinuxWindow::DoDragDrop(const StringView& data)
// Redraw
const float time = Platform::GetTimeSeconds();
- if (time - lastDraw >= 1.0f / 60.0f)
+ if (time - lastDraw >= 1.0f / 20.0f)
{
lastDraw = time;
Engine::OnDraw();
}
+
+ // Prevent dead-loop
+ if (time - startTime >= 10.0f)
+ {
+ break;
+ }
+ }
+
+ // Drag end
+ if (previousWindow != 0 && previousVersion != -1)
+ {
+ // Send drag left event
+ auto ww = WindowsManager::GetByNativePtr((void*)previousWindow);
+ if (ww)
+ {
+ ww->_dragOver = false;
+ ww->OnDragLeave();
+ }
+ else
+ {
+ X11::XClientMessageEvent m;
+ memset(&m, 0, sizeof(m));
+ m.type = ClientMessage;
+ m.display = event.xclient.display;
+ m.window = previousWindow;
+ m.message_type = xAtomXdndLeave;
+ m.format = 32;
+ m.data.l[0] = _window;
+ m.data.l[1] = 0;
+ m.data.l[2] = 0;
+ m.data.l[3] = 0;
+ m.data.l[4] = 0;
+ X11::XSendEvent(xDisplay, previousWindow, 0, NoEventMask, (X11::XEvent*)&m);
+ X11::XFlush(xDisplay);
+ }
}
// End grabbing
@@ -1996,6 +2032,8 @@ bool LinuxPlatform::Init()
// Get user locale string
char* locale = setlocale(LC_ALL, NULL);
+ if (strcmp (locale, "C") == 0)
+ locale = "";
UserLocale = String(locale);
// Get computer name string
diff --git a/Source/Engine/Platform/Network.h b/Source/Engine/Platform/Network.h
index c6c99d1f8..b1f5746ac 100644
--- a/Source/Engine/Platform/Network.h
+++ b/Source/Engine/Platform/Network.h
@@ -14,6 +14,8 @@
#include "Win32/Win32Network.h"
#elif PLATFORM_ANDROID
#include "Unix/UnixNetwork.h"
+#elif PLATFORM_SWITCH
+#include "Base/NetworkBase.h"
#else
#error Missing Network implementation!
#endif
diff --git a/Source/Engine/Platform/Platform.Build.cs b/Source/Engine/Platform/Platform.Build.cs
index 8fb2d2175..1948b56b6 100644
--- a/Source/Engine/Platform/Platform.Build.cs
+++ b/Source/Engine/Platform/Platform.Build.cs
@@ -65,6 +65,9 @@ public class Platform : EngineModule
options.SourcePaths.Add(Path.Combine(FolderPath, "Unix"));
options.SourcePaths.Add(Path.Combine(FolderPath, "Android"));
break;
+ case TargetPlatform.Switch:
+ options.SourcePaths.Add(Path.Combine(Globals.EngineRoot, "Source", "Platforms", "Switch", "Engine", "Platform"));
+ break;
default: throw new InvalidPlatformException(options.Platform.Target);
}
if (options.Target.IsEditor)
@@ -76,6 +79,7 @@ public class Platform : EngineModule
options.SourceFiles.Add(Path.Combine(FolderPath, "Android", "AndroidPlatformSettings.h"));
AddSourceFileIfExists(options, Path.Combine(Globals.EngineRoot, "Source", "Platforms", "XboxScarlett", "Engine", "Platform", "XboxScarlettPlatformSettings.h"));
AddSourceFileIfExists(options, Path.Combine(Globals.EngineRoot, "Source", "Platforms", "PS4", "Engine", "Platform", "PS4PlatformSettings.h"));
+ AddSourceFileIfExists(options, Path.Combine(Globals.EngineRoot, "Source", "Platforms", "Switch", "Engine", "Platform", "SwitchPlatformSettings.h"));
}
}
}
diff --git a/Source/Engine/Platform/Platform.h b/Source/Engine/Platform/Platform.h
index f96526be0..3fa1d99a1 100644
--- a/Source/Engine/Platform/Platform.h
+++ b/Source/Engine/Platform/Platform.h
@@ -20,6 +20,8 @@
#include "Platforms/XboxScarlett/Engine/Platform/XboxScarlettPlatform.h"
#elif PLATFORM_ANDROID
#include "Android/AndroidPlatform.h"
+#elif PLATFORM_SWITCH
+#include "Platforms/Switch/Engine/Platform/SwitchPlatform.h"
#else
#error Missing Platform implementation!
#endif
diff --git a/Source/Engine/Platform/Thread.h b/Source/Engine/Platform/Thread.h
index 4c156f936..4d9c3428a 100644
--- a/Source/Engine/Platform/Thread.h
+++ b/Source/Engine/Platform/Thread.h
@@ -14,6 +14,8 @@
#include "Win32/Win32Thread.h"
#elif PLATFORM_ANDROID
#include "Android/AndroidThread.h"
+#elif PLATFORM_SWITCH
+#include "Platforms/Switch/Engine/Platform/SwitchThread.h"
#else
#error Missing Thread implementation!
#endif
diff --git a/Source/Engine/Platform/Types.h b/Source/Engine/Platform/Types.h
index b43bd2bd5..2fff3089d 100644
--- a/Source/Engine/Platform/Types.h
+++ b/Source/Engine/Platform/Types.h
@@ -140,6 +140,29 @@ typedef AndroidWindow Window;
class UnixNetwork;
typedef UnixNetwork Network;
+#elif PLATFORM_SWITCH
+
+class ClipboardBase;
+typedef ClipboardBase Clipboard;
+class SwitchCriticalSection;
+typedef SwitchCriticalSection CriticalSection;
+class SwitchConditionVariable;
+typedef SwitchConditionVariable ConditionVariable;
+class SwitchFileSystem;
+typedef SwitchFileSystem FileSystem;
+class FileSystemWatcherBase;
+typedef FileSystemWatcherBase FileSystemWatcher;
+class SwitchFile;
+typedef SwitchFile File;
+class SwitchPlatform;
+typedef SwitchPlatform Platform;
+class SwitchThread;
+typedef SwitchThread Thread;
+class SwitchWindow;
+typedef SwitchWindow Window;
+class NetworkBase;
+typedef NetworkBase Network;
+
#else
#error Missing Types implementation!
diff --git a/Source/Engine/Platform/Unix/UnixPlatform.cpp b/Source/Engine/Platform/Unix/UnixPlatform.cpp
index cb734bfcd..42b788649 100644
--- a/Source/Engine/Platform/Unix/UnixPlatform.cpp
+++ b/Source/Engine/Platform/Unix/UnixPlatform.cpp
@@ -51,20 +51,6 @@ void UnixPlatform::Free(void* ptr)
}
}
-void* UnixPlatform::AllocatePages(uint64 numPages, uint64 pageSize)
-{
- const uint64 numBytes = numPages * pageSize;
-
- // Fallback to malloc
- return malloc(numBytes);
-}
-
-void UnixPlatform::FreePages(void* ptr)
-{
- // Fallback to free
- free(ptr);
-}
-
uint64 UnixPlatform::GetCurrentProcessId()
{
return getpid();
diff --git a/Source/Engine/Platform/Unix/UnixPlatform.h b/Source/Engine/Platform/Unix/UnixPlatform.h
index 12d4e5bc2..e0041c604 100644
--- a/Source/Engine/Platform/Unix/UnixPlatform.h
+++ b/Source/Engine/Platform/Unix/UnixPlatform.h
@@ -16,8 +16,6 @@ public:
// [PlatformBase]
static void* Allocate(uint64 size, uint64 alignment);
static void Free(void* ptr);
- static void* AllocatePages(uint64 numPages, uint64 pageSize);
- static void FreePages(void* ptr);
static uint64 GetCurrentProcessId();
};
diff --git a/Source/Engine/Platform/Win32/Win32ConditionVariable.h b/Source/Engine/Platform/Win32/Win32ConditionVariable.h
index ad3bdcff0..8273d914d 100644
--- a/Source/Engine/Platform/Win32/Win32ConditionVariable.h
+++ b/Source/Engine/Platform/Win32/Win32ConditionVariable.h
@@ -5,6 +5,7 @@
#if PLATFORM_WIN32
#include "Win32CriticalSection.h"
+#include "Engine/Core/Types/BaseTypes.h"
///
/// Win32 implementation of a condition variables. Condition variables are synchronization primitives that enable threads to wait until a particular condition occurs. Condition variables enable threads to atomically release a lock and enter the sleeping state.
diff --git a/Source/Engine/Platform/Window.h b/Source/Engine/Platform/Window.h
index 0b17401fc..138303dc6 100644
--- a/Source/Engine/Platform/Window.h
+++ b/Source/Engine/Platform/Window.h
@@ -14,6 +14,8 @@
#include "Platforms/XboxScarlett/Engine/Platform/XboxScarlettWindow.h"
#elif PLATFORM_ANDROID
#include "Android/AndroidWindow.h"
+#elif PLATFORM_SWITCH
+#include "Platforms/Switch/Engine/Platform/SwitchWindow.h"
#else
#error Missing Window implementation!
#endif
diff --git a/Source/Engine/Platform/Windows/WindowsPlatform.cpp b/Source/Engine/Platform/Windows/WindowsPlatform.cpp
index 1b8942dec..8bff48f18 100644
--- a/Source/Engine/Platform/Windows/WindowsPlatform.cpp
+++ b/Source/Engine/Platform/Windows/WindowsPlatform.cpp
@@ -38,7 +38,7 @@ namespace
CriticalSection SymLocker;
bool SymInitialized = false;
bool SymModulesDirty = true;
- char* SymPath = nullptr;
+ Array SymbolsPath;
#endif
}
@@ -617,9 +617,8 @@ void WindowsPlatform::Exit()
{
SymInitialized = false;
SymCleanup(GetCurrentProcess());
- free(SymPath);
- SymPath = nullptr;
}
+ SymbolsPath.Resize(0);
SymLocker.Unlock();
#endif
@@ -1116,7 +1115,13 @@ void* WindowsPlatform::LoadLibrary(const Char* filename)
#if CRASH_LOG_ENABLE
// Refresh modules info during next stack trace collecting to have valid debug symbols information
SymLocker.Lock();
- SymModulesDirty = true;
+ const auto folder = StringUtils::GetDirectoryName(filename);
+ if (!SymbolsPath.Contains(folder))
+ SymbolsPath.Add(folder);
+ if (SymInitialized)
+ {
+ SymModulesDirty = true;
+ }
SymLocker.Unlock();
#endif
@@ -1137,80 +1142,43 @@ Array WindowsPlatform::GetStackFrames(int32 skipCount,
SymInitialized = true;
// Build search path
- const size_t nSymPathLen = 4096;
- SymPath = (char*)malloc(nSymPathLen);
- SymPath[0] = 0;
- strcat_s(SymPath, nSymPathLen, ".;");
- const size_t nTempLen = 1024;
- char szTemp[nTempLen];
-
- // Current directory path
- if (GetCurrentDirectoryA(nTempLen, szTemp) > 0)
+ String symbolSearchPath;
+ TCHAR ModulePath[MAX_PATH] = { 0 };
+ if (::GetModuleFileName(::GetModuleHandle(nullptr), ModulePath, MAX_PATH))
{
- szTemp[nTempLen - 1] = 0;
- strcat_s(SymPath, nSymPathLen, szTemp);
- strcat_s(SymPath, nSymPathLen, ";");
+ symbolSearchPath += StringUtils::GetDirectoryName(ModulePath);
+ symbolSearchPath += ";";
}
-
- // Main module path
- if (GetModuleFileNameA(nullptr, szTemp, nTempLen) > 0)
+ for (auto& path : SymbolsPath)
{
- szTemp[nTempLen - 1] = 0;
- for (char* p = (szTemp + strlen(szTemp) - 1); p >= szTemp; --p)
- {
- // Locate the rightmost path separator
- if ((*p == '\\') || (*p == '/') || (*p == ':'))
- {
- *p = 0;
- break;
- }
- }
- if (strlen(szTemp) > 0)
- {
- strcat_s(SymPath, nSymPathLen, szTemp);
- strcat_s(SymPath, nSymPathLen, ";");
- }
+ symbolSearchPath += path;
+ symbolSearchPath += ";";
}
-
- // System symbols paths
- if (GetEnvironmentVariableA("_NT_SYMBOL_PATH", szTemp, nTempLen) > 0)
+ String _NT_SYMBOL_PATH;
+ if (!Platform::GetEnvironmentVariable(TEXT("_NT_SYMBOL_PATH"), _NT_SYMBOL_PATH))
{
- szTemp[nTempLen - 1] = 0;
- strcat_s(SymPath, nSymPathLen, szTemp);
- strcat_s(SymPath, nSymPathLen, ";");
+ symbolSearchPath += _NT_SYMBOL_PATH;
+ symbolSearchPath += ";";
}
- if (GetEnvironmentVariableA("_NT_ALTERNATE_SYMBOL_PATH", szTemp, nTempLen) > 0)
- {
- szTemp[nTempLen - 1] = 0;
- strcat_s(SymPath, nSymPathLen, szTemp);
- strcat_s(SymPath, nSymPathLen, ";");
- }
- if (GetEnvironmentVariableA("SYSTEMROOT", szTemp, nTempLen) > 0)
- {
- szTemp[nTempLen - 1] = 0;
- strcat_s(SymPath, nSymPathLen, szTemp);
- strcat_s(SymPath, nSymPathLen, ";");
-
- strcat_s(szTemp, nTempLen, "\\system32");
- strcat_s(SymPath, nSymPathLen, szTemp);
- strcat_s(SymPath, nSymPathLen, ";");
- }
-
- SymInitialize(process, SymPath, FALSE);
+ symbolSearchPath += Platform::GetWorkingDirectory();
+ symbolSearchPath += ";";
DWORD options = SymGetOptions();
options |= SYMOPT_LOAD_LINES;
options |= SYMOPT_FAIL_CRITICAL_ERRORS;
+ options |= SYMOPT_DEFERRED_LOADS;
+ options |= SYMOPT_EXACT_SYMBOLS;
SymSetOptions(options);
+
+ SymInitializeW(process, *symbolSearchPath, TRUE);
}
- // Load modules
+ // Refresh modules if needed
if (SymModulesDirty)
{
SymModulesDirty = false;
- GetModuleListPSAPI(process);
+ SymRefreshModuleList(process);
}
- SymRefreshModuleList(process);
// Capture the context if missing
/*EXCEPTION_POINTERS exceptionPointers;
diff --git a/Source/Engine/Platform/WindowsManager.h b/Source/Engine/Platform/WindowsManager.h
index 143322496..7e6800f1d 100644
--- a/Source/Engine/Platform/WindowsManager.h
+++ b/Source/Engine/Platform/WindowsManager.h
@@ -31,13 +31,6 @@ public:
/// Found window or null if cannot find it.
static Window* GetByNativePtr(void* handle);
- ///
- /// Calculates the position for window that has given size and should be placed in the center of the primary screen.
- ///
- /// The size.
- /// window location.
- static Vector2 CalcCenteredWinPos(const Vector2& size);
-
public:
// Used by WindowBase
diff --git a/Source/Engine/Renderer/Utils/BitonicSort.cpp b/Source/Engine/Renderer/Utils/BitonicSort.cpp
index 89313a95d..dc67e5326 100644
--- a/Source/Engine/Renderer/Utils/BitonicSort.cpp
+++ b/Source/Engine/Renderer/Utils/BitonicSort.cpp
@@ -6,10 +6,22 @@
#define INDIRECT_ARGS_STRIDE 12
-BitonicSort::BitonicSort()
- : _dispatchArgsBuffer(nullptr)
+// The sorting keys buffer item structure template. Matches the shader type.
+struct Item
{
-}
+ float Key;
+ uint32 Value;
+};
+
+PACK_STRUCT(struct Data {
+ Item NullItem;
+ uint32 CounterOffset;
+ uint32 MaxIterations;
+ uint32 LoopK;
+ float KeySign;
+ uint32 LoopJ;
+ float Dummy0;
+ });
String BitonicSort::ToString() const
{
diff --git a/Source/Engine/Renderer/Utils/BitonicSort.h b/Source/Engine/Renderer/Utils/BitonicSort.h
index 053cee6ba..caef88078 100644
--- a/Source/Engine/Renderer/Utils/BitonicSort.h
+++ b/Source/Engine/Renderer/Utils/BitonicSort.h
@@ -7,36 +7,15 @@
///
/// Bitonic Sort implementation using GPU compute shaders.
-/// It has a complexity of O(n*(log n)^2), which is inferior to most
-/// traditional sorting algorithms, but because GPUs have so many threads,
-/// and because each thread can be utilized, the algorithm can fully load
-/// the GPU, taking advantage of its high ALU and bandwidth capabilities.
+/// It has a complexity of O(n*(log n)^2), which is inferior to most traditional sorting algorithms, but because GPUs have so many threads,
+/// and because each thread can be utilized, the algorithm can fully load the GPU, taking advantage of its high ALU and bandwidth capabilities.
///
class BitonicSort : public RendererPass
{
-public:
-
- // The sorting keys buffer item structure template. Matches the shader type.
- struct Item
- {
- float Key;
- uint32 Value;
- };
-
private:
- PACK_STRUCT(struct Data {
- Item NullItem;
- uint32 CounterOffset;
- uint32 MaxIterations;
- uint32 LoopK;
- float KeySign;
- uint32 LoopJ;
- float Dummy0;
- });
-
AssetReference _shader;
- GPUBuffer* _dispatchArgsBuffer;
+ GPUBuffer* _dispatchArgsBuffer = nullptr;
GPUConstantBuffer* _cb;
GPUShaderProgramCS* _indirectArgsCS;
GPUShaderProgramCS* _preSortCS;
@@ -44,13 +23,6 @@ private:
GPUShaderProgramCS* _outerSortCS;
GPUShaderProgramCS* _copyIndicesCS;
-public:
-
- ///
- /// Initializes a new instance of the class.
- ///
- BitonicSort();
-
public:
///
diff --git a/Source/Engine/Scripting/InternalCalls/ManagedDictionary.h b/Source/Engine/Scripting/InternalCalls/ManagedDictionary.h
index 215a723ce..6b9743709 100644
--- a/Source/Engine/Scripting/InternalCalls/ManagedDictionary.h
+++ b/Source/Engine/Scripting/InternalCalls/ManagedDictionary.h
@@ -23,15 +23,17 @@ struct FLAXENGINE_API ManagedDictionary
}
template
- static MonoObject* ToManaged(const Dictionary& data, MonoClass* keyType, MonoClass* valueType)
+ static MonoObject* ToManaged(const Dictionary& data, MonoType* keyType, MonoType* valueType)
{
MConverter keysConverter;
MConverter valueConverter;
ManagedDictionary result = New(keyType, valueType);
+ MonoClass* keyClass = mono_type_get_class(keyType);
+ MonoClass* valueClass = mono_type_get_class(valueType);
for (auto i = data.Begin(); i.IsNotEnd(); ++i)
{
- MonoObject* keyManaged = keysConverter.Box(i->Key, keyType);
- MonoObject* valueManaged = valueConverter.Box(i->Value, valueType);
+ MonoObject* keyManaged = keysConverter.Box(i->Key, keyClass);
+ MonoObject* valueManaged = valueConverter.Box(i->Value, valueClass);
result.Add(keyManaged, valueManaged);
}
return result.Instance;
@@ -71,10 +73,11 @@ struct FLAXENGINE_API ManagedDictionary
return result;
}
- static ManagedDictionary New(MonoClass* keyType, MonoClass* valueType)
+ static ManagedDictionary New(MonoType* keyType, MonoType* valueType)
{
ManagedDictionary result;
+ auto domain = mono_domain_get();
auto scriptingClass = Scripting::GetStaticClass();
CHECK_RETURN(scriptingClass, result);
auto makeGenericMethod = scriptingClass->GetMethod("MakeGenericType", 2);
@@ -83,9 +86,9 @@ struct FLAXENGINE_API ManagedDictionary
CHECK_RETURN(createMethod, result);
auto genericType = MUtils::GetType(StdTypesContainer::Instance()->DictionaryClass->GetNative());
- auto genericArgs = mono_array_new(mono_domain_get(), mono_get_object_class(), 2);
- mono_array_set(genericArgs, MonoReflectionType*, 0, MUtils::GetType(keyType));
- mono_array_set(genericArgs, MonoReflectionType*, 1, MUtils::GetType(valueType));
+ auto genericArgs = mono_array_new(domain, mono_get_object_class(), 2);
+ mono_array_set(genericArgs, MonoReflectionType*, 0, mono_type_get_object(domain, keyType));
+ mono_array_set(genericArgs, MonoReflectionType*, 1, mono_type_get_object(domain, valueType));
void* params[2];
params[0] = genericType;
diff --git a/Source/Engine/Scripting/ManagedCLR/MClass.Mono.cpp b/Source/Engine/Scripting/ManagedCLR/MClass.Mono.cpp
index 9e823ea20..21551afc0 100644
--- a/Source/Engine/Scripting/ManagedCLR/MClass.Mono.cpp
+++ b/Source/Engine/Scripting/ManagedCLR/MClass.Mono.cpp
@@ -51,10 +51,12 @@ MClass::MClass(const MAssembly* parentAssembly, MonoClass* monoClass, const MStr
case MONO_TYPE_ATTR_NESTED_ASSEMBLY:
_visibility = MVisibility::Internal;
break;
- case MONO_TYPE_ATTR_NESTED_FAM_AND_ASSEM:
case MONO_TYPE_ATTR_NESTED_FAM_OR_ASSEM:
_visibility = MVisibility::ProtectedInternal;
break;
+ case MONO_TYPE_ATTR_NESTED_FAM_AND_ASSEM:
+ _visibility = MVisibility::PrivateProtected;
+ break;
default:
CRASH;
}
diff --git a/Source/Engine/Scripting/ManagedCLR/MCore.Mono.cpp b/Source/Engine/Scripting/ManagedCLR/MCore.Mono.cpp
index 97f336dc5..fc8f8ee2b 100644
--- a/Source/Engine/Scripting/ManagedCLR/MCore.Mono.cpp
+++ b/Source/Engine/Scripting/ManagedCLR/MCore.Mono.cpp
@@ -510,7 +510,7 @@ bool MCore::LoadEngine()
// Info
char* buildInfo = mono_get_runtime_build_info();
LOG(Info, "Mono version: {0}", String(buildInfo));
- mono_free(buildInfo);
+ mono_free(buildInfo);
return false;
}
diff --git a/Source/Engine/Scripting/ManagedCLR/MField.Mono.cpp b/Source/Engine/Scripting/ManagedCLR/MField.Mono.cpp
index 3ca21be78..cea174462 100644
--- a/Source/Engine/Scripting/ManagedCLR/MField.Mono.cpp
+++ b/Source/Engine/Scripting/ManagedCLR/MField.Mono.cpp
@@ -28,7 +28,7 @@ MField::MField(MonoClassField* monoField, const char* name, MClass* parentClass)
_visibility = MVisibility::Private;
break;
case MONO_FIELD_ATTR_FAM_AND_ASSEM:
- _visibility = MVisibility::ProtectedInternal;
+ _visibility = MVisibility::PrivateProtected;
break;
case MONO_FIELD_ATTR_ASSEMBLY:
_visibility = MVisibility::Internal;
@@ -36,6 +36,9 @@ MField::MField(MonoClassField* monoField, const char* name, MClass* parentClass)
case MONO_FIELD_ATTR_FAMILY:
_visibility = MVisibility::Protected;
break;
+ case MONO_FIELD_ATTR_FAM_OR_ASSEM:
+ _visibility = MVisibility::ProtectedInternal;
+ break;
case MONO_FIELD_ATTR_PUBLIC:
_visibility = MVisibility::Public;
break;
diff --git a/Source/Engine/Scripting/ManagedCLR/MMethod.Mono.cpp b/Source/Engine/Scripting/ManagedCLR/MMethod.Mono.cpp
index 2013cffd7..d1e8a6cef 100644
--- a/Source/Engine/Scripting/ManagedCLR/MMethod.Mono.cpp
+++ b/Source/Engine/Scripting/ManagedCLR/MMethod.Mono.cpp
@@ -34,7 +34,7 @@ MMethod::MMethod(MonoMethod* monoMethod, const char* name, MClass* parentClass)
_visibility = MVisibility::Private;
break;
case MONO_METHOD_ATTR_FAM_AND_ASSEM:
- _visibility = MVisibility::ProtectedInternal;
+ _visibility = MVisibility::PrivateProtected;
break;
case MONO_METHOD_ATTR_ASSEM:
_visibility = MVisibility::Internal;
@@ -42,6 +42,9 @@ MMethod::MMethod(MonoMethod* monoMethod, const char* name, MClass* parentClass)
case MONO_METHOD_ATTR_FAMILY:
_visibility = MVisibility::Protected;
break;
+ case MONO_METHOD_ATTR_FAM_OR_ASSEM:
+ _visibility = MVisibility::ProtectedInternal;
+ break;
case MONO_METHOD_ATTR_PUBLIC:
_visibility = MVisibility::Public;
break;
diff --git a/Source/Engine/Scripting/ManagedCLR/MTypes.h b/Source/Engine/Scripting/ManagedCLR/MTypes.h
index 9ff4062f2..4a79758b4 100644
--- a/Source/Engine/Scripting/ManagedCLR/MTypes.h
+++ b/Source/Engine/Scripting/ManagedCLR/MTypes.h
@@ -62,8 +62,9 @@ class MType;
enum class MVisibility
{
Private,
- Protected,
+ PrivateProtected,
Internal,
+ Protected,
ProtectedInternal,
Public,
};
diff --git a/Source/Engine/Scripting/ManagedCLR/MUtils.h b/Source/Engine/Scripting/ManagedCLR/MUtils.h
index 99e5b5f8f..2eafee53f 100644
--- a/Source/Engine/Scripting/ManagedCLR/MUtils.h
+++ b/Source/Engine/Scripting/ManagedCLR/MUtils.h
@@ -297,6 +297,41 @@ struct MConverter>
}
};
+// Converter for Array.
+template
+struct MConverter>
+{
+ MonoObject* Box(const Array& data, MonoClass* klass)
+ {
+ if (!klass)
+ return nullptr;
+ // TODO: use shared empty arrays cache
+ auto result = mono_array_new(mono_domain_get(), klass, data.Count());
+ MConverter converter;
+ converter.ToManagedArray(result, Span(data.Get(), data.Count()));
+ return (MonoObject*)result;
+ }
+
+ void Unbox(Array& result, MonoObject* data)
+ {
+ auto length = data ? (int32)mono_array_length((MonoArray*)data) : 0;
+ result.EnsureCapacity(length);
+ MConverter converter;
+ converter.ToNativeArray(result, (MonoArray*)data, length);
+ }
+
+ void ToManagedArray(MonoArray* result, const Span>& data)
+ {
+ CRASH; // Not implemented
+ }
+
+ template
+ void ToNativeArray(Array, AllocationType>& result, MonoArray* data, int32 length)
+ {
+ CRASH; // Not implemented
+ }
+};
+
namespace MUtils
{
// Outputs the full typename for the type of the specified object.
diff --git a/Source/Engine/Scripting/Scripting.cpp b/Source/Engine/Scripting/Scripting.cpp
index d53f0a7ab..d5766ed77 100644
--- a/Source/Engine/Scripting/Scripting.cpp
+++ b/Source/Engine/Scripting/Scripting.cpp
@@ -942,7 +942,7 @@ bool initFlaxEngine()
if (exception)
{
MException ex(exception);
- ex.Log(LogType::Fatal, TEXT("FlaxEngine.ClassLibraryInitializer.Init"));
+ ex.Log(LogType::Fatal, TEXT("FlaxEngine.Scripting.Init"));
return true;
}
diff --git a/Source/Engine/Scripting/Scripting.cs b/Source/Engine/Scripting/Scripting.cs
index 6cb04b813..ae7821526 100644
--- a/Source/Engine/Scripting/Scripting.cs
+++ b/Source/Engine/Scripting/Scripting.cs
@@ -158,13 +158,22 @@ namespace FlaxEngine
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
+ Localization.LocalizationChanged += OnLocalizationChanged;
+ OnLocalizationChanged();
if (!Engine.IsEditor)
{
CreateGuiStyle();
}
}
+ private static void OnLocalizationChanged()
+ {
+ var currentThread = Thread.CurrentThread;
+ currentThread.CurrentUICulture = Localization.CurrentLanguage;
+ currentThread.CurrentCulture = Localization.CurrentCulture;
+ }
+
///
/// Sets the managed window as a main game window. Called after creating game window by the native code.
///
diff --git a/Source/Engine/Scripting/ScriptingCalls.h b/Source/Engine/Scripting/ScriptingCalls.h
index 1a48755e8..d76361bee 100644
--- a/Source/Engine/Scripting/ScriptingCalls.h
+++ b/Source/Engine/Scripting/ScriptingCalls.h
@@ -2,6 +2,8 @@
#pragma once
+#include "Engine/Scripting/ManagedCLR/MTypes.h"
+
typedef void (*Thunk_Void_0)(MonoObject** exception);
typedef void (*Thunk_Void_1)(void* param_1, MonoObject** exception);
typedef void (*Thunk_Void_2)(void* param_1, void* param_2, MonoObject** exception);
diff --git a/Source/Engine/Scripting/ScriptingObjectReference.h b/Source/Engine/Scripting/ScriptingObjectReference.h
index eeed0dcc4..fd132d308 100644
--- a/Source/Engine/Scripting/ScriptingObjectReference.h
+++ b/Source/Engine/Scripting/ScriptingObjectReference.h
@@ -318,3 +318,9 @@ public:
OnSet(object);
}
};
+
+template
+uint32 GetHash(const ScriptingObjectReference& key)
+{
+ return GetHash(key.GetID());
+}
diff --git a/Source/Engine/Scripting/SoftObjectReference.h b/Source/Engine/Scripting/SoftObjectReference.h
index b6f08db4a..e03ee81d0 100644
--- a/Source/Engine/Scripting/SoftObjectReference.h
+++ b/Source/Engine/Scripting/SoftObjectReference.h
@@ -326,3 +326,9 @@ public:
OnSet(object);
}
};
+
+template
+uint32 GetHash(const SoftObjectReference& key)
+{
+ return GetHash(key.GetID());
+}
diff --git a/Source/Engine/Serialization/JsonConverters.cs b/Source/Engine/Serialization/JsonConverters.cs
new file mode 100644
index 000000000..2ebf16a79
--- /dev/null
+++ b/Source/Engine/Serialization/JsonConverters.cs
@@ -0,0 +1,331 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+using System;
+using FlaxEngine.GUI;
+using Newtonsoft.Json;
+
+namespace FlaxEngine.Json
+{
+ ///
+ /// Serialize references to the FlaxEngine.Object as Guid.
+ ///
+ ///
+ internal class FlaxObjectConverter : JsonConverter
+ {
+ ///
+ public override unsafe void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ Guid id = Guid.Empty;
+ if (value is Object obj)
+ id = obj.ID;
+ writer.WriteValue(JsonSerializer.GetStringID(&id));
+ }
+
+ ///
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.String)
+ {
+ JsonSerializer.ParseID((string)reader.Value, out var id);
+ return Object.Find(ref id, objectType);
+ }
+ return null;
+ }
+
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ // Skip serialization as reference id for the root object serialization (eg. Script)
+ var cache = JsonSerializer.Current.Value;
+ if (cache != null && cache.IsDuringSerialization && cache.SerializerWriter.SerializeStackSize == 0)
+ {
+ return false;
+ }
+ return typeof(Object).IsAssignableFrom(objectType);
+ }
+ }
+
+ ///
+ /// Serialize SceneReference as Guid in internal format.
+ ///
+ ///
+ internal class SceneReferenceConverter : JsonConverter
+ {
+ ///
+ public override unsafe void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ Guid id = ((SceneReference)value).ID;
+ writer.WriteValue(JsonSerializer.GetStringID(&id));
+ }
+
+ ///
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ SceneReference result = new SceneReference();
+
+ if (reader.TokenType == JsonToken.String)
+ {
+ JsonSerializer.ParseID((string)reader.Value, out result.ID);
+ }
+
+ return result;
+ }
+
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ return objectType == typeof(SceneReference);
+ }
+ }
+
+ ///
+ /// Serialize SoftObjectReference as Guid in internal format.
+ ///
+ ///
+ internal class SoftObjectReferenceConverter : JsonConverter
+ {
+ ///
+ public override unsafe void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ var id = ((SoftObjectReference)value).ID;
+ writer.WriteValue(JsonSerializer.GetStringID(&id));
+ }
+
+ ///
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ var result = new SoftObjectReference();
+ if (reader.TokenType == JsonToken.String)
+ {
+ JsonSerializer.ParseID((string)reader.Value, out var id);
+ result.ID = id;
+ }
+ return result;
+ }
+
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ return objectType == typeof(SoftObjectReference);
+ }
+ }
+
+ ///
+ /// Serialize SoftObjectReference as Guid in internal format.
+ ///
+ ///
+ internal class MarginConverter : JsonConverter
+ {
+ ///
+ public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ var valueMargin = (Margin)value;
+
+ writer.WriteStartObject();
+ {
+ writer.WritePropertyName("Left");
+ writer.WriteValue(valueMargin.Left);
+ writer.WritePropertyName("Right");
+ writer.WriteValue(valueMargin.Right);
+ writer.WritePropertyName("Top");
+ writer.WriteValue(valueMargin.Top);
+ writer.WritePropertyName("Bottom");
+ writer.WriteValue(valueMargin.Bottom);
+ }
+ writer.WriteEndObject();
+ }
+
+ ///
+ public override void WriteJsonDiff(JsonWriter writer, object value, object other, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ var valueMargin = (Margin)value;
+ var otherMargin = (Margin)other;
+ writer.WriteStartObject();
+ if (!Mathf.NearEqual(valueMargin.Left, otherMargin.Left))
+ {
+ writer.WritePropertyName("Left");
+ writer.WriteValue(valueMargin.Left);
+ }
+ if (!Mathf.NearEqual(valueMargin.Right, otherMargin.Right))
+ {
+ writer.WritePropertyName("Right");
+ writer.WriteValue(valueMargin.Right);
+ }
+ if (!Mathf.NearEqual(valueMargin.Top, otherMargin.Top))
+ {
+ writer.WritePropertyName("Top");
+ writer.WriteValue(valueMargin.Top);
+ }
+ if (!Mathf.NearEqual(valueMargin.Bottom, otherMargin.Bottom))
+ {
+ writer.WritePropertyName("Bottom");
+ writer.WriteValue(valueMargin.Bottom);
+ }
+ writer.WriteEndObject();
+ }
+
+ ///
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ var value = (Margin?)existingValue ?? new Margin();
+ if (reader.TokenType == JsonToken.StartObject)
+ {
+ while (reader.Read())
+ {
+ switch (reader.TokenType)
+ {
+ case JsonToken.PropertyName:
+ {
+ var propertyName = (string)reader.Value;
+ var propertyValue = (float)reader.ReadAsDouble();
+ switch (propertyName)
+ {
+ case "Left":
+ value.Left = propertyValue;
+ break;
+ case "Right":
+ value.Right = propertyValue;
+ break;
+ case "Top":
+ value.Top = propertyValue;
+ break;
+ case "Bottom":
+ value.Bottom = propertyValue;
+ break;
+ }
+ break;
+ }
+ case JsonToken.Comment: break;
+ default: return value;
+ }
+ }
+ }
+ return value;
+ }
+
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ return objectType == typeof(Margin);
+ }
+
+ ///
+ public override bool CanRead => true;
+
+ ///
+ public override bool CanWrite => true;
+
+ ///
+ public override bool CanWriteDiff => true;
+ }
+
+ ///
+ /// Serialize LocalizedString as inlined text is not using localization (Id member is empty).
+ ///
+ ///
+ internal class LocalizedStringConverter : JsonConverter
+ {
+ ///
+ public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ var str = (LocalizedString)value;
+ if (string.IsNullOrEmpty(str.Id))
+ {
+ writer.WriteValue(str.Value);
+ }
+ else
+ {
+ writer.WriteStartObject();
+#if FLAX_EDITOR
+ if ((serializer.TypeNameHandling & TypeNameHandling.Objects) == TypeNameHandling.Objects)
+ {
+ writer.WritePropertyName("$type");
+ writer.WriteValue("FlaxEngine.LocalizedString, FlaxEngine.CSharp");
+ }
+#endif
+ writer.WritePropertyName("Id");
+ writer.WriteValue(str.Id);
+ writer.WritePropertyName("Value");
+ writer.WriteValue(str.Value);
+ writer.WriteEndObject();
+ }
+ }
+
+ ///
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ var str = existingValue as LocalizedString ?? new LocalizedString();
+ if (reader.TokenType == JsonToken.String)
+ {
+ str.Id = null;
+ str.Value = (string)reader.Value;
+ }
+ else if (reader.TokenType == JsonToken.StartObject)
+ {
+ while (reader.Read())
+ {
+ switch (reader.TokenType)
+ {
+ case JsonToken.PropertyName:
+ {
+ var propertyName = (string)reader.Value;
+ switch (propertyName)
+ {
+ case "Id":
+ str.Id = reader.ReadAsString();
+ break;
+ case "Value":
+ str.Value = reader.ReadAsString();
+ break;
+ }
+ break;
+ }
+ case JsonToken.Comment: break;
+ default: return str;
+ }
+ }
+ }
+ return str;
+ }
+
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ return objectType == typeof(LocalizedString);
+ }
+ }
+
+ /*
+ ///
+ /// Serialize Guid values using `N` format
+ ///
+ ///
+ internal class GuidConverter : JsonConverter
+ {
+ ///
+ public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ Guid id = (Guid)value;
+ writer.WriteValue(id.ToString("N"));
+ }
+
+ ///
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.String)
+ {
+ var id = Guid.Parse((string)reader.Value);
+ return id;
+ }
+
+ return Guid.Empty;
+ }
+
+ ///
+ public override bool CanConvert(Type objectType)
+ {
+ return objectType == typeof(Guid);
+ }
+ }
+ */
+}
diff --git a/Source/Engine/Serialization/JsonSerializer.cs b/Source/Engine/Serialization/JsonSerializer.cs
index b3bd51d6f..a89ade8ef 100644
--- a/Source/Engine/Serialization/JsonSerializer.cs
+++ b/Source/Engine/Serialization/JsonSerializer.cs
@@ -7,7 +7,6 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
-using FlaxEngine.GUI;
using FlaxEngine.Json.JsonCustomSerializers;
using FlaxEngine.Utilities;
using Newtonsoft.Json;
@@ -16,253 +15,6 @@ using Newtonsoft.Json.Serialization;
namespace FlaxEngine.Json
{
- ///
- /// Serialize references to the FlaxEngine.Object as Guid.
- ///
- ///
- internal class FlaxObjectConverter : JsonConverter
- {
- ///
- public override unsafe void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
- {
- Guid id = Guid.Empty;
- if (value is Object obj)
- id = obj.ID;
- writer.WriteValue(JsonSerializer.GetStringID(&id));
- }
-
- ///
- public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
- {
- if (reader.TokenType == JsonToken.String)
- {
- JsonSerializer.ParseID((string)reader.Value, out var id);
- return Object.Find(ref id, objectType);
- }
- return null;
- }
-
- ///
- public override bool CanConvert(Type objectType)
- {
- // Skip serialization as reference id for the root object serialization (eg. Script)
- var cache = JsonSerializer.Current.Value;
- if (cache != null && cache.IsDuringSerialization && cache.SerializerWriter.SerializeStackSize == 0)
- {
- return false;
- }
- return typeof(Object).IsAssignableFrom(objectType);
- }
- }
-
- ///
- /// Serialize SceneReference as Guid in internal format.
- ///
- ///
- internal class SceneReferenceConverter : JsonConverter
- {
- ///
- public override unsafe void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
- {
- Guid id = ((SceneReference)value).ID;
- writer.WriteValue(JsonSerializer.GetStringID(&id));
- }
-
- ///
- public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
- {
- SceneReference result = new SceneReference();
-
- if (reader.TokenType == JsonToken.String)
- {
- JsonSerializer.ParseID((string)reader.Value, out result.ID);
- }
-
- return result;
- }
-
- ///
- public override bool CanConvert(Type objectType)
- {
- return objectType == typeof(SceneReference);
- }
- }
-
- ///
- /// Serialize SoftObjectReference as Guid in internal format.
- ///
- ///
- internal class SoftObjectReferenceConverter : JsonConverter
- {
- ///
- public override unsafe void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
- {
- var id = ((SoftObjectReference)value).ID;
- writer.WriteValue(JsonSerializer.GetStringID(&id));
- }
-
- ///
- public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
- {
- var result = new SoftObjectReference();
- if (reader.TokenType == JsonToken.String)
- {
- JsonSerializer.ParseID((string)reader.Value, out var id);
- result.ID = id;
- }
- return result;
- }
-
- ///
- public override bool CanConvert(Type objectType)
- {
- return objectType == typeof(SoftObjectReference);
- }
- }
-
- ///
- /// Serialize SoftObjectReference as Guid in internal format.
- ///
- ///
- internal class MarginConverter : JsonConverter
- {
- ///
- public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
- {
- var valueMargin = (Margin)value;
-
- writer.WriteStartObject();
- {
- writer.WritePropertyName("Left");
- writer.WriteValue(valueMargin.Left);
- writer.WritePropertyName("Right");
- writer.WriteValue(valueMargin.Right);
- writer.WritePropertyName("Top");
- writer.WriteValue(valueMargin.Top);
- writer.WritePropertyName("Bottom");
- writer.WriteValue(valueMargin.Bottom);
- }
- writer.WriteEndObject();
- }
-
- ///
- public override void WriteJsonDiff(JsonWriter writer, object value, object other, Newtonsoft.Json.JsonSerializer serializer)
- {
- var valueMargin = (Margin)value;
- var otherMargin = (Margin)other;
- writer.WriteStartObject();
- if (!Mathf.NearEqual(valueMargin.Left, otherMargin.Left))
- {
- writer.WritePropertyName("Left");
- writer.WriteValue(valueMargin.Left);
- }
- if (!Mathf.NearEqual(valueMargin.Right, otherMargin.Right))
- {
- writer.WritePropertyName("Right");
- writer.WriteValue(valueMargin.Right);
- }
- if (!Mathf.NearEqual(valueMargin.Top, otherMargin.Top))
- {
- writer.WritePropertyName("Top");
- writer.WriteValue(valueMargin.Top);
- }
- if (!Mathf.NearEqual(valueMargin.Bottom, otherMargin.Bottom))
- {
- writer.WritePropertyName("Bottom");
- writer.WriteValue(valueMargin.Bottom);
- }
- writer.WriteEndObject();
- }
-
- ///
- public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
- {
- var value = (Margin?)existingValue ?? new Margin();
- if (reader.TokenType == JsonToken.StartObject)
- {
- while (reader.Read())
- {
- switch (reader.TokenType)
- {
- case JsonToken.PropertyName:
- {
- var propertyName = (string)reader.Value;
- var propertyValue = (float)reader.ReadAsDouble();
- switch (propertyName)
- {
- case "Left":
- value.Left = propertyValue;
- break;
- case "Right":
- value.Right = propertyValue;
- break;
- case "Top":
- value.Top = propertyValue;
- break;
- case "Bottom":
- value.Bottom = propertyValue;
- break;
- }
- break;
- }
- case JsonToken.Comment: break;
- default: return value;
- }
- }
- }
- return value;
- }
-
- ///
- public override bool CanConvert(Type objectType)
- {
- return objectType == typeof(Margin);
- }
-
- ///
- public override bool CanRead => true;
-
- ///
- public override bool CanWrite => true;
-
- ///
- public override bool CanWriteDiff => true;
- }
-
- /*
- ///
- /// Serialize Guid values using `N` format
- ///
- ///
- internal class GuidConverter : JsonConverter
- {
- ///
- public override void WriteJson(JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
- {
- Guid id = (Guid)value;
- writer.WriteValue(id.ToString("N"));
- }
-
- ///
- public override object ReadJson(JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
- {
- if (reader.TokenType == JsonToken.String)
- {
- var id = Guid.Parse((string)reader.Value);
- return id;
- }
-
- return Guid.Empty;
- }
-
- ///
- public override bool CanConvert(Type objectType)
- {
- return objectType == typeof(Guid);
- }
- }
- */
-
///
/// Objects serialization tool (json format).
///
@@ -331,6 +83,7 @@ namespace FlaxEngine.Json
settings.Converters.Add(new SoftObjectReferenceConverter());
settings.Converters.Add(new MarginConverter());
settings.Converters.Add(new VersionConverter());
+ settings.Converters.Add(new LocalizedStringConverter());
//settings.Converters.Add(new GuidConverter());
return settings;
}
diff --git a/Source/Engine/Serialization/JsonWriter.h b/Source/Engine/Serialization/JsonWriter.h
index 7182ec69a..ff73e96f0 100644
--- a/Source/Engine/Serialization/JsonWriter.h
+++ b/Source/Engine/Serialization/JsonWriter.h
@@ -11,6 +11,9 @@
#include "Engine/Core/Math/Vector2.h"
#include "Engine/Core/Math/Vector3.h"
#include "Engine/Core/Math/Vector4.h"
+#include "Engine/Core/Math/Int2.h"
+#include "Engine/Core/Math/Int3.h"
+#include "Engine/Core/Math/Int4.h"
#include "Engine/Core/Math/Color.h"
#include "Engine/Core/Math/Quaternion.h"
#include "Engine/Core/Math/Ray.h"
@@ -61,6 +64,12 @@ public:
Key(str.Get(), static_cast(str.Length()));
}
+ FORCE_INLINE void Key(const StringView& str)
+ {
+ const StringAsUTF8<256> buf(*str, str.Length());
+ Key(buf.Get(), buf.Length());
+ }
+
FORCE_INLINE void String(const char* str)
{
String(str, StringUtils::Length(str));
@@ -149,6 +158,42 @@ public:
EndObject();
}
+ void Int2(const Int2& value)
+ {
+ StartObject();
+ JKEY("X");
+ Int(value.X);
+ JKEY("Y");
+ Int(value.Y);
+ EndObject();
+ }
+
+ void Int3(const Int3& value)
+ {
+ StartObject();
+ JKEY("X");
+ Int(value.X);
+ JKEY("Y");
+ Int(value.Y);
+ JKEY("Z");
+ Int(value.Z);
+ EndObject();
+ }
+
+ void Int4(const Int4& value)
+ {
+ StartObject();
+ JKEY("X");
+ Int(value.X);
+ JKEY("Y");
+ Int(value.Y);
+ JKEY("Z");
+ Int(value.Z);
+ JKEY("W");
+ Int(value.W);
+ EndObject();
+ }
+
void Color(const Color& value)
{
StartObject();
diff --git a/Source/Engine/Serialization/Serialization.cpp b/Source/Engine/Serialization/Serialization.cpp
index 7eb48a22c..30cfde962 100644
--- a/Source/Engine/Serialization/Serialization.cpp
+++ b/Source/Engine/Serialization/Serialization.cpp
@@ -138,6 +138,15 @@ void Serialization::Serialize(ISerializable::SerializeStream& stream, const Vari
case VariantType::Vector4:
stream.Vector4(*(Vector4*)v.AsData);
break;
+ case VariantType::Int2:
+ stream.Int2(*(Int2*)v.AsData);
+ break;
+ case VariantType::Int3:
+ stream.Int3(*(Int3*)v.AsData);
+ break;
+ case VariantType::Int4:
+ stream.Int4(*(Int4*)v.AsData);
+ break;
case VariantType::Color:
stream.Color(*(Color*)v.AsData);
break;
@@ -258,6 +267,15 @@ void Serialization::Deserialize(ISerializable::DeserializeStream& stream, Varian
case VariantType::Vector4:
Deserialize(value, *(Vector4*)v.AsData, modifier);
break;
+ case VariantType::Int2:
+ Deserialize(value, *(Int2*)v.AsData, modifier);
+ break;
+ case VariantType::Int3:
+ Deserialize(value, *(Int3*)v.AsData, modifier);
+ break;
+ case VariantType::Int4:
+ Deserialize(value, *(Int4*)v.AsData, modifier);
+ break;
case VariantType::Color:
Deserialize(value, *(Color*)v.AsData, modifier);
break;
@@ -445,6 +463,51 @@ void Serialization::Deserialize(ISerializable::DeserializeStream& stream, Vector
v.W = mW != stream.MemberEnd() ? mW->value.GetFloat() : 0.0f;
}
+bool Serialization::ShouldSerialize(const Int2& v, const void* otherObj)
+{
+ return !otherObj || !(v == *(Int2*)otherObj);
+}
+
+void Serialization::Deserialize(ISerializable::DeserializeStream& stream, Int2& v, ISerializeModifier* modifier)
+{
+ const auto mX = SERIALIZE_FIND_MEMBER(stream, "X");
+ const auto mY = SERIALIZE_FIND_MEMBER(stream, "Y");
+ v.X = mX != stream.MemberEnd() ? mX->value.GetInt() : 0;
+ v.Y = mY != stream.MemberEnd() ? mY->value.GetInt() : 0;
+}
+
+bool Serialization::ShouldSerialize(const Int3& v, const void* otherObj)
+{
+ return !otherObj || !(v == *(Int3*)otherObj);
+}
+
+void Serialization::Deserialize(ISerializable::DeserializeStream& stream, Int3& v, ISerializeModifier* modifier)
+{
+ const auto mX = SERIALIZE_FIND_MEMBER(stream, "X");
+ const auto mY = SERIALIZE_FIND_MEMBER(stream, "Y");
+ const auto mZ = SERIALIZE_FIND_MEMBER(stream, "Z");
+ v.X = mX != stream.MemberEnd() ? mX->value.GetInt() : 0;
+ v.Y = mY != stream.MemberEnd() ? mY->value.GetInt() : 0;
+ v.Z = mZ != stream.MemberEnd() ? mZ->value.GetInt() : 0;
+}
+
+bool Serialization::ShouldSerialize(const Int4& v, const void* otherObj)
+{
+ return !otherObj || !(v == *(Int4*)otherObj);
+}
+
+void Serialization::Deserialize(ISerializable::DeserializeStream& stream, Int4& v, ISerializeModifier* modifier)
+{
+ const auto mX = SERIALIZE_FIND_MEMBER(stream, "X");
+ const auto mY = SERIALIZE_FIND_MEMBER(stream, "Y");
+ const auto mZ = SERIALIZE_FIND_MEMBER(stream, "Z");
+ const auto mW = SERIALIZE_FIND_MEMBER(stream, "W");
+ v.X = mX != stream.MemberEnd() ? mX->value.GetInt() : 0;
+ v.Y = mY != stream.MemberEnd() ? mY->value.GetInt() : 0;
+ v.Z = mZ != stream.MemberEnd() ? mZ->value.GetInt() : 0;
+ v.W = mW != stream.MemberEnd() ? mW->value.GetInt() : 0;
+}
+
bool Serialization::ShouldSerialize(const Quaternion& v, const void* otherObj)
{
return !otherObj || !Quaternion::NearEqual(v, *(Quaternion*)otherObj, SERIALIZE_EPSILON);
diff --git a/Source/Engine/Serialization/Serialization.h b/Source/Engine/Serialization/Serialization.h
index 29642f850..0a2fad106 100644
--- a/Source/Engine/Serialization/Serialization.h
+++ b/Source/Engine/Serialization/Serialization.h
@@ -9,6 +9,7 @@
#include "Engine/Scripting/SoftObjectReference.h"
#include "Engine/Content/AssetReference.h"
#include "Engine/Content/WeakAssetReference.h"
+#include "Engine/Utilities/Encryption.h"
struct Version;
struct VariantType;
@@ -268,6 +269,27 @@ namespace Serialization
}
FLAXENGINE_API void Deserialize(ISerializable::DeserializeStream& stream, Vector4& v, ISerializeModifier* modifier);
+ FLAXENGINE_API bool ShouldSerialize(const Int2& v, const void* otherObj);
+ inline void Serialize(ISerializable::SerializeStream& stream, const Int2& v, const void* otherObj)
+ {
+ stream.Int2(v);
+ }
+ FLAXENGINE_API void Deserialize(ISerializable::DeserializeStream& stream, Int2& v, ISerializeModifier* modifier);
+
+ FLAXENGINE_API bool ShouldSerialize(const Int3& v, const void* otherObj);
+ inline void Serialize(ISerializable::SerializeStream& stream, const Int3& v, const void* otherObj)
+ {
+ stream.Int3(v);
+ }
+ FLAXENGINE_API void Deserialize(ISerializable::DeserializeStream& stream, Int3& v, ISerializeModifier* modifier);
+
+ FLAXENGINE_API bool ShouldSerialize(const Int4& v, const void* otherObj);
+ inline void Serialize(ISerializable::SerializeStream& stream, const Int4& v, const void* otherObj)
+ {
+ stream.Int4(v);
+ }
+ FLAXENGINE_API void Deserialize(ISerializable::DeserializeStream& stream, Int4& v, ISerializeModifier* modifier);
+
FLAXENGINE_API bool ShouldSerialize(const Quaternion& v, const void* otherObj);
inline void Serialize(ISerializable::SerializeStream& stream, const Quaternion& v, const void* otherObj)
{
@@ -501,6 +523,24 @@ namespace Serialization
for (int32 i = 0; i < v.Count(); i++)
Deserialize(streamArray[i], (T&)v[i], modifier);
}
+ template
+ inline void Deserialize(ISerializable::DeserializeStream& stream, Array& v, ISerializeModifier* modifier)
+ {
+ if (stream.IsArray())
+ {
+ const auto& streamArray = stream.GetArray();
+ v.Resize(streamArray.Size());
+ for (int32 i = 0; i < v.Count(); i++)
+ Deserialize(streamArray[i], v[i], modifier);
+ }
+ else if (stream.IsString())
+ {
+ // byte[] encoded as Base64
+ const StringAnsiView streamView(stream.GetString(), stream.GetStringLength());
+ v.Resize(Encryption::Base64DecodeLength(*streamView, streamView.Length()));
+ Encryption::Base64Decode(*streamView, streamView.Length(), v.Get());
+ }
+ }
// Dictionary
diff --git a/Source/Engine/Terrain/TerrainPatch.cpp b/Source/Engine/Terrain/TerrainPatch.cpp
index 133b44c6a..38094fcb7 100644
--- a/Source/Engine/Terrain/TerrainPatch.cpp
+++ b/Source/Engine/Terrain/TerrainPatch.cpp
@@ -2183,6 +2183,9 @@ void TerrainPatch::CreateCollision()
_physicsActor = CPhysX->createRigidStatic(trans);
ASSERT(_physicsActor);
_physicsActor->userData = _terrain;
+#if WITH_PVD
+ _physicsActor->setActorFlag(PxActorFlag::eVISUALIZATION, true);
+#endif
_physicsActor->attachShape(*_physicsShape);
Physics::AddActor(_physicsActor);
diff --git a/Source/Engine/Tools/TextureTool/TextureTool.Build.cs b/Source/Engine/Tools/TextureTool/TextureTool.Build.cs
index 55da51bf5..6d98a0651 100644
--- a/Source/Engine/Tools/TextureTool/TextureTool.Build.cs
+++ b/Source/Engine/Tools/TextureTool/TextureTool.Build.cs
@@ -33,6 +33,7 @@ public class TextureTool : EngineModule
case TargetPlatform.Linux:
case TargetPlatform.PS4:
case TargetPlatform.Android:
+ case TargetPlatform.Switch:
useStb = true;
break;
default: throw new InvalidPlatformException(options.Platform.Target);
diff --git a/Source/Engine/UI/GUI/Common/Button.cs b/Source/Engine/UI/GUI/Common/Button.cs
index 639552ec3..d983e22e0 100644
--- a/Source/Engine/UI/GUI/Common/Button.cs
+++ b/Source/Engine/UI/GUI/Common/Button.cs
@@ -24,11 +24,20 @@ namespace FlaxEngine.GUI
///
protected FontReference _font;
+ ///
+ /// The text.
+ ///
+ protected LocalizedString _text = new LocalizedString();
+
///
/// Button text property.
///
[EditorOrder(10), Tooltip("The button label text.")]
- public string Text { get; set; }
+ public LocalizedString Text
+ {
+ get => _text;
+ set => _text = value;
+ }
///
/// Gets or sets the font used to draw button text.
@@ -201,7 +210,7 @@ namespace FlaxEngine.GUI
Render2D.DrawRectangle(clientRect, borderColor);
// Draw text
- Render2D.DrawText(_font.GetFont(), TextMaterial, Text, clientRect, textColor, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawText(_font.GetFont(), TextMaterial, _text, clientRect, textColor, TextAlignment.Center, TextAlignment.Center);
}
///
diff --git a/Source/Engine/UI/GUI/Common/Dropdown.cs b/Source/Engine/UI/GUI/Common/Dropdown.cs
index 3bb00990f..ea2debb4a 100644
--- a/Source/Engine/UI/GUI/Common/Dropdown.cs
+++ b/Source/Engine/UI/GUI/Common/Dropdown.cs
@@ -77,7 +77,7 @@ namespace FlaxEngine.GUI
///
/// The items.
///
- protected List _items = new List();
+ protected List _items = new List();
///
/// The popup menu. May be null if has not been used yet.
@@ -95,7 +95,7 @@ namespace FlaxEngine.GUI
/// Gets or sets the items collection.
///
[EditorOrder(1), Tooltip("The items collection.")]
- public List Items
+ public List Items
{
get => _items;
set => _items = value;
@@ -107,7 +107,17 @@ namespace FlaxEngine.GUI
[HideInEditor, NoSerialize]
public string SelectedItem
{
- get => _selectedIndex != -1 ? _items[_selectedIndex] : string.Empty;
+ get => _selectedIndex != -1 ? _items[_selectedIndex].ToString() : string.Empty;
+ set => SelectedIndex = _items.IndexOf(value);
+ }
+
+ ///
+ /// Gets or sets the selected item (returns if no item is being selected).
+ ///
+ [HideInEditor, NoSerialize]
+ public LocalizedString SelectedItemLocalized
+ {
+ get => _selectedIndex != -1 ? _items[_selectedIndex] : LocalizedString.Empty;
set => SelectedIndex = _items.IndexOf(value);
}
@@ -265,7 +275,8 @@ namespace FlaxEngine.GUI
/// The items.
public void AddItems(IEnumerable items)
{
- _items.AddRange(items);
+ foreach (var item in items)
+ _items.Add(item);
}
///
@@ -276,7 +287,8 @@ namespace FlaxEngine.GUI
{
SelectedIndex = -1;
_items.Clear();
- _items.AddRange(items);
+ foreach (var item in items)
+ _items.Add(item);
}
///
diff --git a/Source/Engine/UI/GUI/Common/Label.cs b/Source/Engine/UI/GUI/Common/Label.cs
index 196bbb2b6..1b06e1867 100644
--- a/Source/Engine/UI/GUI/Common/Label.cs
+++ b/Source/Engine/UI/GUI/Common/Label.cs
@@ -10,7 +10,11 @@ namespace FlaxEngine.GUI
///
public class Label : ContainerControl
{
- private string _text;
+ ///
+ /// The text.
+ ///
+ protected LocalizedString _text = new LocalizedString();
+
private bool _autoWidth;
private bool _autoHeight;
private bool _autoFitText;
@@ -26,7 +30,7 @@ namespace FlaxEngine.GUI
/// Gets or sets the text.
///
[EditorOrder(10), MultilineText, Tooltip("The label text.")]
- public string Text
+ public LocalizedString Text
{
get => _text;
set
@@ -225,18 +229,7 @@ namespace FlaxEngine.GUI
}
}
- Render2D.DrawText(
- _font.GetFont(),
- Material,
- Text,
- rect,
- color,
- hAlignment,
- wAlignment,
- Wrapping,
- 1.0f,
- scale
- );
+ Render2D.DrawText(_font.GetFont(), Material, _text, rect, color, hAlignment, wAlignment, Wrapping, 1.0f, scale);
if (ClipText)
Render2D.PopClip();
diff --git a/Source/Engine/UI/GUI/Common/ProgressBar.cs b/Source/Engine/UI/GUI/Common/ProgressBar.cs
index 21cce7faa..881bbc161 100644
--- a/Source/Engine/UI/GUI/Common/ProgressBar.cs
+++ b/Source/Engine/UI/GUI/Common/ProgressBar.cs
@@ -39,9 +39,6 @@ namespace FlaxEngine.GUI
///
/// Gets a value indicating whether use progress value smoothing.
///
- ///
- /// true if use progress value smoothing; otherwise, false.
- ///
public bool UseSmoothing => !Mathf.IsZero(SmoothingScale);
///
@@ -91,8 +88,6 @@ namespace FlaxEngine.GUI
if (!Mathf.NearEqual(value, _value))
{
_value = value;
-
- // Check if skip smoothing
if (!UseSmoothing)
{
_current = _value;
@@ -138,22 +133,22 @@ namespace FlaxEngine.GUI
///
public override void Update(float deltaTime)
{
- bool isDeltaSlow = deltaTime > (1 / 20.0f);
-
- // Ensure progress bar is visible
if (Visible)
{
// Value smoothing
+ var value = _value;
if (Mathf.Abs(_current - _value) > 0.01f)
{
// Lerp or not if running slow
- float value;
+ bool isDeltaSlow = deltaTime > (1 / 20.0f);
if (!isDeltaSlow && UseSmoothing)
value = Mathf.Lerp(_current, _value, Mathf.Saturate(deltaTime * 5.0f * SmoothingScale));
- else
- value = _value;
_current = value;
}
+ else
+ {
+ _current = _value;
+ }
}
base.Update(deltaTime);
diff --git a/Source/Engine/UI/GUI/Common/RenderToTextureControl.cs b/Source/Engine/UI/GUI/Common/RenderToTextureControl.cs
index 3894c3027..e2e1532f3 100644
--- a/Source/Engine/UI/GUI/Common/RenderToTextureControl.cs
+++ b/Source/Engine/UI/GUI/Common/RenderToTextureControl.cs
@@ -55,8 +55,9 @@ namespace FlaxEngine.GUI
///
public bool AutomaticInvalidate { get; set; } = true;
+#if FLAX_EDITOR
private bool CanEditTextureSize => !_autoSize;
-
+#endif
///
/// Invalidates the cached image of children controls and invokes the redraw to the texture.
///
@@ -105,7 +106,7 @@ namespace FlaxEngine.GUI
}
///
- public override void DrawSelf()
+ public override void Draw()
{
// Draw cached texture
if (_texture && !_invalid && !_isDuringTextureDraw)
@@ -119,7 +120,7 @@ namespace FlaxEngine.GUI
}
// Draw default UI directly
- base.DrawSelf();
+ base.Draw();
}
///
diff --git a/Source/Engine/UI/GUI/Common/TextBox.cs b/Source/Engine/UI/GUI/Common/TextBox.cs
index 0ed5c731c..20548eed8 100644
--- a/Source/Engine/UI/GUI/Common/TextBox.cs
+++ b/Source/Engine/UI/GUI/Common/TextBox.cs
@@ -9,11 +9,20 @@ namespace FlaxEngine.GUI
{
private TextLayoutOptions _layout;
+ ///
+ /// The watermark text.
+ ///
+ protected LocalizedString _watermarkText;
+
///
/// Gets or sets the watermark text to show grayed when textbox is empty.
///
[EditorOrder(20), Tooltip("The watermark text to show grayed when textbox is empty.")]
- public string WatermarkText { get; set; }
+ public LocalizedString WatermarkText
+ {
+ get => _watermarkText;
+ set => _watermarkText = value;
+ }
///
/// Gets or sets the text wrapping within the control bounds.
@@ -201,9 +210,9 @@ namespace FlaxEngine.GUI
color *= 0.6f;
Render2D.DrawText(font, _text, color, ref _layout, TextMaterial);
}
- else if (!string.IsNullOrEmpty(WatermarkText) && !IsFocused)
+ else if (!string.IsNullOrEmpty(_watermarkText) && !IsFocused)
{
- Render2D.DrawText(font, WatermarkText, WatermarkTextColor, ref _layout, TextMaterial);
+ Render2D.DrawText(font, _watermarkText, WatermarkTextColor, ref _layout, TextMaterial);
}
// Caret
diff --git a/Source/Engine/UI/GUI/Common/TextBoxBase.cs b/Source/Engine/UI/GUI/Common/TextBoxBase.cs
index 2e4ef51e3..ee6aaa7bc 100644
--- a/Source/Engine/UI/GUI/Common/TextBoxBase.cs
+++ b/Source/Engine/UI/GUI/Common/TextBoxBase.cs
@@ -261,6 +261,11 @@ namespace FlaxEngine.GUI
}
}
+ ///
+ /// Gets a value indicating whether user is editing the text.
+ ///
+ public bool IsEditing => _isEditing;
+
///
/// Gets or sets text property.
///
@@ -279,10 +284,11 @@ namespace FlaxEngine.GUI
}
///
- /// Sets the text.
+ /// Sets the text (forced, even if user is editing it).
///
/// The value.
- protected void SetText(string value)
+ [NoAnimate]
+ public void SetText(string value)
{
// Prevent from null problems
if (value == null)
@@ -314,6 +320,18 @@ namespace FlaxEngine.GUI
}
}
+ ///
+ /// Sets the text as it was entered by user (focus, change value, defocus).
+ ///
+ /// The value.
+ [NoAnimate]
+ public void SetTextAsUser(string value)
+ {
+ Focus();
+ SetText(value);
+ Defocus();
+ }
+
///
/// Gets length of the text
///
@@ -504,9 +522,7 @@ namespace FlaxEngine.GUI
if (string.IsNullOrEmpty(clipboardText))
return;
- var right = SelectionRight;
Insert(clipboardText);
- SetSelection(Mathf.Max(right, 0) + clipboardText.Length);
}
///
@@ -622,11 +638,13 @@ namespace FlaxEngine.GUI
{
var left = SelectionLeft >= 0 ? SelectionLeft : 0;
if (HasSelection)
+ {
_text = _text.Remove(left, selectionLength);
-
+ SetSelection(left);
+ }
_text = _text.Insert(left, str);
- SetSelection(left + 1);
+ SetSelection(left + str.Length);
}
OnTextChanged();
@@ -1000,7 +1018,8 @@ namespace FlaxEngine.GUI
///
public override void OnMouseMove(Vector2 location)
{
- // Check if user is selecting
+ base.OnMouseMove(location);
+
if (_isSelecting)
{
// Find char index at current mouse location
@@ -1014,6 +1033,9 @@ namespace FlaxEngine.GUI
///
public override bool OnMouseDown(Vector2 location, MouseButton button)
{
+ if (base.OnMouseDown(location, button))
+ return true;
+
if (button == MouseButton.Left && _text.Length > 0)
{
Focus();
@@ -1050,6 +1072,9 @@ namespace FlaxEngine.GUI
///
public override bool OnMouseUp(Vector2 location, MouseButton button)
{
+ if (base.OnMouseUp(location, button))
+ return true;
+
if (button == MouseButton.Left)
{
OnSelectingEnd();
@@ -1079,6 +1104,8 @@ namespace FlaxEngine.GUI
///
public override bool OnCharInput(char c)
{
+ if (base.OnCharInput(c))
+ return true;
Insert(c);
return true;
}
diff --git a/Source/Engine/UI/GUI/ContainerControl.cs b/Source/Engine/UI/GUI/ContainerControl.cs
index 57d2fb528..3519469a2 100644
--- a/Source/Engine/UI/GUI/ContainerControl.cs
+++ b/Source/Engine/UI/GUI/ContainerControl.cs
@@ -249,6 +249,8 @@ namespace FlaxEngine.GUI
internal void ChangeChildIndex(Control child, int newIndex)
{
int oldIndex = _children.IndexOf(child);
+ if (oldIndex == newIndex)
+ return;
_children.RemoveAt(oldIndex);
// Check if index is invalid
diff --git a/Source/Engine/UI/GUI/Control.Bounds.cs b/Source/Engine/UI/GUI/Control.Bounds.cs
index e4e2eafcc..717b3c4d7 100644
--- a/Source/Engine/UI/GUI/Control.Bounds.cs
+++ b/Source/Engine/UI/GUI/Control.Bounds.cs
@@ -26,11 +26,30 @@ namespace FlaxEngine.GUI
set => Bounds = new Rectangle(X, value, _bounds.Size);
}
+ ///
+ /// Gets or sets the local X coordinate of the pivot of the control relative to the anchor in parent of its container.
+ ///
+ [HideInEditor, NoSerialize]
+ public float LocalX
+ {
+ get => LocalLocation.X;
+ set => LocalLocation = new Vector2(value, LocalLocation.Y);
+ }
+
+ ///
+ /// Gets or sets the local Y coordinate of the pivot of the control relative to the anchor in parent of its container.
+ ///
+ [HideInEditor, NoSerialize]
+ public float LocalY
+ {
+ get => LocalLocation.Y;
+ set => LocalLocation = new Vector2(LocalLocation.X, value);
+ }
+
///
/// Gets or sets the normalized position in the parent control that the upper left corner is anchored to (range 0-1).
///
- [Serialize]
- [HideInEditor, ExpandGroups, Limit(0.0f, 1.0f, 0.01f), EditorDisplay("Transform"), EditorOrder(990), Tooltip("The normalized position in the parent control that the upper left corner is anchored to (range 0-1).")]
+ [Serialize, HideInEditor]
public Vector2 AnchorMin
{
get => _anchorMin;
@@ -49,8 +68,7 @@ namespace FlaxEngine.GUI
///
/// Gets or sets the normalized position in the parent control that the bottom right corner is anchored to (range 0-1).
///
- [Serialize]
- [HideInEditor, ExpandGroups, Limit(0.0f, 1.0f, 0.01f), EditorDisplay("Transform"), EditorOrder(991), Tooltip("The normalized position in the parent control that the bottom right corner is anchored to (range 0-1).")]
+ [Serialize, HideInEditor]
public Vector2 AnchorMax
{
get => _anchorMax;
@@ -69,8 +87,7 @@ namespace FlaxEngine.GUI
///
/// Gets or sets the offsets of the corners of the control relative to its anchors.
///
- [Serialize]
- [HideInEditor, ExpandGroups, EditorDisplay("Transform"), EditorOrder(992), Tooltip("The offsets of the corners of the control relative to its anchors.")]
+ [Serialize, HideInEditor]
public Margin Offsets
{
get => _offsets;
@@ -91,8 +108,8 @@ namespace FlaxEngine.GUI
[NoSerialize, HideInEditor]
internal float Proxy_Offset_Left
{
- get => Offsets.Left;
- set => Offsets = new Margin(value, Offsets.Right, Offsets.Top, Offsets.Bottom);
+ get => _offsets.Left;
+ set => Offsets = new Margin(value, _offsets.Right, _offsets.Top, _offsets.Bottom);
}
///
@@ -101,8 +118,8 @@ namespace FlaxEngine.GUI
[NoSerialize, HideInEditor]
internal float Proxy_Offset_Right
{
- get => Offsets.Right;
- set => Offsets = new Margin(Offsets.Left, value, Offsets.Top, Offsets.Bottom);
+ get => _offsets.Right;
+ set => Offsets = new Margin(_offsets.Left, value, _offsets.Top, _offsets.Bottom);
}
///
@@ -111,8 +128,8 @@ namespace FlaxEngine.GUI
[NoSerialize, HideInEditor]
internal float Proxy_Offset_Top
{
- get => Offsets.Top;
- set => Offsets = new Margin(Offsets.Left, Offsets.Right, value, Offsets.Bottom);
+ get => _offsets.Top;
+ set => Offsets = new Margin(_offsets.Left, _offsets.Right, value, _offsets.Bottom);
}
///
@@ -121,22 +138,31 @@ namespace FlaxEngine.GUI
[NoSerialize, HideInEditor]
internal float Proxy_Offset_Bottom
{
- get => Offsets.Bottom;
- set => Offsets = new Margin(Offsets.Left, Offsets.Right, Offsets.Top, value);
+ get => _offsets.Bottom;
+ set => Offsets = new Margin(_offsets.Left, _offsets.Right, _offsets.Top, value);
}
#endif
///
/// Gets or sets coordinates of the upper-left corner of the control relative to the upper-left corner of its container.
///
- [NoSerialize]
- [HideInEditor, ExpandGroups, EditorDisplay("Transform"), EditorOrder(1000), Tooltip("The location of the upper-left corner of the control relative to he upper-left corner of its container.")]
+ [NoSerialize, HideInEditor]
public Vector2 Location
{
get => _bounds.Location;
set => Bounds = new Rectangle(value, _bounds.Size);
}
+ ///
+ /// Gets or sets the local position of the pivot of the control relative to the anchor in parent of its container.
+ ///
+ [NoSerialize, HideInEditor]
+ public Vector2 LocalLocation
+ {
+ get => _bounds.Location - (_parent != null ? _parent._bounds.Size * (_anchorMax + _anchorMin) * 0.5f : Vector2.Zero) + _bounds.Size * _pivot;
+ set => Bounds = new Rectangle(value + (_parent != null ? _parent.Bounds.Size * (_anchorMax + _anchorMin) * 0.5f : Vector2.Zero) - _bounds.Size * _pivot, _bounds.Size);
+ }
+
///
/// Gets or sets width of the control.
///
@@ -160,8 +186,7 @@ namespace FlaxEngine.GUI
///
/// Gets or sets control's size.
///
- [NoSerialize]
- [HideInEditor, EditorDisplay("Transform"), EditorOrder(1010), Tooltip("The size of the control bounds.")]
+ [NoSerialize, HideInEditor]
public Vector2 Size
{
get => _bounds.Size;
@@ -466,7 +491,8 @@ namespace FlaxEngine.GUI
///
/// The anchor preset to set.
/// True if preserve current control bounds, otherwise will align control position accordingly to the anchor location.
- public void SetAnchorPreset(AnchorPresets anchorPreset, bool preserveBounds)
+ /// Whether or not we should set the pivot too, eg left-top 0,0, bottom-right 1,1
+ public void SetAnchorPreset(AnchorPresets anchorPreset, bool preserveBounds, bool setPivotToo = false)
{
for (int i = 0; i < AnchorPresetsData.Length; i++)
{
@@ -558,6 +584,10 @@ namespace FlaxEngine.GUI
}
SetBounds(ref bounds);
}
+ if (setPivotToo)
+ {
+ Pivot = (anchorMin + anchorMax) / 2;
+ }
_parent?.PerformLayout();
return;
}
diff --git a/Source/Engine/UI/TextRender.cpp b/Source/Engine/UI/TextRender.cpp
index df75bbb87..30335aee3 100644
--- a/Source/Engine/UI/TextRender.cpp
+++ b/Source/Engine/UI/TextRender.cpp
@@ -6,6 +6,7 @@
#include "Engine/Graphics/GPUDevice.h"
#include "Engine/Graphics/Models/Types.h"
#include "Engine/Graphics/RenderView.h"
+#include "Engine/Graphics/RenderTask.h"
#include "Engine/Level/Scene/SceneRendering.h"
#include "Engine/Render2D/Font.h"
#include "Engine/Render2D/FontAsset.h"
@@ -16,7 +17,7 @@
#include "Engine/Content/Assets/MaterialInstance.h"
#include "Engine/Content/Content.h"
#include "Engine/Core/Types/Variant.h"
-#include "Engine/Graphics/RenderTask.h"
+#include "Engine/Localization/Localization.h"
#if USE_EDITOR
#include "Editor/Editor.h"
#endif
@@ -45,7 +46,12 @@ TextRender::TextRender(const SpawnParams& params)
Material.Changed.Bind(this);
}
-void TextRender::SetText(const StringView& value)
+const LocalizedString& TextRender::GetText() const
+{
+ return _text;
+}
+
+void TextRender::SetText(const LocalizedString& value)
{
if (_text != value)
{
@@ -54,6 +60,11 @@ void TextRender::SetText(const StringView& value)
}
}
+Color TextRender::GetColor() const
+{
+ return _color;
+}
+
void TextRender::SetColor(const Color& value)
{
if (_color != value)
@@ -63,6 +74,11 @@ void TextRender::SetColor(const Color& value)
}
}
+int32 TextRender::GetFontSize() const
+{
+ return _size;
+}
+
void TextRender::SetFontSize(int32 value)
{
value = Math::Clamp(value, 1, 1024);
@@ -84,9 +100,6 @@ void TextRender::SetLayoutOptions(TextLayoutOptions& value)
void TextRender::UpdateLayout()
{
- if (!_isDirty)
- return;
-
// Clear
_ib.Clear();
_vb0.Clear();
@@ -111,8 +124,28 @@ void TextRender::UpdateLayout()
_isDirty = false;
// Skip if no need to calculate the layout
- if (_text.IsEmpty())
- return;
+ String textData;
+ String* textPtr = &_text.Value;
+ if (textPtr->IsEmpty())
+ {
+ if (_text.Id.IsEmpty())
+ return;
+ textData = Localization::GetString(_text.Id);
+ textPtr = &textData;
+ if (!_isLocalized)
+ {
+ _isLocalized = true;
+ Localization::LocalizationChanged.Bind(this);
+ }
+ if (textPtr->IsEmpty())
+ return;
+ }
+ else if (_isLocalized)
+ {
+ _isLocalized = false;
+ Localization::LocalizationChanged.Unbind(this);
+ }
+ const String& text = *textPtr;
// Pick a font (remove DPI text scale as the text is being placed in the world)
auto font = Font->CreateFont(_size);
@@ -126,13 +159,13 @@ void TextRender::UpdateLayout()
// Perform layout
Array lines;
- font->ProcessText(_text, lines, _layoutOptions);
+ font->ProcessText(text, lines, _layoutOptions);
// Prepare buffers capacity
- _ib.Data.EnsureCapacity(_text.Length() * 6 * sizeof(uint16));
- _vb0.Data.EnsureCapacity(_text.Length() * 4 * sizeof(VB0ElementType));
- _vb1.Data.EnsureCapacity(_text.Length() * 4 * sizeof(VB1ElementType));
- _vb2.Data.EnsureCapacity(_text.Length() * 4 * sizeof(VB2ElementType));
+ _ib.Data.EnsureCapacity(text.Length() * 6 * sizeof(uint16));
+ _vb0.Data.EnsureCapacity(text.Length() * 4 * sizeof(VB0ElementType));
+ _vb1.Data.EnsureCapacity(text.Length() * 4 * sizeof(VB1ElementType));
+ _vb2.Data.EnsureCapacity(text.Length() * 4 * sizeof(VB2ElementType));
_buffersDirty = true;
// Init draw chunks data
@@ -155,7 +188,7 @@ void TextRender::UpdateLayout()
// Render all characters from the line
for (int32 charIndex = line.FirstCharIndex; charIndex <= line.LastCharIndex; charIndex++)
{
- const Char c = _text[charIndex];
+ const Char c = text[charIndex];
if (c != '\n')
{
font->GetCharacter(c, entry);
@@ -198,7 +231,7 @@ void TextRender::UpdateLayout()
const auto param = drawChunk.Material->Params.Get(FontParamName);
if (param && param->GetParameterType() == MaterialParameterType::Texture)
{
- param->SetValue(fontAtlas);
+ param->SetValue(Variant(fontAtlas));
param->SetIsOverride(true);
}
}
@@ -305,7 +338,10 @@ bool TextRender::HasContentLoaded() const
void TextRender::Draw(RenderContext& renderContext)
{
- UpdateLayout();
+ if (_isDirty)
+ {
+ UpdateLayout();
+ }
GEOMETRY_DRAW_STATE_EVENT_BEGIN(_drawState, _world);
@@ -449,11 +485,19 @@ void TextRender::OnEnable()
// Base
Actor::OnEnable();
- UpdateLayout();
+ if (_isDirty)
+ {
+ UpdateLayout();
+ }
}
void TextRender::OnDisable()
{
+ if (_isLocalized)
+ {
+ _isLocalized = false;
+ Localization::LocalizationChanged.Unbind(this);
+ }
GetSceneRendering()->RemoveGeometry(this);
// Base
diff --git a/Source/Engine/UI/TextRender.h b/Source/Engine/UI/TextRender.h
index 07bfcfbe0..fff3915a5 100644
--- a/Source/Engine/UI/TextRender.h
+++ b/Source/Engine/UI/TextRender.h
@@ -11,6 +11,7 @@
#include "Engine/Content/Assets/MaterialInstance.h"
#include "Engine/Graphics/DynamicBuffer.h"
#include "Engine/Graphics/Models/Config.h"
+#include "Engine/Localization/LocalizedString.h"
#if USE_PRECISE_MESH_INTERSECTS
#include "Engine/Graphics/Models/CollisionProxy.h"
#endif
@@ -34,7 +35,8 @@ private:
bool _isDirty = false;
bool _buffersDirty = false;
- String _text;
+ bool _isLocalized = false;
+ LocalizedString _text;
Color _color;
TextLayoutOptions _layoutOptions;
int32 _size;
@@ -56,25 +58,19 @@ public:
///
/// Gets the text.
///
- API_PROPERTY(Attributes="EditorOrder(0), DefaultValue(\"\"), MultilineText, EditorDisplay(\"Text\")")
- FORCE_INLINE const String& GetText() const
- {
- return _text;
- }
+ API_PROPERTY(Attributes="EditorOrder(0), EditorDisplay(\"Text\")")
+ const LocalizedString& GetText() const;
///
/// Sets the text.
///
- API_PROPERTY() void SetText(const StringView& value);
+ API_PROPERTY() void SetText(const LocalizedString& value);
///
/// Gets the color of the text.
///
API_PROPERTY(Attributes="EditorOrder(10), DefaultValue(typeof(Color), \"1,1,1,1\"), EditorDisplay(\"Text\")")
- FORCE_INLINE Color GetColor() const
- {
- return _color;
- }
+ Color GetColor() const;
///
/// Sets the color of the text.
@@ -97,10 +93,7 @@ public:
/// Gets the font characters size.
///
API_PROPERTY(Attributes="EditorOrder(40), DefaultValue(32), Limit(1, 1000), EditorDisplay(\"Text\")")
- FORCE_INLINE int32 GetFontSize() const
- {
- return _size;
- }
+ int32 GetFontSize() const;
///
/// Sets the font characters size.
@@ -123,7 +116,7 @@ public:
/// Gets the layout options. Layout is defined in local space of the object (on XY plane).
///
API_PROPERTY(Attributes="EditorOrder(100), EditorDisplay(\"Text\")")
- FORCE_INLINE TextLayoutOptions GetLayoutOptions() const
+ FORCE_INLINE const TextLayoutOptions& GetLayoutOptions() const
{
return _layoutOptions;
}
diff --git a/Source/Engine/UI/UI.Build.cs b/Source/Engine/UI/UI.Build.cs
index 86c6f23c8..b72b7ca01 100644
--- a/Source/Engine/UI/UI.Build.cs
+++ b/Source/Engine/UI/UI.Build.cs
@@ -1,10 +1,18 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
using Flax.Build;
+using Flax.Build.NativeCpp;
///
/// User Interface module.
///
public class UI : EngineModule
{
+ ///
+ public override void Setup(BuildOptions options)
+ {
+ base.Setup(options);
+
+ options.PublicDependencies.Add("Localization");
+ }
}
diff --git a/Source/Engine/UI/UICanvas.cpp b/Source/Engine/UI/UICanvas.cpp
index c21281c67..3d6310ee4 100644
--- a/Source/Engine/UI/UICanvas.cpp
+++ b/Source/Engine/UI/UICanvas.cpp
@@ -14,6 +14,9 @@ MMethod* UICanvas_Deserialize = nullptr;
MMethod* UICanvas_PostDeserialize = nullptr;
MMethod* UICanvas_OnEnable = nullptr;
MMethod* UICanvas_OnDisable = nullptr;
+#if USE_EDITOR
+MMethod* UICanvas_OnActiveInTreeChanged = nullptr;
+#endif
MMethod* UICanvas_EndPlay = nullptr;
MMethod* UICanvas_ParentChanged = nullptr;
@@ -43,6 +46,9 @@ UICanvas::UICanvas(const SpawnParams& params)
UICanvas_PostDeserialize = mclass->GetMethod("PostDeserialize");
UICanvas_OnEnable = mclass->GetMethod("OnEnable");
UICanvas_OnDisable = mclass->GetMethod("OnDisable");
+#if USE_EDITOR
+ UICanvas_OnActiveInTreeChanged = mclass->GetMethod("OnActiveInTreeChanged");
+#endif
UICanvas_EndPlay = mclass->GetMethod("EndPlay");
UICanvas_ParentChanged = mclass->GetMethod("ParentChanged");
}
@@ -167,3 +173,15 @@ void UICanvas::OnTransformChanged()
_box = BoundingBox(_transform.Translation);
_sphere = BoundingSphere(_transform.Translation, 0.0f);
}
+
+#if USE_EDITOR
+
+void UICanvas::OnActiveInTreeChanged()
+{
+ UICANVAS_INVOKE(OnActiveInTreeChanged);
+
+ // Base
+ Actor::OnActiveInTreeChanged();
+}
+
+#endif
diff --git a/Source/Engine/UI/UICanvas.cs b/Source/Engine/UI/UICanvas.cs
index 4030b66b9..fdb413837 100644
--- a/Source/Engine/UI/UICanvas.cs
+++ b/Source/Engine/UI/UICanvas.cs
@@ -428,7 +428,10 @@ namespace FlaxEngine
}
#if FLAX_EDITOR
if (_editorRoot != null && IsActiveInHierarchy)
+ {
_guiRoot.Parent = _editorRoot;
+ _guiRoot.IndexInParent = 0;
+ }
#endif
if (_isRegisteredForTick)
{
@@ -637,6 +640,7 @@ namespace FlaxEngine
if (RenderMode == CanvasRenderMode.ScreenSpace && _editorRoot != null && _guiRoot != null)
{
_guiRoot.Parent = HasParent && IsActiveInHierarchy ? _editorRoot : null;
+ _guiRoot.IndexInParent = 0;
}
#endif
}
@@ -644,7 +648,15 @@ namespace FlaxEngine
internal void OnEnable()
{
#if FLAX_EDITOR
- _guiRoot.Parent = _editorRoot ?? RootControl.CanvasRoot;
+ if (_editorRoot != null)
+ {
+ _guiRoot.Parent = _editorRoot;
+ _guiRoot.IndexInParent = 0;
+ }
+ else
+ {
+ _guiRoot.Parent = RootControl.CanvasRoot;
+ }
#else
_guiRoot.Parent = RootControl.CanvasRoot;
#endif
@@ -672,6 +684,17 @@ namespace FlaxEngine
}
}
+#if FLAX_EDITOR
+ internal void OnActiveInTreeChanged()
+ {
+ if (RenderMode == CanvasRenderMode.ScreenSpace && _editorRoot != null && _guiRoot != null)
+ {
+ _guiRoot.Parent = HasParent && IsActiveInHierarchy ? _editorRoot : null;
+ _guiRoot.IndexInParent = 0;
+ }
+ }
+#endif
+
internal void EndPlay()
{
if (_isRegisteredForTick)
@@ -707,7 +730,10 @@ namespace FlaxEngine
Setup();
if (RenderMode == CanvasRenderMode.ScreenSpace && _editorRoot != null && _guiRoot != null && IsActiveInHierarchy)
+ {
_guiRoot.Parent = _editorRoot;
+ _guiRoot.IndexInParent = 0;
+ }
}
#endif
}
diff --git a/Source/Engine/UI/UICanvas.h b/Source/Engine/UI/UICanvas.h
index cb049c684..4980f7d28 100644
--- a/Source/Engine/UI/UICanvas.h
+++ b/Source/Engine/UI/UICanvas.h
@@ -28,4 +28,7 @@ protected:
void OnEnable() override;
void OnDisable() override;
void OnTransformChanged() final override;
+#if USE_EDITOR
+ void OnActiveInTreeChanged() override;
+#endif
};
diff --git a/Source/Engine/UI/UIControl.cs b/Source/Engine/UI/UIControl.cs
index b8f8b00dd..d981c1b6c 100644
--- a/Source/Engine/UI/UIControl.cs
+++ b/Source/Engine/UI/UIControl.cs
@@ -52,7 +52,6 @@ namespace FlaxEngine
_control.Parent = GetParent();
_control.IndexInParent = OrderInParent;
_control.Location = new Vector2(LocalPosition);
- // TODO: sync control order in parent with actor order in parent (think about special cases like Panel with scroll bars used as internal controls)
_control.LocationChanged += OnControlLocationChanged;
// Link children UI controls
@@ -353,6 +352,7 @@ namespace FlaxEngine
if (_control != null)
{
_control.Parent = GetParent();
+ _control.IndexInParent = OrderInParent;
}
}
diff --git a/Source/Engine/Utilities/Extensions.cs b/Source/Engine/Utilities/Extensions.cs
index 3eb31e1d2..0fc46efe7 100644
--- a/Source/Engine/Utilities/Extensions.cs
+++ b/Source/Engine/Utilities/Extensions.cs
@@ -44,6 +44,21 @@ namespace FlaxEngine.Utilities
}
}
+ ///
+ /// Checks if the text is multiline.
+ ///
+ /// Text to check.
+ /// True if text is a multiline, otherwise false.
+ public static bool IsMultiline(this string str)
+ {
+ for (int i = 0; i < str.Length; i++)
+ {
+ if (str[i] == '\n')
+ return true;
+ }
+ return false;
+ }
+
///
/// Splits string into lines
///
diff --git a/Source/Engine/Utilities/Utils.cs b/Source/Engine/Utilities/Utils.cs
index a72b4e676..ab4fdf17b 100644
--- a/Source/Engine/Utilities/Utils.cs
+++ b/Source/Engine/Utilities/Utils.cs
@@ -240,6 +240,36 @@ namespace FlaxEngine
return new Vector4(stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle());
}
+ ///
+ /// Reads the Int2 from the binary stream.
+ ///
+ /// The stream.
+ /// The value.
+ public static Int2 ReadInt2(this BinaryReader stream)
+ {
+ return new Int2(stream.ReadInt32(), stream.ReadInt32());
+ }
+
+ ///
+ /// Reads the Int3 from the binary stream.
+ ///
+ /// The stream.
+ /// The value.
+ public static Int3 ReadInt3(this BinaryReader stream)
+ {
+ return new Int3(stream.ReadInt32(), stream.ReadInt32(), stream.ReadInt32());
+ }
+
+ ///
+ /// Reads the Int4 from the binary stream.
+ ///
+ /// The stream.
+ /// The value.
+ public static Int4 ReadInt4(this BinaryReader stream)
+ {
+ return new Int4(stream.ReadInt32(), stream.ReadInt32(), stream.ReadInt32(), stream.ReadInt32());
+ }
+
///
/// Reads the Quaternion from the binary stream.
///
@@ -362,6 +392,42 @@ namespace FlaxEngine
stream.Write(value.W);
}
+ ///
+ /// Writes the Int2 to the binary stream.
+ ///
+ /// The stream.
+ /// The value to write.
+ public static void Write(this BinaryWriter stream, Int2 value)
+ {
+ stream.Write(value.X);
+ stream.Write(value.Y);
+ }
+
+ ///
+ /// Writes the Int3 to the binary stream.
+ ///
+ /// The stream.
+ /// The value to write.
+ public static void Write(this BinaryWriter stream, Int3 value)
+ {
+ stream.Write(value.X);
+ stream.Write(value.Y);
+ stream.Write(value.Z);
+ }
+
+ ///
+ /// Writes the Int4 to the binary stream.
+ ///
+ /// The stream.
+ /// The value to write.
+ public static void Write(this BinaryWriter stream, Int4 value)
+ {
+ stream.Write(value.X);
+ stream.Write(value.Y);
+ stream.Write(value.Z);
+ stream.Write(value.W);
+ }
+
///
/// Writes the Quaternion to the binary stream.
///
diff --git a/Source/Engine/Visject/ShaderGraph.cpp b/Source/Engine/Visject/ShaderGraph.cpp
index c3669855c..754c1aac9 100644
--- a/Source/Engine/Visject/ShaderGraph.cpp
+++ b/Source/Engine/Visject/ShaderGraph.cpp
@@ -767,6 +767,7 @@ void ShaderGenerator::ProcessGroupTools(Box* box, Node* node, Value& value)
PLATFORM_CASE(6, "PLATFORM_PS4");
PLATFORM_CASE(7, "PLATFORM_XBOX_SCARLETT");
PLATFORM_CASE(8, "PLATFORM_ANDROID");
+ PLATFORM_CASE(9, "PLATFORM_SWITCH");
#undef PLATFORM_CASE
break;
}
diff --git a/Source/Engine/Visject/VisjectGraph.cpp b/Source/Engine/Visject/VisjectGraph.cpp
index 49885887f..fcba6c8b7 100644
--- a/Source/Engine/Visject/VisjectGraph.cpp
+++ b/Source/Engine/Visject/VisjectGraph.cpp
@@ -714,6 +714,9 @@ void VisjectExecutor::ProcessGroupTools(Box* box, Node* node, Value& value)
case PlatformType::Android:
boxId = 8;
break;
+ case PlatformType::Switch:
+ boxId = 9;
+ break;
default: ;
}
value = tryGetValue(node->GetBox(node->GetBox(boxId)->HasConnection() ? boxId : 1), Value::Zero);
diff --git a/Source/FlaxEngine.Gen.cs b/Source/FlaxEngine.Gen.cs
index 6f8878d25..62d40ad9a 100644
--- a/Source/FlaxEngine.Gen.cs
+++ b/Source/FlaxEngine.Gen.cs
@@ -13,5 +13,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("b8442186-4a70-7c85-704a-857c262d00f6")]
-[assembly: AssemblyVersion("1.1.6217")]
-[assembly: AssemblyFileVersion("1.1.6217")]
+[assembly: AssemblyVersion("1.1.6218")]
+[assembly: AssemblyFileVersion("1.1.6218")]
diff --git a/Source/FlaxEngine.Gen.h b/Source/FlaxEngine.Gen.h
index 7a888ae1f..eff8449cc 100644
--- a/Source/FlaxEngine.Gen.h
+++ b/Source/FlaxEngine.Gen.h
@@ -3,11 +3,11 @@
#pragma once
#define FLAXENGINE_NAME "FlaxEngine"
-#define FLAXENGINE_VERSION Version(1, 1, 6217)
-#define FLAXENGINE_VERSION_TEXT "1.1.6217"
+#define FLAXENGINE_VERSION Version(1, 1, 6218)
+#define FLAXENGINE_VERSION_TEXT "1.1.6218"
#define FLAXENGINE_VERSION_MAJOR 1
#define FLAXENGINE_VERSION_MINOR 1
-#define FLAXENGINE_VERSION_BUILD 6217
+#define FLAXENGINE_VERSION_BUILD 6218
#define FLAXENGINE_COMPANY "Flax"
#define FLAXENGINE_COPYRIGHT "Copyright (c) 2012-2021 Wojciech Figat. All rights reserved."
diff --git a/Source/Platforms/UWP/Binaries/Newtonsoft.Json.pdb b/Source/Platforms/UWP/Binaries/Newtonsoft.Json.pdb
deleted file mode 100644
index ae45100f6..000000000
--- a/Source/Platforms/UWP/Binaries/Newtonsoft.Json.pdb
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:b999346525f40ccb72ecbc560462d94c8c2cce6fa515722b8f2a53f0fa334b4f
-size 236420
diff --git a/Source/Platforms/UWP/Binaries/Newtonsoft.Json.xml b/Source/Platforms/UWP/Binaries/Newtonsoft.Json.xml
deleted file mode 100644
index 5e472c8a0..000000000
--- a/Source/Platforms/UWP/Binaries/Newtonsoft.Json.xml
+++ /dev/null
@@ -1,10588 +0,0 @@
-
-
-
- Newtonsoft.Json
-
-
-
-
- Represents a BSON Oid (object id).
-
-
-
-
- Gets or sets the value of the Oid.
-
- The value of the Oid.
-
-
-
- Initializes a new instance of the class.
-
- The Oid value.
-
-
-
- Represents a reader that provides fast, non-cached, forward-only access to serialized BSON data.
-
-
-
-
- Gets or sets a value indicating whether binary data reading should be compatible with incorrect Json.NET 3.5 written binary.
-
-
- true if binary data reading will be compatible with incorrect Json.NET 3.5 written binary; otherwise, false.
-
-
-
-
- Gets or sets a value indicating whether the root object will be read as a JSON array.
-
-
- true if the root object will be read as a JSON array; otherwise, false.
-
-
-
-
- Gets or sets the used when reading values from BSON.
-
- The used when reading values from BSON.
-
-
-
- Initializes a new instance of the class.
-
- The containing the BSON data to read.
-
-
-
- Initializes a new instance of the class.
-
- The containing the BSON data to read.
-
-
-
- Initializes a new instance of the class.
-
- The containing the BSON data to read.
- if set to true the root object will be read as a JSON array.
- The used when reading values from BSON.
-
-
-
- Initializes a new instance of the class.
-
- The containing the BSON data to read.
- if set to true the root object will be read as a JSON array.
- The used when reading values from BSON.
-
-
-
- Reads the next JSON token from the underlying .
-
-
- true if the next token was read successfully; false if there are no more tokens to read.
-
-
-
-
- Changes the reader's state to .
- If is set to true, the underlying is also closed.
-
-
-
-
- Represents a writer that provides a fast, non-cached, forward-only way of generating BSON data.
-
-
-
-
- Gets or sets the used when writing values to BSON.
- When set to no conversion will occur.
-
- The used when writing values to BSON.
-
-
-
- Initializes a new instance of the class.
-
- The to write to.
-
-
-
- Initializes a new instance of the class.
-
- The to write to.
-
-
-
- Flushes whatever is in the buffer to the underlying and also flushes the underlying stream.
-
-
-
-
- Writes the end.
-
- The token.
-
-
-
- Writes a comment /*...*/ containing the specified text.
-
- Text to place inside the comment.
-
-
-
- Writes the start of a constructor with the given name.
-
- The name of the constructor.
-
-
-
- Writes raw JSON.
-
- The raw JSON to write.
-
-
-
- Writes raw JSON where a value is expected and updates the writer's state.
-
- The raw JSON to write.
-
-
-
- Writes the beginning of a JSON array.
-
-
-
-
- Writes the beginning of a JSON object.
-
-
-
-
- Writes the property name of a name/value pair on a JSON object.
-
- The name of the property.
-
-
-
- Closes this writer.
- If is set to true, the underlying is also closed.
- If is set to true, the JSON is auto-completed.
-
-
-
-
- Writes a value.
- An error will raised if the value cannot be written as a single JSON token.
-
- The value to write.
-
-
-
- Writes a null value.
-
-
-
-
- Writes an undefined value.
-
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a [] value.
-
- The [] value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a [] value that represents a BSON object id.
-
- The Object ID value to write.
-
-
-
- Writes a BSON regex.
-
- The regex pattern.
- The regex options.
-
-
-
- Specifies how constructors are used when initializing objects during deserialization by the .
-
-
-
-
- First attempt to use the public default constructor, then fall back to a single parameterized constructor, then to the non-public default constructor.
-
-
-
-
- Json.NET will use a non-public default constructor before falling back to a parameterized constructor.
-
-
-
-
- Converts a binary value to and from a base 64 string value.
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Converts a to and from JSON and BSON.
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Creates a custom object.
-
- The object type to convert.
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Creates an object which will then be populated by the serializer.
-
- Type of the object.
- The created object.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Gets a value indicating whether this can write JSON.
-
-
- true if this can write JSON; otherwise, false.
-
-
-
-
- Provides a base class for converting a to and from JSON.
-
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Converts an to and from JSON.
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Gets a value indicating whether this can write JSON.
-
-
- true if this can write JSON; otherwise, false.
-
-
-
-
- Converts a to and from the ISO 8601 date format (e.g. "2008-04-12T12:53Z").
-
-
-
-
- Gets or sets the date time styles used when converting a date to and from JSON.
-
- The date time styles used when converting a date to and from JSON.
-
-
-
- Gets or sets the date time format used when converting a date to and from JSON.
-
- The date time format used when converting a date to and from JSON.
-
-
-
- Gets or sets the culture used when converting a date to and from JSON.
-
- The culture used when converting a date to and from JSON.
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Converts a to and from a JavaScript Date constructor (e.g. new Date(52231943)).
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing property value of the JSON that is being converted.
- The calling serializer.
- The object value.
-
-
-
- Converts a to and from JSON.
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Converts a to and from JSON and BSON.
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Converts an to and from its name string value.
-
-
-
-
- Gets or sets a value indicating whether the written enum text should be camel case.
- The default value is false.
-
- true if the written enum text will be camel case; otherwise, false.
-
-
-
- Gets or sets a value indicating whether integer values are allowed when deserializing.
- The default value is true.
-
- true if integers are allowed when deserializing; otherwise, false.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class.
-
- true if the written enum text will be camel case; otherwise, false.
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Converts a to and from Unix epoch time
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing property value of the JSON that is being converted.
- The calling serializer.
- The object value.
-
-
-
- Converts a to and from a string (e.g. "1.2.3.4").
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing property value of the JSON that is being converted.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Converts XML to and from JSON.
-
-
-
-
- Gets or sets the name of the root element to insert when deserializing to XML if the JSON structure has produced multiple root elements.
-
- The name of the deserialized root element.
-
-
-
- Gets or sets a flag to indicate whether to write the Json.NET array attribute.
- This attribute helps preserve arrays when converting the written XML back to JSON.
-
- true if the array attribute is written to the XML; otherwise, false.
-
-
-
- Gets or sets a value indicating whether to write the root JSON object.
-
- true if the JSON root object is omitted; otherwise, false.
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The calling serializer.
- The value.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Checks if the is a namespace attribute.
-
- Attribute name to test.
- The attribute name prefix if it has one, otherwise an empty string.
- true if attribute name is for a namespace attribute, otherwise false.
-
-
-
- Determines whether this instance can convert the specified value type.
-
- Type of the value.
-
- true if this instance can convert the specified value type; otherwise, false.
-
-
-
-
- Specifies how dates are formatted when writing JSON text.
-
-
-
-
- Dates are written in the ISO 8601 format, e.g. "2012-03-21T05:40Z".
-
-
-
-
- Dates are written in the Microsoft JSON format, e.g. "\/Date(1198908717056)\/".
-
-
-
-
- Specifies how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON text.
-
-
-
-
- Date formatted strings are not parsed to a date type and are read as strings.
-
-
-
-
- Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to .
-
-
-
-
- Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to .
-
-
-
-
- Specifies how to treat the time value when converting between string and .
-
-
-
-
- Treat as local time. If the object represents a Coordinated Universal Time (UTC), it is converted to the local time.
-
-
-
-
- Treat as a UTC. If the object represents a local time, it is converted to a UTC.
-
-
-
-
- Treat as a local time if a is being converted to a string.
- If a string is being converted to , convert to a local time if a time zone is specified.
-
-
-
-
- Time zone information should be preserved when converting.
-
-
-
-
- Specifies default value handling options for the .
-
-
-
-
-
-
-
-
- Include members where the member value is the same as the member's default value when serializing objects.
- Included members are written to JSON. Has no effect when deserializing.
-
-
-
-
- Ignore members where the member value is the same as the member's default value when serializing objects
- so that it is not written to JSON.
- This option will ignore all default values (e.g. null for objects and nullable types; 0 for integers,
- decimals and floating point numbers; and false for booleans). The default value ignored can be changed by
- placing the on the property.
-
-
-
-
- Members with a default value but no JSON will be set to their default value when deserializing.
-
-
-
-
- Ignore members where the member value is the same as the member's default value when serializing objects
- and set members to their default value when deserializing.
-
-
-
-
- Specifies float format handling options when writing special floating point numbers, e.g. ,
- and with .
-
-
-
-
- Write special floating point values as strings in JSON, e.g. "NaN", "Infinity", "-Infinity".
-
-
-
-
- Write special floating point values as symbols in JSON, e.g. NaN, Infinity, -Infinity.
- Note that this will produce non-valid JSON.
-
-
-
-
- Write special floating point values as the property's default value in JSON, e.g. 0.0 for a property, null for a of property.
-
-
-
-
- Specifies how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text.
-
-
-
-
- Floating point numbers are parsed to .
-
-
-
-
- Floating point numbers are parsed to .
-
-
-
-
- Specifies formatting options for the .
-
-
-
-
- No special formatting is applied. This is the default.
-
-
-
-
- Causes child objects to be indented according to the and settings.
-
-
-
-
- Provides an interface for using pooled arrays.
-
- The array type content.
-
-
-
- Rent an array from the pool. This array must be returned when it is no longer needed.
-
- The minimum required length of the array. The returned array may be longer.
- The rented array from the pool. This array must be returned when it is no longer needed.
-
-
-
- Return an array to the pool.
-
- The array that is being returned.
-
-
-
- Provides an interface to enable a class to return line and position information.
-
-
-
-
- Gets a value indicating whether the class can return line information.
-
-
- true if and can be provided; otherwise, false.
-
-
-
-
- Gets the current line number.
-
- The current line number or 0 if no line information is available (for example, when returns false).
-
-
-
- Gets the current line position.
-
- The current line position or 0 if no line information is available (for example, when returns false).
-
-
-
- Instructs the how to serialize the collection.
-
-
-
-
- Gets or sets a value indicating whether null items are allowed in the collection.
-
- true if null items are allowed in the collection; otherwise, false.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class with a flag indicating whether the array can contain null items.
-
- A flag indicating whether the array can contain null items.
-
-
-
- Initializes a new instance of the class with the specified container Id.
-
- The container Id.
-
-
-
- Instructs the to use the specified constructor when deserializing that object.
-
-
-
-
- Instructs the how to serialize the object.
-
-
-
-
- Gets or sets the id.
-
- The id.
-
-
-
- Gets or sets the title.
-
- The title.
-
-
-
- Gets or sets the description.
-
- The description.
-
-
-
- Gets or sets the collection's items converter.
-
- The collection's items converter.
-
-
-
- The parameter list to use when constructing the described by .
- If null, the default constructor is used.
- When non-null, there must be a constructor defined in the that exactly matches the number,
- order, and type of these parameters.
-
-
-
- [JsonContainer(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })]
-
-
-
-
-
- Gets or sets the of the .
-
- The of the .
-
-
-
- The parameter list to use when constructing the described by .
- If null, the default constructor is used.
- When non-null, there must be a constructor defined in the that exactly matches the number,
- order, and type of these parameters.
-
-
-
- [JsonContainer(NamingStrategyType = typeof(MyNamingStrategy), NamingStrategyParameters = new object[] { 123, "Four" })]
-
-
-
-
-
- Gets or sets a value that indicates whether to preserve object references.
-
-
- true to keep object reference; otherwise, false. The default is false.
-
-
-
-
- Gets or sets a value that indicates whether to preserve collection's items references.
-
-
- true to keep collection's items object references; otherwise, false. The default is false.
-
-
-
-
- Gets or sets the reference loop handling used when serializing the collection's items.
-
- The reference loop handling.
-
-
-
- Gets or sets the type name handling used when serializing the collection's items.
-
- The type name handling.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class with the specified container Id.
-
- The container Id.
-
-
-
- Provides methods for converting between .NET types and JSON types.
-
-
-
-
-
-
-
- Gets or sets a function that creates default .
- Default settings are automatically used by serialization methods on ,
- and and on .
- To serialize without using any default settings create a with
- .
-
-
-
-
- Represents JavaScript's boolean value true as a string. This field is read-only.
-
-
-
-
- Represents JavaScript's boolean value false as a string. This field is read-only.
-
-
-
-
- Represents JavaScript's null as a string. This field is read-only.
-
-
-
-
- Represents JavaScript's undefined as a string. This field is read-only.
-
-
-
-
- Represents JavaScript's positive infinity as a string. This field is read-only.
-
-
-
-
- Represents JavaScript's negative infinity as a string. This field is read-only.
-
-
-
-
- Represents JavaScript's NaN as a string. This field is read-only.
-
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation using the specified.
-
- The value to convert.
- The format the date will be converted to.
- The time zone handling when the date is converted to a string.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation using the specified.
-
- The value to convert.
- The format the date will be converted to.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- The string delimiter character.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- The string delimiter character.
- The string escape handling.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Serializes the specified object to a JSON string.
-
- The object to serialize.
- A JSON string representation of the object.
-
-
-
- Serializes the specified object to a JSON string using formatting.
-
- The object to serialize.
- Indicates how the output should be formatted.
-
- A JSON string representation of the object.
-
-
-
-
- Serializes the specified object to a JSON string using a collection of .
-
- The object to serialize.
- A collection of converters used while serializing.
- A JSON string representation of the object.
-
-
-
- Serializes the specified object to a JSON string using formatting and a collection of .
-
- The object to serialize.
- Indicates how the output should be formatted.
- A collection of converters used while serializing.
- A JSON string representation of the object.
-
-
-
- Serializes the specified object to a JSON string using .
-
- The object to serialize.
- The used to serialize the object.
- If this is null, default serialization settings will be used.
-
- A JSON string representation of the object.
-
-
-
-
- Serializes the specified object to a JSON string using a type, formatting and .
-
- The object to serialize.
- The used to serialize the object.
- If this is null, default serialization settings will be used.
-
- The type of the value being serialized.
- This parameter is used when is to write out the type name if the type of the value does not match.
- Specifying the type is optional.
-
-
- A JSON string representation of the object.
-
-
-
-
- Serializes the specified object to a JSON string using formatting and .
-
- The object to serialize.
- Indicates how the output should be formatted.
- The used to serialize the object.
- If this is null, default serialization settings will be used.
-
- A JSON string representation of the object.
-
-
-
-
- Serializes the specified object to a JSON string using a type, formatting and .
-
- The object to serialize.
- Indicates how the output should be formatted.
- The used to serialize the object.
- If this is null, default serialization settings will be used.
-
- The type of the value being serialized.
- This parameter is used when is to write out the type name if the type of the value does not match.
- Specifying the type is optional.
-
-
- A JSON string representation of the object.
-
-
-
-
- Deserializes the JSON to a .NET object.
-
- The JSON to deserialize.
- The deserialized object from the JSON string.
-
-
-
- Deserializes the JSON to a .NET object using .
-
- The JSON to deserialize.
-
- The used to deserialize the object.
- If this is null, default serialization settings will be used.
-
- The deserialized object from the JSON string.
-
-
-
- Deserializes the JSON to the specified .NET type.
-
- The JSON to deserialize.
- The of object being deserialized.
- The deserialized object from the JSON string.
-
-
-
- Deserializes the JSON to the specified .NET type.
-
- The type of the object to deserialize to.
- The JSON to deserialize.
- The deserialized object from the JSON string.
-
-
-
- Deserializes the JSON to the given anonymous type.
-
-
- The anonymous type to deserialize to. This can't be specified
- traditionally and must be inferred from the anonymous type passed
- as a parameter.
-
- The JSON to deserialize.
- The anonymous type object.
- The deserialized anonymous type from the JSON string.
-
-
-
- Deserializes the JSON to the given anonymous type using .
-
-
- The anonymous type to deserialize to. This can't be specified
- traditionally and must be inferred from the anonymous type passed
- as a parameter.
-
- The JSON to deserialize.
- The anonymous type object.
-
- The used to deserialize the object.
- If this is null, default serialization settings will be used.
-
- The deserialized anonymous type from the JSON string.
-
-
-
- Deserializes the JSON to the specified .NET type using a collection of .
-
- The type of the object to deserialize to.
- The JSON to deserialize.
- Converters to use while deserializing.
- The deserialized object from the JSON string.
-
-
-
- Deserializes the JSON to the specified .NET type using .
-
- The type of the object to deserialize to.
- The object to deserialize.
-
- The used to deserialize the object.
- If this is null, default serialization settings will be used.
-
- The deserialized object from the JSON string.
-
-
-
- Deserializes the JSON to the specified .NET type using a collection of .
-
- The JSON to deserialize.
- The type of the object to deserialize.
- Converters to use while deserializing.
- The deserialized object from the JSON string.
-
-
-
- Deserializes the JSON to the specified .NET type using .
-
- The JSON to deserialize.
- The type of the object to deserialize to.
-
- The used to deserialize the object.
- If this is null, default serialization settings will be used.
-
- The deserialized object from the JSON string.
-
-
-
- Populates the object with values from the JSON string.
-
- The JSON to populate values from.
- The target object to populate values onto.
-
-
-
- Populates the object with values from the JSON string using .
-
- The JSON to populate values from.
- The target object to populate values onto.
-
- The used to deserialize the object.
- If this is null, default serialization settings will be used.
-
-
-
-
- Serializes the to a JSON string.
-
- The node to serialize.
- A JSON string of the .
-
-
-
- Serializes the to a JSON string using formatting.
-
- The node to serialize.
- Indicates how the output should be formatted.
- A JSON string of the .
-
-
-
- Serializes the to a JSON string using formatting and omits the root object if is true.
-
- The node to serialize.
- Indicates how the output should be formatted.
- Omits writing the root object.
- A JSON string of the .
-
-
-
- Deserializes the from a JSON string.
-
- The JSON string.
- The deserialized .
-
-
-
- Deserializes the from a JSON string nested in a root element specified by .
-
- The JSON string.
- The name of the root element to append when deserializing.
- The deserialized .
-
-
-
- Deserializes the from a JSON string nested in a root element specified by
- and writes a Json.NET array attribute for collections.
-
- The JSON string.
- The name of the root element to append when deserializing.
-
- A flag to indicate whether to write the Json.NET array attribute.
- This attribute helps preserve arrays when converting the written XML back to JSON.
-
- The deserialized .
-
-
-
- Serializes the to a JSON string.
-
- The node to convert to JSON.
- A JSON string of the .
-
-
-
- Serializes the to a JSON string using formatting.
-
- The node to convert to JSON.
- Indicates how the output should be formatted.
- A JSON string of the .
-
-
-
- Serializes the to a JSON string using formatting and omits the root object if is true.
-
- The node to serialize.
- Indicates how the output should be formatted.
- Omits writing the root object.
- A JSON string of the .
-
-
-
- Deserializes the from a JSON string.
-
- The JSON string.
- The deserialized .
-
-
-
- Deserializes the from a JSON string nested in a root element specified by .
-
- The JSON string.
- The name of the root element to append when deserializing.
- The deserialized .
-
-
-
- Deserializes the from a JSON string nested in a root element specified by
- and writes a Json.NET array attribute for collections.
-
- The JSON string.
- The name of the root element to append when deserializing.
-
- A flag to indicate whether to write the Json.NET array attribute.
- This attribute helps preserve arrays when converting the written XML back to JSON.
-
- The deserialized .
-
-
-
- Converts an object to and from JSON.
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Gets a value indicating whether this can read JSON.
-
- true if this can read JSON; otherwise, false.
-
-
-
- Gets a value indicating whether this can write JSON.
-
- true if this can write JSON; otherwise, false.
-
-
-
- Converts an object to and from JSON.
-
- The object type to convert.
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read. If there is no existing value then null will be used.
- The existing value has a value.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Instructs the to use the specified when serializing the member or class.
-
-
-
-
- Gets the of the .
-
- The of the .
-
-
-
- The parameter list to use when constructing the described by .
- If null, the default constructor is used.
-
-
-
-
- Initializes a new instance of the class.
-
- Type of the .
-
-
-
- Initializes a new instance of the class.
-
- Type of the .
- Parameter list to use when constructing the . Can be null.
-
-
-
- Represents a collection of .
-
-
-
-
- Instructs the how to serialize the collection.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class with the specified container Id.
-
- The container Id.
-
-
-
- The exception thrown when an error occurs during JSON serialization or deserialization.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class
- with a specified error message.
-
- The error message that explains the reason for the exception.
-
-
-
- Initializes a new instance of the class
- with a specified error message and a reference to the inner exception that is the cause of this exception.
-
- The error message that explains the reason for the exception.
- The exception that is the cause of the current exception, or null if no inner exception is specified.
-
-
-
- Instructs the to deserialize properties with no matching class member into the specified collection
- and write values during serialization.
-
-
-
-
- Gets or sets a value that indicates whether to write extension data when serializing the object.
-
-
- true to write extension data when serializing the object; otherwise, false. The default is true.
-
-
-
-
- Gets or sets a value that indicates whether to read extension data when deserializing the object.
-
-
- true to read extension data when deserializing the object; otherwise, false. The default is true.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Instructs the not to serialize the public field or public read/write property value.
-
-
-
-
- Instructs the how to serialize the object.
-
-
-
-
- Gets or sets the member serialization.
-
- The member serialization.
-
-
-
- Gets or sets how the object's properties with null values are handled during serialization and deserialization.
-
- How the object's properties with null values are handled during serialization and deserialization.
-
-
-
- Gets or sets a value that indicates whether the object's properties are required.
-
-
- A value indicating whether the object's properties are required.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class with the specified member serialization.
-
- The member serialization.
-
-
-
- Initializes a new instance of the class with the specified container Id.
-
- The container Id.
-
-
-
- Instructs the to always serialize the member with the specified name.
-
-
-
-
- Gets or sets the used when serializing the property's collection items.
-
- The collection's items .
-
-
-
- The parameter list to use when constructing the described by .
- If null, the default constructor is used.
- When non-null, there must be a constructor defined in the that exactly matches the number,
- order, and type of these parameters.
-
-
-
- [JsonProperty(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })]
-
-
-
-
-
- Gets or sets the of the .
-
- The of the .
-
-
-
- The parameter list to use when constructing the described by .
- If null, the default constructor is used.
- When non-null, there must be a constructor defined in the that exactly matches the number,
- order, and type of these parameters.
-
-
-
- [JsonProperty(NamingStrategyType = typeof(MyNamingStrategy), NamingStrategyParameters = new object[] { 123, "Four" })]
-
-
-
-
-
- Gets or sets the null value handling used when serializing this property.
-
- The null value handling.
-
-
-
- Gets or sets the default value handling used when serializing this property.
-
- The default value handling.
-
-
-
- Gets or sets the reference loop handling used when serializing this property.
-
- The reference loop handling.
-
-
-
- Gets or sets the object creation handling used when deserializing this property.
-
- The object creation handling.
-
-
-
- Gets or sets the type name handling used when serializing this property.
-
- The type name handling.
-
-
-
- Gets or sets whether this property's value is serialized as a reference.
-
- Whether this property's value is serialized as a reference.
-
-
-
- Gets or sets the order of serialization of a member.
-
- The numeric order of serialization.
-
-
-
- Gets or sets a value indicating whether this property is required.
-
-
- A value indicating whether this property is required.
-
-
-
-
- Gets or sets the name of the property.
-
- The name of the property.
-
-
-
- Gets or sets the reference loop handling used when serializing the property's collection items.
-
- The collection's items reference loop handling.
-
-
-
- Gets or sets the type name handling used when serializing the property's collection items.
-
- The collection's items type name handling.
-
-
-
- Gets or sets whether this property's collection items are serialized as a reference.
-
- Whether this property's collection items are serialized as a reference.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class with the specified name.
-
- Name of the property.
-
-
-
- Represents a reader that provides fast, non-cached, forward-only access to serialized JSON data.
-
-
-
-
- Asynchronously reads the next JSON token from the source.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns true if the next token was read successfully; false if there are no more tokens to read.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously skips the children of the current token.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously reads the next JSON token from the source as a [].
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the []. This result will be null at the end of an array.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously reads the next JSON token from the source as a .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the . This result will be null at the end of an array.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Specifies the state of the reader.
-
-
-
-
- A read method has not been called.
-
-
-
-
- The end of the file has been reached successfully.
-
-
-
-
- Reader is at a property.
-
-
-
-
- Reader is at the start of an object.
-
-
-
-
- Reader is in an object.
-
-
-
-
- Reader is at the start of an array.
-
-
-
-
- Reader is in an array.
-
-
-
-
- The method has been called.
-
-
-
-
- Reader has just read a value.
-
-
-
-
- Reader is at the start of a constructor.
-
-
-
-
- Reader is in a constructor.
-
-
-
-
- An error occurred that prevents the read operation from continuing.
-
-
-
-
- The end of the file has been reached successfully.
-
-
-
-
- Gets the current reader state.
-
- The current reader state.
-
-
-
- Gets or sets a value indicating whether the source should be closed when this reader is closed.
-
-
- true to close the source when this reader is closed; otherwise false. The default is true.
-
-
-
-
- Gets or sets a value indicating whether multiple pieces of JSON content can
- be read from a continuous stream without erroring.
-
-
- true to support reading multiple pieces of JSON content; otherwise false.
- The default is false.
-
-
-
-
- Gets the quotation mark character used to enclose the value of a string.
-
-
-
-
- Gets or sets how time zones are handled when reading JSON.
-
-
-
-
- Gets or sets how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON.
-
-
-
-
- Gets or sets how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text.
-
-
-
-
- Gets or sets how custom date formatted strings are parsed when reading JSON.
-
-
-
-
- Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a .
-
-
-
-
- Gets the type of the current JSON token.
-
-
-
-
- Gets the text value of the current JSON token.
-
-
-
-
- Gets the .NET type for the current JSON token.
-
-
-
-
- Gets the depth of the current token in the JSON document.
-
- The depth of the current token in the JSON document.
-
-
-
- Gets the path of the current JSON token.
-
-
-
-
- Gets or sets the culture used when reading JSON. Defaults to .
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Reads the next JSON token from the source.
-
- true if the next token was read successfully; false if there are no more tokens to read.
-
-
-
- Reads the next JSON token from the source as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the source as a .
-
- A . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the source as a [].
-
- A [] or null if the next JSON token is null. This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the source as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the source as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the source as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the source as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the source as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Skips the children of the current token.
-
-
-
-
- Sets the current token.
-
- The new token.
-
-
-
- Sets the current token and value.
-
- The new token.
- The value.
-
-
-
- Sets the current token and value.
-
- The new token.
- The value.
- A flag indicating whether the position index inside an array should be updated.
-
-
-
- Sets the state based on current token type.
-
-
-
-
- Releases unmanaged and - optionally - managed resources.
-
- true to release both managed and unmanaged resources; false to release only unmanaged resources.
-
-
-
- Changes the reader's state to .
- If is set to true, the source is also closed.
-
-
-
-
- The exception thrown when an error occurs while reading JSON text.
-
-
-
-
- Gets the line number indicating where the error occurred.
-
- The line number indicating where the error occurred.
-
-
-
- Gets the line position indicating where the error occurred.
-
- The line position indicating where the error occurred.
-
-
-
- Gets the path to the JSON where the error occurred.
-
- The path to the JSON where the error occurred.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class
- with a specified error message.
-
- The error message that explains the reason for the exception.
-
-
-
- Initializes a new instance of the class
- with a specified error message and a reference to the inner exception that is the cause of this exception.
-
- The error message that explains the reason for the exception.
- The exception that is the cause of the current exception, or null if no inner exception is specified.
-
-
-
- Initializes a new instance of the class
- with a specified error message, JSON path, line number, line position, and a reference to the inner exception that is the cause of this exception.
-
- The error message that explains the reason for the exception.
- The path to the JSON where the error occurred.
- The line number indicating where the error occurred.
- The line position indicating where the error occurred.
- The exception that is the cause of the current exception, or null if no inner exception is specified.
-
-
-
- Instructs the to always serialize the member, and to require that the member has a value.
-
-
-
-
- The exception thrown when an error occurs during JSON serialization or deserialization.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class
- with a specified error message.
-
- The error message that explains the reason for the exception.
-
-
-
- Initializes a new instance of the class
- with a specified error message and a reference to the inner exception that is the cause of this exception.
-
- The error message that explains the reason for the exception.
- The exception that is the cause of the current exception, or null if no inner exception is specified.
-
-
-
- Serializes and deserializes objects into and from the JSON format.
- The enables you to control how objects are encoded into JSON.
-
-
-
-
- Occurs when the errors during serialization and deserialization.
-
-
-
-
- Gets or sets the used by the serializer when resolving references.
-
-
-
-
- Gets or sets the used by the serializer when resolving type names.
-
-
-
-
- Gets or sets the equality comparer used by the serializer when comparing references.
-
- The equality comparer.
-
-
-
- Gets or sets how type name writing and reading is handled by the serializer.
- The default value is .
-
-
- should be used with caution when your application deserializes JSON from an external source.
- Incoming types should be validated with a custom
- when deserializing with a value other than .
-
-
-
-
- Gets or sets how a type name assembly is written and resolved by the serializer.
- The default value is .
-
- The type name assembly format.
-
-
-
- Gets or sets how object references are preserved by the serializer.
- The default value is .
-
-
-
-
- Gets or sets how reference loops (e.g. a class referencing itself) is handled.
- The default value is .
-
-
-
-
- Gets or sets how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization.
- The default value is .
-
-
-
-
- Gets or sets how null values are handled during serialization and deserialization.
- The default value is .
-
-
-
-
- Gets or sets how default values are handled during serialization and deserialization.
- The default value is .
-
-
-
-
- Gets or sets how objects are created during deserialization.
- The default value is .
-
- The object creation handling.
-
-
-
- Gets or sets how constructors are used during deserialization.
- The default value is .
-
- The constructor handling.
-
-
-
- Gets or sets how metadata properties are used during deserialization.
- The default value is .
-
- The metadata properties handling.
-
-
-
- Gets a collection that will be used during serialization.
-
- Collection that will be used during serialization.
-
-
-
- Gets or sets the contract resolver used by the serializer when
- serializing .NET objects to JSON and vice versa.
-
-
-
-
- Indicates how JSON text output is formatted.
- The default value is .
-
-
-
-
- Gets or sets how dates are written to JSON text.
- The default value is .
-
-
-
-
- Gets or sets how time zones are handled during serialization and deserialization.
- The default value is .
-
-
-
-
- Gets or sets how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON.
- The default value is .
-
-
-
-
- Gets or sets how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text.
- The default value is .
-
-
-
-
- Gets or sets how special floating point numbers, e.g. ,
- and ,
- are written as JSON text.
- The default value is .
-
-
-
-
- Gets or sets how strings are escaped when writing JSON text.
- The default value is .
-
-
-
-
- Gets or sets how and values are formatted when writing JSON text,
- and the expected date format when reading JSON text.
- The default value is "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK".
-
-
-
-
- Gets or sets the culture used when reading JSON.
- The default value is .
-
-
-
-
- Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a .
- A null value means there is no maximum.
- The default value is null.
-
-
-
-
- Gets a value indicating whether there will be a check for additional JSON content after deserializing an object.
- The default value is false.
-
-
- true if there will be a check for additional JSON content after deserializing an object; otherwise, false.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Clears all the cached types, attributes and methods to release references to any types of the other assemblies.
-
-
-
-
- Creates a new instance.
- The will not use default settings
- from .
-
-
- A new instance.
- The will not use default settings
- from .
-
-
-
-
- Creates a new instance using the specified .
- The will not use default settings
- from .
-
- The settings to be applied to the .
-
- A new instance using the specified .
- The will not use default settings
- from .
-
-
-
-
- Creates a new instance.
- The will use default settings
- from .
-
-
- A new instance.
- The will use default settings
- from .
-
-
-
-
- Creates a new instance using the specified .
- The will use default settings
- from as well as the specified .
-
- The settings to be applied to the .
-
- A new instance using the specified .
- The will use default settings
- from as well as the specified .
-
-
-
-
- Populates the JSON values onto the target object.
-
- The that contains the JSON structure to reader values from.
- The target object to populate values onto.
-
-
-
- Populates the JSON values onto the target object.
-
- The that contains the JSON structure to reader values from.
- The target object to populate values onto.
-
-
-
- Deserializes the JSON structure contained by the specified .
-
- The that contains the JSON structure to deserialize.
- The being deserialized.
-
-
-
- Deserializes the JSON structure contained by the specified
- into an instance of the specified type.
-
- The containing the object.
- The of object being deserialized.
- The instance of being deserialized.
-
-
-
- Deserializes the JSON structure contained by the specified
- into an instance of the specified type.
-
- The containing the object.
- The type of the object to deserialize.
- The instance of being deserialized.
-
-
-
- Deserializes the JSON structure contained by the specified
- into an instance of the specified type.
-
- The containing the object.
- The of object being deserialized.
- The instance of being deserialized.
-
-
-
- Serializes the specified difference to the other object of the same type. and writes the JSON structure using the specified .
-
- The used to write the JSON structure.
- The to serialize.
- The reference object.
-
-
-
- Serializes the specified difference to the other object of the same type. Writes the JSON structure using the specified .
-
- The used to write the JSON structure.
- The to serialize.
-
- The type of the value being serialized.
- This parameter is used when is to write out the type name if the type of the value does not match.
- Specifying the type is optional.
-
- The reference object.
-
-
-
- Serializes the specified difference to the other object of the same type. Writes the JSON structure using the specified .
-
- The used to write the JSON structure.
- The to serialize.
-
- The type of the value being serialized.
- This parameter is used when is Auto to write out the type name if the type of the value does not match.
- Specifying the type is optional.
-
- The reference object.
-
-
-
- Serializes the specified and writes the JSON structure
- using the specified .
-
- The used to write the JSON structure.
- The to serialize.
- The reference object.
-
-
-
- Serializes the specified and writes the JSON structure
- using the specified .
-
- The used to write the JSON structure.
- The to serialize.
-
-
-
- Serializes the specified and writes the JSON structure
- using the specified .
-
- The used to write the JSON structure.
- The to serialize.
-
- The type of the value being serialized.
- This parameter is used when is to write out the type name if the type of the value does not match.
- Specifying the type is optional.
-
-
-
-
- Serializes the specified and writes the JSON structure
- using the specified .
-
- The used to write the JSON structure.
- The to serialize.
-
- The type of the value being serialized.
- This parameter is used when is Auto to write out the type name if the type of the value does not match.
- Specifying the type is optional.
-
-
-
-
- Serializes the specified and writes the JSON structure
- using the specified .
-
- The used to write the JSON structure.
- The to serialize.
-
-
-
- Specifies the settings on a object.
-
-
-
-
- Gets or sets how reference loops (e.g. a class referencing itself) are handled.
- The default value is .
-
- Reference loop handling.
-
-
-
- Gets or sets how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization.
- The default value is .
-
- Missing member handling.
-
-
-
- Gets or sets how objects are created during deserialization.
- The default value is .
-
- The object creation handling.
-
-
-
- Gets or sets how null values are handled during serialization and deserialization.
- The default value is .
-
- Null value handling.
-
-
-
- Gets or sets how default values are handled during serialization and deserialization.
- The default value is .
-
- The default value handling.
-
-
-
- Gets or sets a collection that will be used during serialization.
-
- The converters.
-
-
-
- Gets or sets how object references are preserved by the serializer.
- The default value is .
-
- The preserve references handling.
-
-
-
- Gets or sets how type name writing and reading is handled by the serializer.
- The default value is .
-
-
- should be used with caution when your application deserializes JSON from an external source.
- Incoming types should be validated with a custom
- when deserializing with a value other than .
-
- The type name handling.
-
-
-
- Gets or sets how metadata properties are used during deserialization.
- The default value is .
-
- The metadata properties handling.
-
-
-
- Gets or sets how a type name assembly is written and resolved by the serializer.
- The default value is .
-
- The type name assembly format.
-
-
-
- Gets or sets how constructors are used during deserialization.
- The default value is .
-
- The constructor handling.
-
-
-
- Gets or sets the contract resolver used by the serializer when
- serializing .NET objects to JSON and vice versa.
-
- The contract resolver.
-
-
-
- Gets or sets the equality comparer used by the serializer when comparing references.
-
- The equality comparer.
-
-
-
- Gets or sets a function that creates the used by the serializer when resolving references.
-
- A function that creates the used by the serializer when resolving references.
-
-
-
- Gets or sets the used by the serializer when resolving type names.
-
- The binder.
-
-
-
- Gets or sets the error handler called during serialization and deserialization.
-
- The error handler called during serialization and deserialization.
-
-
-
- Gets or sets how and values are formatted when writing JSON text,
- and the expected date format when reading JSON text.
- The default value is "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK".
-
-
-
-
- Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a .
- A null value means there is no maximum.
- The default value is null.
-
-
-
-
- Indicates how JSON text output is formatted.
- The default value is .
-
-
-
-
- Gets or sets how dates are written to JSON text.
- The default value is .
-
-
-
-
- Gets or sets how time zones are handled during serialization and deserialization.
- The default value is .
-
-
-
-
- Gets or sets how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON.
- The default value is .
-
-
-
-
- Gets or sets how special floating point numbers, e.g. ,
- and ,
- are written as JSON.
- The default value is .
-
-
-
-
- Gets or sets how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text.
- The default value is .
-
-
-
-
- Gets or sets how strings are escaped when writing JSON text.
- The default value is .
-
-
-
-
- Gets or sets the culture used when reading JSON.
- The default value is .
-
-
-
-
- Gets a value indicating whether there will be a check for additional content after deserializing an object.
- The default value is false.
-
-
- true if there will be a check for additional content after deserializing an object; otherwise, false.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Represents a reader that provides fast, non-cached, forward-only access to JSON text data.
-
-
-
-
- Asynchronously reads the next JSON token from the source.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns true if the next token was read successfully; false if there are no more tokens to read.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously reads the next JSON token from the source as a [].
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the []. This result will be null at the end of an array.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously reads the next JSON token from the source as a .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the . This result will be null at the end of an array.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Initializes a new instance of the class with the specified .
-
- The containing the JSON data to read.
-
-
-
- Gets or sets the reader's character buffer pool.
-
-
-
-
- Reads the next JSON token from the underlying .
-
-
- true if the next token was read successfully; false if there are no more tokens to read.
-
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a .
-
- A . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a [].
-
- A [] or null if the next JSON token is null. This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Changes the reader's state to .
- If is set to true, the underlying is also closed.
-
-
-
-
- Gets a value indicating whether the class can return line information.
-
-
- true if and can be provided; otherwise, false.
-
-
-
-
- Gets the current line number.
-
-
- The current line number or 0 if no line information is available (for example, returns false).
-
-
-
-
- Gets the current line position.
-
-
- The current line position or 0 if no line information is available (for example, returns false).
-
-
-
-
- Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data.
-
-
-
-
- Asynchronously flushes whatever is in the buffer to the destination and also flushes the destination.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the JSON value delimiter.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the specified end token.
-
- The end token to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously closes this writer.
- If is set to true, the destination is also closed.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the end of the current JSON object or array.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes indent characters.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes an indent space.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes raw JSON without changing the writer's state.
-
- The raw JSON to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a null value.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the property name of a name/value pair of a JSON object.
-
- The name of the property.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the property name of a name/value pair of a JSON object.
-
- The name of the property.
- A flag to indicate whether the text should be escaped when it is written as a JSON property name.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the beginning of a JSON array.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the beginning of a JSON object.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the start of a constructor with the given name.
-
- The name of the constructor.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes an undefined value.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the given white space.
-
- The string of white space characters.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a [] value.
-
- The [] value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a comment /*...*/ containing the specified text.
-
- Text to place inside the comment.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the end of an array.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the end of a constructor.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the end of a JSON object.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes raw JSON where a value is expected and updates the writer's state.
-
- The raw JSON to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Gets or sets the writer's character array pool.
-
-
-
-
- Gets or sets how many s to write for each level in the hierarchy when is set to .
-
-
-
-
- Gets or sets which character to use to quote attribute values.
-
-
-
-
- Gets or sets which character to use for indenting when is set to .
-
-
-
-
- Gets or sets a value indicating whether object names will be surrounded with quotes.
-
-
-
-
- Initializes a new instance of the class using the specified .
-
- The to write to.
-
-
-
- Flushes whatever is in the buffer to the underlying and also flushes the underlying .
-
-
-
-
- Closes this writer.
- If is set to true, the underlying is also closed.
- If is set to true, the JSON is auto-completed.
-
-
-
-
- Writes the beginning of a JSON object.
-
-
-
-
- Writes the beginning of a JSON array.
-
-
-
-
- Writes the start of a constructor with the given name.
-
- The name of the constructor.
-
-
-
- Writes the specified end token.
-
- The end token to write.
-
-
-
- Writes the property name of a name/value pair on a JSON object.
-
- The name of the property.
-
-
-
- Writes the property name of a name/value pair on a JSON object.
-
- The name of the property.
- A flag to indicate whether the text should be escaped when it is written as a JSON property name.
-
-
-
- Writes indent characters.
-
-
-
-
- Writes the JSON value delimiter.
-
-
-
-
- Writes an indent space.
-
-
-
-
- Writes a value.
- An error will raised if the value cannot be written as a single JSON token.
-
- The value to write.
-
-
-
- Writes a null value.
-
-
-
-
- Writes an undefined value.
-
-
-
-
- Writes raw JSON.
-
- The raw JSON to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a [] value.
-
- The [] value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a comment /*...*/ containing the specified text.
-
- Text to place inside the comment.
-
-
-
- Writes the given white space.
-
- The string of white space characters.
-
-
-
- Specifies the type of JSON token.
-
-
-
-
- This is returned by the if a read method has not been called.
-
-
-
-
- An object start token.
-
-
-
-
- An array start token.
-
-
-
-
- A constructor start token.
-
-
-
-
- An object property name.
-
-
-
-
- A comment.
-
-
-
-
- Raw JSON.
-
-
-
-
- An integer.
-
-
-
-
- A float.
-
-
-
-
- A string.
-
-
-
-
- A boolean.
-
-
-
-
- A null token.
-
-
-
-
- An undefined token.
-
-
-
-
- An object end token.
-
-
-
-
- An array end token.
-
-
-
-
- A constructor end token.
-
-
-
-
- A Date.
-
-
-
-
- Byte data.
-
-
-
-
-
- Represents a reader that provides validation.
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- Sets an event handler for receiving schema validation errors.
-
-
-
-
- Gets the text value of the current JSON token.
-
-
-
-
-
- Gets the depth of the current token in the JSON document.
-
- The depth of the current token in the JSON document.
-
-
-
- Gets the path of the current JSON token.
-
-
-
-
- Gets the quotation mark character used to enclose the value of a string.
-
-
-
-
-
- Gets the type of the current JSON token.
-
-
-
-
-
- Gets the .NET type for the current JSON token.
-
-
-
-
-
- Initializes a new instance of the class that
- validates the content returned from the given .
-
- The to read from while validating.
-
-
-
- Gets or sets the schema.
-
- The schema.
-
-
-
- Gets the used to construct this .
-
- The specified in the constructor.
-
-
-
- Changes the reader's state to .
- If is set to true, the underlying is also closed.
-
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of .
-
-
-
- Reads the next JSON token from the underlying as a [].
-
-
- A [] or null if the next JSON token is null.
-
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of .
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of .
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of .
-
-
-
- Reads the next JSON token from the underlying as a .
-
- A . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of .
-
-
-
- Reads the next JSON token from the underlying .
-
-
- true if the next token was read successfully; false if there are no more tokens to read.
-
-
-
-
- Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data.
-
-
-
-
- Asynchronously closes this writer.
- If is set to true, the destination is also closed.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously flushes whatever is in the buffer to the destination and also flushes the destination.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the specified end token.
-
- The end token to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes indent characters.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the JSON value delimiter.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes an indent space.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes raw JSON without changing the writer's state.
-
- The raw JSON to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the end of the current JSON object or array.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the end of an array.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the end of a constructor.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the end of a JSON object.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a null value.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the property name of a name/value pair of a JSON object.
-
- The name of the property.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the property name of a name/value pair of a JSON object.
-
- The name of the property.
- A flag to indicate whether the text should be escaped when it is written as a JSON property name.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the beginning of a JSON array.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a comment /*...*/ containing the specified text.
-
- Text to place inside the comment.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes raw JSON where a value is expected and updates the writer's state.
-
- The raw JSON to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the start of a constructor with the given name.
-
- The name of the constructor.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the beginning of a JSON object.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the current token.
-
- The to read the token from.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the current token.
-
- The to read the token from.
- A flag indicating whether the current token's children should be written.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the token and its value.
-
- The to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the token and its value.
-
- The to write.
-
- The value to write.
- A value is only required for tokens that have an associated value, e.g. the property name for .
- null can be passed to the method for tokens that don't have a value, e.g. .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a [] value.
-
- The [] value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes an undefined value.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the given white space.
-
- The string of white space characters.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously ets the state of the .
-
- The being written.
- The value being written.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Gets or sets a value indicating whether the destination should be closed when this writer is closed.
-
-
- true to close the destination when this writer is closed; otherwise false. The default is true.
-
-
-
-
- Gets or sets a value indicating whether the JSON should be auto-completed when this writer is closed.
-
-
- true to auto-complete the JSON when this writer is closed; otherwise false. The default is true.
-
-
-
-
- Gets the top.
-
- The top.
-
-
-
- Gets the state of the writer.
-
-
-
-
- Gets the path of the writer.
-
-
-
-
- Gets or sets a value indicating how JSON text output should be formatted.
-
-
-
-
- Gets or sets how dates are written to JSON text.
-
-
-
-
- Gets or sets how time zones are handled when writing JSON text.
-
-
-
-
- Gets or sets how strings are escaped when writing JSON text.
-
-
-
-
- Gets or sets how special floating point numbers, e.g. ,
- and ,
- are written to JSON text.
-
-
-
-
- Gets or sets how and values are formatted when writing JSON text.
-
-
-
-
- Gets or sets the culture used when writing JSON. Defaults to .
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Flushes whatever is in the buffer to the destination and also flushes the destination.
-
-
-
-
- Closes this writer.
- If is set to true, the destination is also closed.
- If is set to true, the JSON is auto-completed.
-
-
-
-
- Writes the beginning of a JSON object.
-
-
-
-
- Writes the end of a JSON object.
-
-
-
-
- Writes the beginning of a JSON array.
-
-
-
-
- Writes the end of an array.
-
-
-
-
- Writes the start of a constructor with the given name.
-
- The name of the constructor.
-
-
-
- Writes the end constructor.
-
-
-
-
- Writes the property name of a name/value pair of a JSON object.
-
- The name of the property.
-
-
-
- Writes the property name of a name/value pair of a JSON object.
-
- The name of the property.
- A flag to indicate whether the text should be escaped when it is written as a JSON property name.
-
-
-
- Writes the end of the current JSON object or array.
-
-
-
-
- Writes the current token and its children.
-
- The to read the token from.
-
-
-
- Writes the current token.
-
- The to read the token from.
- A flag indicating whether the current token's children should be written.
-
-
-
- Writes the token and its value.
-
- The to write.
-
- The value to write.
- A value is only required for tokens that have an associated value, e.g. the property name for .
- null can be passed to the method for tokens that don't have a value, e.g. .
-
-
-
-
- Writes the token.
-
- The to write.
-
-
-
- Writes the specified end token.
-
- The end token to write.
-
-
-
- Writes indent characters.
-
-
-
-
- Writes the JSON value delimiter.
-
-
-
-
- Writes an indent space.
-
-
-
-
- Writes a null value.
-
-
-
-
- Writes an undefined value.
-
-
-
-
- Writes raw JSON without changing the writer's state.
-
- The raw JSON to write.
-
-
-
- Writes raw JSON where a value is expected and updates the writer's state.
-
- The raw JSON to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a [] value.
-
- The [] value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
- An error will raised if the value cannot be written as a single JSON token.
-
- The value to write.
-
-
-
- Writes a comment /*...*/ containing the specified text.
-
- Text to place inside the comment.
-
-
-
- Writes the given white space.
-
- The string of white space characters.
-
-
-
- Releases unmanaged and - optionally - managed resources.
-
- true to release both managed and unmanaged resources; false to release only unmanaged resources.
-
-
-
- Sets the state of the .
-
- The being written.
- The value being written.
-
-
-
- The exception thrown when an error occurs while writing JSON text.
-
-
-
-
- Gets the path to the JSON where the error occurred.
-
- The path to the JSON where the error occurred.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class
- with a specified error message.
-
- The error message that explains the reason for the exception.
-
-
-
- Initializes a new instance of the class
- with a specified error message and a reference to the inner exception that is the cause of this exception.
-
- The error message that explains the reason for the exception.
- The exception that is the cause of the current exception, or null if no inner exception is specified.
-
-
-
- Initializes a new instance of the class
- with a specified error message, JSON path and a reference to the inner exception that is the cause of this exception.
-
- The error message that explains the reason for the exception.
- The path to the JSON where the error occurred.
- The exception that is the cause of the current exception, or null if no inner exception is specified.
-
-
-
- Specifies how JSON comments are handled when loading JSON.
-
-
-
-
- Ignore comments.
-
-
-
-
- Load comments as a with type .
-
-
-
-
- Contains the LINQ to JSON extension methods.
-
-
-
-
- Returns a collection of tokens that contains the ancestors of every token in the source collection.
-
- The type of the objects in source, constrained to .
- An of that contains the source collection.
- An of that contains the ancestors of every token in the source collection.
-
-
-
- Returns a collection of tokens that contains every token in the source collection, and the ancestors of every token in the source collection.
-
- The type of the objects in source, constrained to .
- An of that contains the source collection.
- An of that contains every token in the source collection, the ancestors of every token in the source collection.
-
-
-
- Returns a collection of tokens that contains the descendants of every token in the source collection.
-
- The type of the objects in source, constrained to .
- An of that contains the source collection.
- An of that contains the descendants of every token in the source collection.
-
-
-
- Returns a collection of tokens that contains every token in the source collection, and the descendants of every token in the source collection.
-
- The type of the objects in source, constrained to .
- An of that contains the source collection.
- An of that contains every token in the source collection, and the descendants of every token in the source collection.
-
-
-
- Returns a collection of child properties of every object in the source collection.
-
- An of that contains the source collection.
- An of that contains the properties of every object in the source collection.
-
-
-
- Returns a collection of child values of every object in the source collection with the given key.
-
- An of that contains the source collection.
- The token key.
- An of that contains the values of every token in the source collection with the given key.
-
-
-
- Returns a collection of child values of every object in the source collection.
-
- An of that contains the source collection.
- An of that contains the values of every token in the source collection.
-
-
-
- Returns a collection of converted child values of every object in the source collection with the given key.
-
- The type to convert the values to.
- An of that contains the source collection.
- The token key.
- An that contains the converted values of every token in the source collection with the given key.
-
-
-
- Returns a collection of converted child values of every object in the source collection.
-
- The type to convert the values to.
- An of that contains the source collection.
- An that contains the converted values of every token in the source collection.
-
-
-
- Converts the value.
-
- The type to convert the value to.
- A cast as a of .
- A converted value.
-
-
-
- Converts the value.
-
- The source collection type.
- The type to convert the value to.
- A cast as a of .
- A converted value.
-
-
-
- Returns a collection of child tokens of every array in the source collection.
-
- The source collection type.
- An of that contains the source collection.
- An of that contains the values of every token in the source collection.
-
-
-
- Returns a collection of converted child tokens of every array in the source collection.
-
- An of that contains the source collection.
- The type to convert the values to.
- The source collection type.
- An that contains the converted values of every token in the source collection.
-
-
-
- Returns the input typed as .
-
- An of that contains the source collection.
- The input typed as .
-
-
-
- Returns the input typed as .
-
- The source collection type.
- An of that contains the source collection.
- The input typed as .
-
-
-
- Represents a collection of objects.
-
- The type of token.
-
-
-
- Gets the of with the specified key.
-
-
-
-
-
- Represents a JSON array.
-
-
-
-
-
-
-
- Writes this token to a asynchronously.
-
- A into which this method will write.
- The token to monitor for cancellation requests.
- A collection of which will be used when writing the token.
- A that represents the asynchronous write operation.
-
-
-
- Asynchronously loads a from a .
-
- A that will be read for the content of the .
- If this is null, default load settings will be used.
- The token to monitor for cancellation requests. The default value is .
- A representing the asynchronous load. The property contains the JSON that was read from the specified .
-
-
-
- Asynchronously loads a from a .
-
- A that will be read for the content of the .
- The used to load the JSON.
- If this is null, default load settings will be used.
- The token to monitor for cancellation requests. The default value is .
- A representing the asynchronous load. The property contains the JSON that was read from the specified .
-
-
-
- Gets the container's children tokens.
-
- The container's children tokens.
-
-
-
- Gets the node type for this .
-
- The type.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class from another object.
-
- A object to copy from.
-
-
-
- Initializes a new instance of the class with the specified content.
-
- The contents of the array.
-
-
-
- Initializes a new instance of the class with the specified content.
-
- The contents of the array.
-
-
-
- Loads an from a .
-
- A that will be read for the content of the .
- A that contains the JSON that was read from the specified .
-
-
-
- Loads an from a .
-
- A that will be read for the content of the .
- The used to load the JSON.
- If this is null, default load settings will be used.
- A that contains the JSON that was read from the specified .
-
-
-
- Load a from a string that contains JSON.
-
- A that contains JSON.
- A populated from the string that contains JSON.
-
-
-
-
-
-
- Load a from a string that contains JSON.
-
- A that contains JSON.
- The used to load the JSON.
- If this is null, default load settings will be used.
- A populated from the string that contains JSON.
-
-
-
-
-
-
- Creates a from an object.
-
- The object that will be used to create .
- A with the values of the specified object.
-
-
-
- Creates a from an object.
-
- The object that will be used to create .
- The that will be used to read the object.
- A with the values of the specified object.
-
-
-
- Writes this token to a .
-
- A into which this method will write.
- A collection of which will be used when writing the token.
-
-
-
- Gets the with the specified key.
-
- The with the specified key.
-
-
-
- Gets or sets the at the specified index.
-
-
-
-
-
- Determines the index of a specific item in the .
-
- The object to locate in the .
-
- The index of if found in the list; otherwise, -1.
-
-
-
-
- Inserts an item to the at the specified index.
-
- The zero-based index at which should be inserted.
- The object to insert into the .
-
- is not a valid index in the .
-
-
-
-
- Removes the item at the specified index.
-
- The zero-based index of the item to remove.
-
- is not a valid index in the .
-
-
-
-
- Returns an enumerator that iterates through the collection.
-
-
- A of that can be used to iterate through the collection.
-
-
-
-
- Adds an item to the .
-
- The object to add to the .
-
-
-
- Removes all items from the .
-
-
-
-
- Determines whether the contains a specific value.
-
- The object to locate in the .
-
- true if is found in the ; otherwise, false.
-
-
-
-
- Copies the elements of the to an array, starting at a particular array index.
-
- The array.
- Index of the array.
-
-
-
- Gets a value indicating whether the is read-only.
-
- true if the is read-only; otherwise, false.
-
-
-
- Removes the first occurrence of a specific object from the .
-
- The object to remove from the .
-
- true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original .
-
-
-
-
- Represents a JSON constructor.
-
-
-
-
- Writes this token to a asynchronously.
-
- A into which this method will write.
- The token to monitor for cancellation requests.
- A collection of which will be used when writing the token.
- A that represents the asynchronous write operation.
-
-
-
- Asynchronously loads a from a .
-
- A that will be read for the content of the .
- The token to monitor for cancellation requests. The default value is .
-
- A that represents the asynchronous load. The
- property returns a that contains the JSON that was read from the specified .
-
-
-
- Asynchronously loads a from a .
-
- A that will be read for the content of the .
- The used to load the JSON.
- If this is null, default load settings will be used.
- The token to monitor for cancellation requests. The default value is .
-
- A that represents the asynchronous load. The
- property returns a that contains the JSON that was read from the specified .
-
-
-
- Gets the container's children tokens.
-
- The container's children tokens.
-
-
-
- Gets or sets the name of this constructor.
-
- The constructor name.
-
-
-
- Gets the node type for this .
-
- The type.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class from another object.
-
- A object to copy from.
-
-
-
- Initializes a new instance of the class with the specified name and content.
-
- The constructor name.
- The contents of the constructor.
-
-
-
- Initializes a new instance of the class with the specified name and content.
-
- The constructor name.
- The contents of the constructor.
-
-
-
- Initializes a new instance of the class with the specified name.
-
- The constructor name.
-
-
-
- Writes this token to a .
-
- A into which this method will write.
- A collection of which will be used when writing the token.
-
-
-
- Gets the with the specified key.
-
- The with the specified key.
-
-
-
- Loads a from a .
-
- A that will be read for the content of the .
- A that contains the JSON that was read from the specified .
-
-
-
- Loads a from a .
-
- A that will be read for the content of the .
- The used to load the JSON.
- If this is null, default load settings will be used.
- A that contains the JSON that was read from the specified .
-
-
-
- Represents a token that can contain other tokens.
-
-
-
-
- Occurs when the list changes or an item in the list changes.
-
-
-
-
- Occurs before an item is added to the collection.
-
-
-
-
- Occurs when the items list of the collection has changed, or the collection is reset.
-
-
-
-
- Gets the container's children tokens.
-
- The container's children tokens.
-
-
-
- Raises the event.
-
- The instance containing the event data.
-
-
-
- Raises the event.
-
- The instance containing the event data.
-
-
-
- Raises the event.
-
- The instance containing the event data.
-
-
-
- Gets a value indicating whether this token has child tokens.
-
-
- true if this token has child values; otherwise, false.
-
-
-
-
- Get the first child token of this token.
-
-
- A containing the first child token of the .
-
-
-
-
- Get the last child token of this token.
-
-
- A containing the last child token of the .
-
-
-
-
- Returns a collection of the child tokens of this token, in document order.
-
-
- An of containing the child tokens of this , in document order.
-
-
-
-
- Returns a collection of the child values of this token, in document order.
-
- The type to convert the values to.
-
- A containing the child values of this , in document order.
-
-
-
-
- Returns a collection of the descendant tokens for this token in document order.
-
- An of containing the descendant tokens of the .
-
-
-
- Returns a collection of the tokens that contain this token, and all descendant tokens of this token, in document order.
-
- An of containing this token, and all the descendant tokens of the .
-
-
-
- Adds the specified content as children of this .
-
- The content to be added.
-
-
-
- Adds the specified content as the first children of this .
-
- The content to be added.
-
-
-
- Creates a that can be used to add tokens to the .
-
- A that is ready to have content written to it.
-
-
-
- Replaces the child nodes of this token with the specified content.
-
- The content.
-
-
-
- Removes the child nodes from this token.
-
-
-
-
- Merge the specified content into this .
-
- The content to be merged.
-
-
-
- Merge the specified content into this using .
-
- The content to be merged.
- The used to merge the content.
-
-
-
- Gets the count of child JSON tokens.
-
- The count of child JSON tokens.
-
-
-
- Represents a collection of objects.
-
- The type of token.
-
-
-
- An empty collection of objects.
-
-
-
-
- Initializes a new instance of the struct.
-
- The enumerable.
-
-
-
- Returns an enumerator that can be used to iterate through the collection.
-
-
- A that can be used to iterate through the collection.
-
-
-
-
- Gets the of with the specified key.
-
-
-
-
-
- Determines whether the specified is equal to this instance.
-
- The to compare with this instance.
-
- true if the specified is equal to this instance; otherwise, false.
-
-
-
-
- Determines whether the specified is equal to this instance.
-
- The to compare with this instance.
-
- true if the specified is equal to this instance; otherwise, false.
-
-
-
-
- Returns a hash code for this instance.
-
-
- A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
-
-
-
-
- Represents a JSON object.
-
-
-
-
-
-
-
- Writes this token to a asynchronously.
-
- A into which this method will write.
- The token to monitor for cancellation requests.
- A collection of which will be used when writing the token.
- A that represents the asynchronous write operation.
-
-
-
- Asynchronously loads a from a .
-
- A that will be read for the content of the .
- The token to monitor for cancellation requests. The default value is .
-
- A that represents the asynchronous load. The
- property returns a that contains the JSON that was read from the specified .
-
-
-
- Asynchronously loads a from a .
-
- A that will be read for the content of the .
- The used to load the JSON.
- If this is null, default load settings will be used.
- The token to monitor for cancellation requests. The default value is .
-
- A that represents the asynchronous load. The
- property returns a that contains the JSON that was read from the specified .
-
-
-
- Gets the container's children tokens.
-
- The container's children tokens.
-
-
-
- Occurs when a property value changes.
-
-
-
-
- Occurs when a property value is changing.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class from another object.
-
- A object to copy from.
-
-
-
- Initializes a new instance of the class with the specified content.
-
- The contents of the object.
-
-
-
- Initializes a new instance of the class with the specified content.
-
- The contents of the object.
-
-
-
- Gets the node type for this .
-
- The type.
-
-
-
- Gets an of of this object's properties.
-
- An of of this object's properties.
-
-
-
- Gets a the specified name.
-
- The property name.
- A with the specified name or null.
-
-
-
- Gets a of of this object's property values.
-
- A of of this object's property values.
-
-
-
- Gets the with the specified key.
-
- The with the specified key.
-
-
-
- Gets or sets the with the specified property name.
-
-
-
-
-
- Loads a from a .
-
- A that will be read for the content of the .
- A that contains the JSON that was read from the specified .
-
- is not valid JSON.
-
-
-
-
- Loads a from a .
-
- A that will be read for the content of the .
- The used to load the JSON.
- If this is null, default load settings will be used.
- A that contains the JSON that was read from the specified .
-
- is not valid JSON.
-
-
-
-
- Load a from a string that contains JSON.
-
- A that contains JSON.
- A populated from the string that contains JSON.
-
- is not valid JSON.
-
-
-
-
-
-
-
- Load a from a string that contains JSON.
-
- A that contains JSON.
- The used to load the JSON.
- If this is null, default load settings will be used.
- A populated from the string that contains JSON.
-
- is not valid JSON.
-
-
-
-
-
-
-
- Creates a from an object.
-
- The object that will be used to create .
- A with the values of the specified object.
-
-
-
- Creates a from an object.
-
- The object that will be used to create .
- The that will be used to read the object.
- A with the values of the specified object.
-
-
-
- Writes this token to a .
-
- A into which this method will write.
- A collection of which will be used when writing the token.
-
-
-
- Gets the with the specified property name.
-
- Name of the property.
- The with the specified property name.
-
-
-
- Gets the with the specified property name.
- The exact property name will be searched for first and if no matching property is found then
- the will be used to match a property.
-
- Name of the property.
- One of the enumeration values that specifies how the strings will be compared.
- The with the specified property name.
-
-
-
- Tries to get the with the specified property name.
- The exact property name will be searched for first and if no matching property is found then
- the will be used to match a property.
-
- Name of the property.
- The value.
- One of the enumeration values that specifies how the strings will be compared.
- true if a value was successfully retrieved; otherwise, false.
-
-
-
- Adds the specified property name.
-
- Name of the property.
- The value.
-
-
-
- Determines whether the JSON object has the specified property name.
-
- Name of the property.
- true if the JSON object has the specified property name; otherwise, false.
-
-
-
- Removes the property with the specified name.
-
- Name of the property.
- true if item was successfully removed; otherwise, false.
-
-
-
- Tries to get the with the specified property name.
-
- Name of the property.
- The value.
- true if a value was successfully retrieved; otherwise, false.
-
-
-
- Returns an enumerator that can be used to iterate through the collection.
-
-
- A that can be used to iterate through the collection.
-
-
-
-
- Raises the event with the provided arguments.
-
- Name of the property.
-
-
-
- Raises the event with the provided arguments.
-
- Name of the property.
-
-
-
- Returns the responsible for binding operations performed on this object.
-
- The expression tree representation of the runtime value.
-
- The to bind this object.
-
-
-
-
- Represents a JSON property.
-
-
-
-
- Writes this token to a asynchronously.
-
- A into which this method will write.
- The token to monitor for cancellation requests.
- A collection of which will be used when writing the token.
- A that represents the asynchronous write operation.
-
-
-
- Asynchronously loads a from a .
-
- A that will be read for the content of the .
- The token to monitor for cancellation requests. The default value is .
- A representing the asynchronous creation. The
- property returns a that contains the JSON that was read from the specified .
-
-
-
- Asynchronously loads a from a .
-
- A that will be read for the content of the .
- The used to load the JSON.
- If this is null, default load settings will be used.
- The token to monitor for cancellation requests. The default value is .
- A representing the asynchronous creation. The
- property returns a that contains the JSON that was read from the specified .
-
-
-
- Gets the container's children tokens.
-
- The container's children tokens.
-
-
-
- Gets the property name.
-
- The property name.
-
-
-
- Gets or sets the property value.
-
- The property value.
-
-
-
- Initializes a new instance of the class from another object.
-
- A object to copy from.
-
-
-
- Gets the node type for this .
-
- The type.
-
-
-
- Initializes a new instance of the class.
-
- The property name.
- The property content.
-
-
-
- Initializes a new instance of the class.
-
- The property name.
- The property content.
-
-
-
- Writes this token to a .
-
- A into which this method will write.
- A collection of which will be used when writing the token.
-
-
-
- Loads a from a .
-
- A that will be read for the content of the .
- A that contains the JSON that was read from the specified .
-
-
-
- Loads a from a .
-
- A that will be read for the content of the .
- The used to load the JSON.
- If this is null, default load settings will be used.
- A that contains the JSON that was read from the specified .
-
-
-
- Represents a view of a .
-
-
-
-
- Initializes a new instance of the class.
-
- The name.
-
-
-
- When overridden in a derived class, returns whether resetting an object changes its value.
-
-
- true if resetting the component changes its value; otherwise, false.
-
- The component to test for reset capability.
-
-
-
- When overridden in a derived class, gets the current value of the property on a component.
-
-
- The value of a property for a given component.
-
- The component with the property for which to retrieve the value.
-
-
-
- When overridden in a derived class, resets the value for this property of the component to the default value.
-
- The component with the property value that is to be reset to the default value.
-
-
-
- When overridden in a derived class, sets the value of the component to a different value.
-
- The component with the property value that is to be set.
- The new value.
-
-
-
- When overridden in a derived class, determines a value indicating whether the value of this property needs to be persisted.
-
-
- true if the property should be persisted; otherwise, false.
-
- The component with the property to be examined for persistence.
-
-
-
- When overridden in a derived class, gets the type of the component this property is bound to.
-
-
- A that represents the type of component this property is bound to.
- When the or
-
- methods are invoked, the object specified might be an instance of this type.
-
-
-
-
- When overridden in a derived class, gets a value indicating whether this property is read-only.
-
-
- true if the property is read-only; otherwise, false.
-
-
-
-
- When overridden in a derived class, gets the type of the property.
-
-
- A that represents the type of the property.
-
-
-
-
- Gets the hash code for the name of the member.
-
-
-
- The hash code for the name of the member.
-
-
-
-
- Represents a raw JSON string.
-
-
-
-
- Asynchronously creates an instance of with the content of the reader's current token.
-
- The reader.
- The token to monitor for cancellation requests. The default value is .
- A representing the asynchronous creation. The
- property returns an instance of with the content of the reader's current token.
-
-
-
- Initializes a new instance of the class from another object.
-
- A object to copy from.
-
-
-
- Initializes a new instance of the class.
-
- The raw json.
-
-
-
- Creates an instance of with the content of the reader's current token.
-
- The reader.
- An instance of with the content of the reader's current token.
-
-
-
- Specifies the settings used when loading JSON.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Gets or sets how JSON comments are handled when loading JSON.
-
- The JSON comment handling.
-
-
-
- Gets or sets how JSON line info is handled when loading JSON.
-
- The JSON line info handling.
-
-
-
- Specifies the settings used when merging JSON.
-
-
-
-
- Gets or sets the method used when merging JSON arrays.
-
- The method used when merging JSON arrays.
-
-
-
- Gets or sets how null value properties are merged.
-
- How null value properties are merged.
-
-
-
- Represents an abstract JSON token.
-
-
-
-
- Writes this token to a asynchronously.
-
- A into which this method will write.
- The token to monitor for cancellation requests.
- A collection of which will be used when writing the token.
- A that represents the asynchronous write operation.
-
-
-
- Writes this token to a asynchronously.
-
- A into which this method will write.
- A collection of which will be used when writing the token.
- A that represents the asynchronous write operation.
-
-
-
- Asynchronously creates a from a .
-
- An positioned at the token to read into this .
- The token to monitor for cancellation requests. The default value is .
-
- A that represents the asynchronous creation. The
- property returns a that contains
- the token and its descendant tokens
- that were read from the reader. The runtime type of the token is determined
- by the token type of the first token encountered in the reader.
-
-
-
-
- Asynchronously creates a from a .
-
- An positioned at the token to read into this .
- The used to load the JSON.
- If this is null, default load settings will be used.
- The token to monitor for cancellation requests. The default value is .
-
- A that represents the asynchronous creation. The
- property returns a that contains
- the token and its descendant tokens
- that were read from the reader. The runtime type of the token is determined
- by the token type of the first token encountered in the reader.
-
-
-
-
- Asynchronously creates a from a .
-
- A positioned at the token to read into this .
- The token to monitor for cancellation requests. The default value is .
-
- A that represents the asynchronous creation. The
- property returns a that contains the token and its descendant tokens
- that were read from the reader. The runtime type of the token is determined
- by the token type of the first token encountered in the reader.
-
-
-
-
- Asynchronously creates a from a .
-
- A positioned at the token to read into this .
- The used to load the JSON.
- If this is null, default load settings will be used.
- The token to monitor for cancellation requests. The default value is .
-
- A that represents the asynchronous creation. The
- property returns a that contains the token and its descendant tokens
- that were read from the reader. The runtime type of the token is determined
- by the token type of the first token encountered in the reader.
-
-
-
-
- Gets a comparer that can compare two tokens for value equality.
-
- A that can compare two nodes for value equality.
-
-
-
- Gets or sets the parent.
-
- The parent.
-
-
-
- Gets the root of this .
-
- The root of this .
-
-
-
- Gets the node type for this .
-
- The type.
-
-
-
- Gets a value indicating whether this token has child tokens.
-
-
- true if this token has child values; otherwise, false.
-
-
-
-
- Compares the values of two tokens, including the values of all descendant tokens.
-
- The first to compare.
- The second to compare.
- true if the tokens are equal; otherwise false.
-
-
-
- Gets the next sibling token of this node.
-
- The that contains the next sibling token.
-
-
-
- Gets the previous sibling token of this node.
-
- The that contains the previous sibling token.
-
-
-
- Gets the path of the JSON token.
-
-
-
-
- Adds the specified content immediately after this token.
-
- A content object that contains simple content or a collection of content objects to be added after this token.
-
-
-
- Adds the specified content immediately before this token.
-
- A content object that contains simple content or a collection of content objects to be added before this token.
-
-
-
- Returns a collection of the ancestor tokens of this token.
-
- A collection of the ancestor tokens of this token.
-
-
-
- Returns a collection of tokens that contain this token, and the ancestors of this token.
-
- A collection of tokens that contain this token, and the ancestors of this token.
-
-
-
- Returns a collection of the sibling tokens after this token, in document order.
-
- A collection of the sibling tokens after this tokens, in document order.
-
-
-
- Returns a collection of the sibling tokens before this token, in document order.
-
- A collection of the sibling tokens before this token, in document order.
-
-
-
- Gets the with the specified key.
-
- The with the specified key.
-
-
-
- Gets the with the specified key converted to the specified type.
-
- The type to convert the token to.
- The token key.
- The converted token value.
-
-
-
- Get the first child token of this token.
-
- A containing the first child token of the .
-
-
-
- Get the last child token of this token.
-
- A containing the last child token of the .
-
-
-
- Returns a collection of the child tokens of this token, in document order.
-
- An of containing the child tokens of this , in document order.
-
-
-
- Returns a collection of the child tokens of this token, in document order, filtered by the specified type.
-
- The type to filter the child tokens on.
- A containing the child tokens of this , in document order.
-
-
-
- Returns a collection of the child values of this token, in document order.
-
- The type to convert the values to.
- A containing the child values of this , in document order.
-
-
-
- Removes this token from its parent.
-
-
-
-
- Replaces this token with the specified token.
-
- The value.
-
-
-
- Writes this token to a .
-
- A into which this method will write.
- A collection of which will be used when writing the token.
-
-
-
- Returns the indented JSON for this token.
-
-
- The indented JSON for this token.
-
-
-
-
- Returns the JSON for this token using the given formatting and converters.
-
- Indicates how the output should be formatted.
- A collection of s which will be used when writing the token.
- The JSON for this token using the given formatting and converters.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to [].
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from [] to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Creates a for this token.
-
- A that can be used to read this token and its descendants.
-
-
-
- Creates a from an object.
-
- The object that will be used to create .
- A with the value of the specified object.
-
-
-
- Creates a from an object using the specified .
-
- The object that will be used to create .
- The that will be used when reading the object.
- A with the value of the specified object.
-
-
-
- Creates an instance of the specified .NET type from the .
-
- The object type that the token will be deserialized to.
- The new object created from the JSON value.
-
-
-
- Creates an instance of the specified .NET type from the .
-
- The object type that the token will be deserialized to.
- The new object created from the JSON value.
-
-
-
- Creates an instance of the specified .NET type from the using the specified .
-
- The object type that the token will be deserialized to.
- The that will be used when creating the object.
- The new object created from the JSON value.
-
-
-
- Creates an instance of the specified .NET type from the using the specified .
-
- The object type that the token will be deserialized to.
- The that will be used when creating the object.
- The new object created from the JSON value.
-
-
-
- Creates a from a .
-
- A positioned at the token to read into this .
-
- A that contains the token and its descendant tokens
- that were read from the reader. The runtime type of the token is determined
- by the token type of the first token encountered in the reader.
-
-
-
-
- Creates a from a .
-
- An positioned at the token to read into this .
- The used to load the JSON.
- If this is null, default load settings will be used.
-
- A that contains the token and its descendant tokens
- that were read from the reader. The runtime type of the token is determined
- by the token type of the first token encountered in the reader.
-
-
-
-
- Load a from a string that contains JSON.
-
- A that contains JSON.
- A populated from the string that contains JSON.
-
-
-
- Load a from a string that contains JSON.
-
- A that contains JSON.
- The used to load the JSON.
- If this is null, default load settings will be used.
- A populated from the string that contains JSON.
-
-
-
- Creates a from a .
-
- A positioned at the token to read into this .
- The used to load the JSON.
- If this is null, default load settings will be used.
-
- A that contains the token and its descendant tokens
- that were read from the reader. The runtime type of the token is determined
- by the token type of the first token encountered in the reader.
-
-
-
-
- Creates a from a .
-
- A positioned at the token to read into this .
-
- A that contains the token and its descendant tokens
- that were read from the reader. The runtime type of the token is determined
- by the token type of the first token encountered in the reader.
-
-
-
-
- Selects a using a JPath expression. Selects the token that matches the object path.
-
-
- A that contains a JPath expression.
-
- A , or null.
-
-
-
- Selects a using a JPath expression. Selects the token that matches the object path.
-
-
- A that contains a JPath expression.
-
- A flag to indicate whether an error should be thrown if no tokens are found when evaluating part of the expression.
- A .
-
-
-
- Selects a collection of elements using a JPath expression.
-
-
- A that contains a JPath expression.
-
- An of that contains the selected elements.
-
-
-
- Selects a collection of elements using a JPath expression.
-
-
- A that contains a JPath expression.
-
- A flag to indicate whether an error should be thrown if no tokens are found when evaluating part of the expression.
- An of that contains the selected elements.
-
-
-
- Returns the responsible for binding operations performed on this object.
-
- The expression tree representation of the runtime value.
-
- The to bind this object.
-
-
-
-
- Returns the responsible for binding operations performed on this object.
-
- The expression tree representation of the runtime value.
-
- The to bind this object.
-
-
-
-
- Creates a new instance of the . All child tokens are recursively cloned.
-
- A new instance of the .
-
-
-
- Adds an object to the annotation list of this .
-
- The annotation to add.
-
-
-
- Get the first annotation object of the specified type from this .
-
- The type of the annotation to retrieve.
- The first annotation object that matches the specified type, or null if no annotation is of the specified type.
-
-
-
- Gets the first annotation object of the specified type from this .
-
- The of the annotation to retrieve.
- The first annotation object that matches the specified type, or null if no annotation is of the specified type.
-
-
-
- Gets a collection of annotations of the specified type for this .
-
- The type of the annotations to retrieve.
- An that contains the annotations for this .
-
-
-
- Gets a collection of annotations of the specified type for this .
-
- The of the annotations to retrieve.
- An of that contains the annotations that match the specified type for this .
-
-
-
- Removes the annotations of the specified type from this .
-
- The type of annotations to remove.
-
-
-
- Removes the annotations of the specified type from this .
-
- The of annotations to remove.
-
-
-
- Compares tokens to determine whether they are equal.
-
-
-
-
- Determines whether the specified objects are equal.
-
- The first object of type to compare.
- The second object of type to compare.
-
- true if the specified objects are equal; otherwise, false.
-
-
-
-
- Returns a hash code for the specified object.
-
- The for which a hash code is to be returned.
- A hash code for the specified object.
- The type of is a reference type and is null.
-
-
-
- Represents a reader that provides fast, non-cached, forward-only access to serialized JSON data.
-
-
-
-
- Gets the at the reader's current position.
-
-
-
-
- Initializes a new instance of the class.
-
- The token to read from.
-
-
-
- Reads the next JSON token from the underlying .
-
-
- true if the next token was read successfully; false if there are no more tokens to read.
-
-
-
-
- Gets the path of the current JSON token.
-
-
-
-
- Specifies the type of token.
-
-
-
-
- No token type has been set.
-
-
-
-
- A JSON object.
-
-
-
-
- A JSON array.
-
-
-
-
- A JSON constructor.
-
-
-
-
- A JSON object property.
-
-
-
-
- A comment.
-
-
-
-
- An integer value.
-
-
-
-
- A float value.
-
-
-
-
- A string value.
-
-
-
-
- A boolean value.
-
-
-
-
- A null value.
-
-
-
-
- An undefined value.
-
-
-
-
- A date value.
-
-
-
-
- A raw JSON value.
-
-
-
-
- A collection of bytes value.
-
-
-
-
- A Guid value.
-
-
-
-
- A Uri value.
-
-
-
-
- A TimeSpan value.
-
-
-
-
- Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data.
-
-
-
-
- Gets the at the writer's current position.
-
-
-
-
- Gets the token being written.
-
- The token being written.
-
-
-
- Initializes a new instance of the class writing to the given .
-
- The container being written to.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Flushes whatever is in the buffer to the underlying .
-
-
-
-
- Closes this writer.
- If is set to true, the JSON is auto-completed.
-
-
- Setting to true has no additional effect, since the underlying is a type that cannot be closed.
-
-
-
-
- Writes the beginning of a JSON object.
-
-
-
-
- Writes the beginning of a JSON array.
-
-
-
-
- Writes the start of a constructor with the given name.
-
- The name of the constructor.
-
-
-
- Writes the end.
-
- The token.
-
-
-
- Writes the property name of a name/value pair on a JSON object.
-
- The name of the property.
-
-
-
- Writes a value.
- An error will be raised if the value cannot be written as a single JSON token.
-
- The value to write.
-
-
-
- Writes a null value.
-
-
-
-
- Writes an undefined value.
-
-
-
-
- Writes raw JSON.
-
- The raw JSON to write.
-
-
-
- Writes a comment /*...*/ containing the specified text.
-
- Text to place inside the comment.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a [] value.
-
- The [] value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Represents a value in JSON (string, integer, date, etc).
-
-
-
-
- Writes this token to a asynchronously.
-
- A into which this method will write.
- The token to monitor for cancellation requests.
- A collection of which will be used when writing the token.
- A that represents the asynchronous write operation.
-
-
-
- Initializes a new instance of the class from another object.
-
- A object to copy from.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Gets a value indicating whether this token has child tokens.
-
-
- true if this token has child values; otherwise, false.
-
-
-
-
- Creates a comment with the given value.
-
- The value.
- A comment with the given value.
-
-
-
- Creates a string with the given value.
-
- The value.
- A string with the given value.
-
-
-
- Creates a null value.
-
- A null value.
-
-
-
- Creates a undefined value.
-
- A undefined value.
-
-
-
- Gets the node type for this .
-
- The type.
-
-
-
- Gets or sets the underlying token value.
-
- The underlying token value.
-
-
-
- Writes this token to a .
-
- A into which this method will write.
- A collection of s which will be used when writing the token.
-
-
-
- Indicates whether the current object is equal to another object of the same type.
-
-
- true if the current object is equal to the parameter; otherwise, false.
-
- An object to compare with this object.
-
-
-
- Determines whether the specified is equal to the current .
-
- The to compare with the current .
-
- true if the specified is equal to the current ; otherwise, false.
-
-
-
-
- Serves as a hash function for a particular type.
-
-
- A hash code for the current .
-
-
-
-
- Returns a that represents this instance.
-
-
- A that represents this instance.
-
-
-
-
- Returns a that represents this instance.
-
- The format.
-
- A that represents this instance.
-
-
-
-
- Returns a that represents this instance.
-
- The format provider.
-
- A that represents this instance.
-
-
-
-
- Returns a that represents this instance.
-
- The format.
- The format provider.
-
- A that represents this instance.
-
-
-
-
- Returns the responsible for binding operations performed on this object.
-
- The expression tree representation of the runtime value.
-
- The to bind this object.
-
-
-
-
- Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
-
- An object to compare with this instance.
-
- A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has these meanings:
- Value
- Meaning
- Less than zero
- This instance is less than .
- Zero
- This instance is equal to .
- Greater than zero
- This instance is greater than .
-
-
- is not of the same type as this instance.
-
-
-
-
- Specifies how line information is handled when loading JSON.
-
-
-
-
- Ignore line information.
-
-
-
-
- Load line information.
-
-
-
-
- Specifies how JSON arrays are merged together.
-
-
-
- Concatenate arrays.
-
-
- Union arrays, skipping items that already exist.
-
-
- Replace all array items.
-
-
- Merge array items together, matched by index.
-
-
-
- Specifies how null value properties are merged.
-
-
-
-
- The content's null value properties will be ignored during merging.
-
-
-
-
- The content's null value properties will be merged.
-
-
-
-
- Specifies the member serialization options for the .
-
-
-
-
- All public members are serialized by default. Members can be excluded using or .
- This is the default member serialization mode.
-
-
-
-
- Only members marked with or are serialized.
- This member serialization mode can also be set by marking the class with .
-
-
-
-
- All public and private fields are serialized. Members can be excluded using or .
- This member serialization mode can also be set by marking the class with
- and setting IgnoreSerializableAttribute on to false.
-
-
-
-
- Specifies metadata property handling options for the .
-
-
-
-
- Read metadata properties located at the start of a JSON object.
-
-
-
-
- Read metadata properties located anywhere in a JSON object. Note that this setting will impact performance.
-
-
-
-
- Do not try to read metadata properties.
-
-
-
-
- Specifies missing member handling options for the .
-
-
-
-
- Ignore a missing member and do not attempt to deserialize it.
-
-
-
-
- Throw a when a missing member is encountered during deserialization.
-
-
-
-
- Specifies null value handling options for the .
-
-
-
-
-
-
-
-
- Include null values when serializing and deserializing objects.
-
-
-
-
- Ignore null values when serializing and deserializing objects.
-
-
-
-
- Specifies how object creation is handled by the .
-
-
-
-
- Reuse existing objects, create new objects when needed.
-
-
-
-
- Only reuse existing objects.
-
-
-
-
- Always create new objects.
-
-
-
-
- Specifies reference handling options for the .
- Note that references cannot be preserved when a value is set via a non-default constructor such as types that implement .
-
-
-
-
-
-
-
- Do not preserve references when serializing types.
-
-
-
-
- Preserve references when serializing into a JSON object structure.
-
-
-
-
- Preserve references when serializing into a JSON array structure.
-
-
-
-
- Preserve references when serializing.
-
-
-
-
- Specifies reference loop handling options for the .
-
-
-
-
- Throw a when a loop is encountered.
-
-
-
-
- Ignore loop references and do not serialize.
-
-
-
-
- Serialize loop references.
-
-
-
-
- Indicating whether a property is required.
-
-
-
-
- The property is not required. The default state.
-
-
-
-
- The property must be defined in JSON but can be a null value.
-
-
-
-
- The property must be defined in JSON and cannot be a null value.
-
-
-
-
- The property is not required but it cannot be a null value.
-
-
-
-
-
- Contains the JSON schema extension methods.
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
-
- Determines whether the is valid.
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
- The source to test.
- The schema to test with.
-
- true if the specified is valid; otherwise, false.
-
-
-
-
-
- Determines whether the is valid.
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
- The source to test.
- The schema to test with.
- When this method returns, contains any error messages generated while validating.
-
- true if the specified is valid; otherwise, false.
-
-
-
-
-
- Validates the specified .
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
- The source to test.
- The schema to test with.
-
-
-
-
- Validates the specified .
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
- The source to test.
- The schema to test with.
- The validation event handler.
-
-
-
-
- An in-memory representation of a JSON Schema.
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- Gets or sets the id.
-
-
-
-
- Gets or sets the title.
-
-
-
-
- Gets or sets whether the object is required.
-
-
-
-
- Gets or sets whether the object is read-only.
-
-
-
-
- Gets or sets whether the object is visible to users.
-
-
-
-
- Gets or sets whether the object is transient.
-
-
-
-
- Gets or sets the description of the object.
-
-
-
-
- Gets or sets the types of values allowed by the object.
-
- The type.
-
-
-
- Gets or sets the pattern.
-
- The pattern.
-
-
-
- Gets or sets the minimum length.
-
- The minimum length.
-
-
-
- Gets or sets the maximum length.
-
- The maximum length.
-
-
-
- Gets or sets a number that the value should be divisible by.
-
- A number that the value should be divisible by.
-
-
-
- Gets or sets the minimum.
-
- The minimum.
-
-
-
- Gets or sets the maximum.
-
- The maximum.
-
-
-
- Gets or sets a flag indicating whether the value can not equal the number defined by the minimum attribute ().
-
- A flag indicating whether the value can not equal the number defined by the minimum attribute ().
-
-
-
- Gets or sets a flag indicating whether the value can not equal the number defined by the maximum attribute ().
-
- A flag indicating whether the value can not equal the number defined by the maximum attribute ().
-
-
-
- Gets or sets the minimum number of items.
-
- The minimum number of items.
-
-
-
- Gets or sets the maximum number of items.
-
- The maximum number of items.
-
-
-
- Gets or sets the of items.
-
- The of items.
-
-
-
- Gets or sets a value indicating whether items in an array are validated using the instance at their array position from .
-
-
- true if items are validated using their array position; otherwise, false.
-
-
-
-
- Gets or sets the of additional items.
-
- The of additional items.
-
-
-
- Gets or sets a value indicating whether additional items are allowed.
-
-
- true if additional items are allowed; otherwise, false.
-
-
-
-
- Gets or sets whether the array items must be unique.
-
-
-
-
- Gets or sets the of properties.
-
- The of properties.
-
-
-
- Gets or sets the of additional properties.
-
- The of additional properties.
-
-
-
- Gets or sets the pattern properties.
-
- The pattern properties.
-
-
-
- Gets or sets a value indicating whether additional properties are allowed.
-
-
- true if additional properties are allowed; otherwise, false.
-
-
-
-
- Gets or sets the required property if this property is present.
-
- The required property if this property is present.
-
-
-
- Gets or sets the a collection of valid enum values allowed.
-
- A collection of valid enum values allowed.
-
-
-
- Gets or sets disallowed types.
-
- The disallowed types.
-
-
-
- Gets or sets the default value.
-
- The default value.
-
-
-
- Gets or sets the collection of that this schema extends.
-
- The collection of that this schema extends.
-
-
-
- Gets or sets the format.
-
- The format.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Reads a from the specified .
-
- The containing the JSON Schema to read.
- The object representing the JSON Schema.
-
-
-
- Reads a from the specified .
-
- The containing the JSON Schema to read.
- The to use when resolving schema references.
- The object representing the JSON Schema.
-
-
-
- Load a from a string that contains JSON Schema.
-
- A that contains JSON Schema.
- A populated from the string that contains JSON Schema.
-
-
-
- Load a from a string that contains JSON Schema using the specified .
-
- A that contains JSON Schema.
- The resolver.
- A populated from the string that contains JSON Schema.
-
-
-
- Writes this schema to a .
-
- A into which this method will write.
-
-
-
- Writes this schema to a using the specified .
-
- A into which this method will write.
- The resolver used.
-
-
-
- Returns a that represents the current .
-
-
- A that represents the current .
-
-
-
-
-
- Returns detailed information about the schema exception.
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- Gets the line number indicating where the error occurred.
-
- The line number indicating where the error occurred.
-
-
-
- Gets the line position indicating where the error occurred.
-
- The line position indicating where the error occurred.
-
-
-
- Gets the path to the JSON where the error occurred.
-
- The path to the JSON where the error occurred.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class
- with a specified error message.
-
- The error message that explains the reason for the exception.
-
-
-
- Initializes a new instance of the class
- with a specified error message and a reference to the inner exception that is the cause of this exception.
-
- The error message that explains the reason for the exception.
- The exception that is the cause of the current exception, or null if no inner exception is specified.
-
-
-
-
- Generates a from a specified .
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- Gets or sets how undefined schemas are handled by the serializer.
-
-
-
-
- Gets or sets the contract resolver.
-
- The contract resolver.
-
-
-
- Generate a from the specified type.
-
- The type to generate a from.
- A generated from the specified type.
-
-
-
- Generate a from the specified type.
-
- The type to generate a from.
- The used to resolve schema references.
- A generated from the specified type.
-
-
-
- Generate a from the specified type.
-
- The type to generate a from.
- Specify whether the generated root will be nullable.
- A generated from the specified type.
-
-
-
- Generate a from the specified type.
-
- The type to generate a from.
- The used to resolve schema references.
- Specify whether the generated root will be nullable.
- A generated from the specified type.
-
-
-
-
- Resolves from an id.
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- Gets or sets the loaded schemas.
-
- The loaded schemas.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Gets a for the specified reference.
-
- The id.
- A for the specified reference.
-
-
-
-
- The value types allowed by the .
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- No type specified.
-
-
-
-
- String type.
-
-
-
-
- Float type.
-
-
-
-
- Integer type.
-
-
-
-
- Boolean type.
-
-
-
-
- Object type.
-
-
-
-
- Array type.
-
-
-
-
- Null type.
-
-
-
-
- Any type.
-
-
-
-
-
- Specifies undefined schema Id handling options for the .
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- Do not infer a schema Id.
-
-
-
-
- Use the .NET type name as the schema Id.
-
-
-
-
- Use the assembly qualified .NET type name as the schema Id.
-
-
-
-
-
- Returns detailed information related to the .
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- Gets the associated with the validation error.
-
- The JsonSchemaException associated with the validation error.
-
-
-
- Gets the path of the JSON location where the validation error occurred.
-
- The path of the JSON location where the validation error occurred.
-
-
-
- Gets the text description corresponding to the validation error.
-
- The text description.
-
-
-
-
- Represents the callback method that will handle JSON schema validation events and the .
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- A camel case naming strategy.
-
-
-
-
- Initializes a new instance of the class.
-
-
- A flag indicating whether dictionary keys should be processed.
-
-
- A flag indicating whether explicitly specified property names should be processed,
- e.g. a property name customized with a .
-
-
-
-
- Initializes a new instance of the class.
-
-
- A flag indicating whether dictionary keys should be processed.
-
-
- A flag indicating whether explicitly specified property names should be processed,
- e.g. a property name customized with a .
-
-
- A flag indicating whether extension data names should be processed.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Resolves the specified property name.
-
- The property name to resolve.
- The resolved property name.
-
-
-
- Resolves member mappings for a type, camel casing property names.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Resolves the contract for a given type.
-
- The type to resolve a contract for.
- The contract for a given type.
-
-
-
- Used by to resolve a for a given .
-
-
-
-
- Gets a value indicating whether members are being get and set using dynamic code generation.
- This value is determined by the runtime permissions available.
-
-
- true if using dynamic code generation; otherwise, false.
-
-
-
-
- Gets or sets the default members search flags.
-
- The default members search flags.
-
-
-
- Gets or sets a value indicating whether compiler generated members should be serialized.
-
-
- true if serialized compiler generated members; otherwise, false.
-
-
-
-
- Gets or sets a value indicating whether to ignore the interface when serializing and deserializing types.
-
-
- true if the interface will be ignored when serializing and deserializing types; otherwise, false.
-
-
-
-
- Gets or sets a value indicating whether to ignore the attribute when serializing and deserializing types.
-
-
- true if the attribute will be ignored when serializing and deserializing types; otherwise, false.
-
-
-
-
- Gets or sets a value indicating whether to ignore IsSpecified members when serializing and deserializing types.
-
-
- true if the IsSpecified members will be ignored when serializing and deserializing types; otherwise, false.
-
-
-
-
- Gets or sets a value indicating whether to ignore ShouldSerialize members when serializing and deserializing types.
-
-
- true if the ShouldSerialize members will be ignored when serializing and deserializing types; otherwise, false.
-
-
-
-
- Gets or sets the naming strategy used to resolve how property names and dictionary keys are serialized.
-
- The naming strategy used to resolve how property names and dictionary keys are serialized.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Resolves the contract for a given type.
-
- The type to resolve a contract for.
- The contract for a given type.
-
-
-
- Gets the serializable members for the type.
-
- The type to get serializable members for.
- The serializable members for the type.
-
-
-
- Creates a for the given type.
-
- Type of the object.
- A for the given type.
-
-
-
- Creates the constructor parameters.
-
- The constructor to create properties for.
- The type's member properties.
- Properties for the given .
-
-
-
- Creates a for the given .
-
- The matching member property.
- The constructor parameter.
- A created for the given .
-
-
-
- Resolves the default for the contract.
-
- Type of the object.
- The contract's default .
-
-
-
- Creates a for the given type.
-
- Type of the object.
- A for the given type.
-
-
-
- Creates a for the given type.
-
- Type of the object.
- A for the given type.
-
-
-
- Creates a for the given type.
-
- Type of the object.
- A for the given type.
-
-
-
- Creates a for the given type.
-
- Type of the object.
- A for the given type.
-
-
-
- Creates a for the given type.
-
- Type of the object.
- A for the given type.
-
-
-
- Creates a for the given type.
-
- Type of the object.
- A for the given type.
-
-
-
- Determines which contract type is created for the given type.
-
- Type of the object.
- A for the given type.
-
-
-
- Creates properties for the given .
-
- The type to create properties for.
- /// The member serialization mode for the type.
- Properties for the given .
-
-
-
- Creates the used by the serializer to get and set values from a member.
-
- The member.
- The used by the serializer to get and set values from a member.
-
-
-
- Creates a for the given .
-
- The member's parent .
- The member to create a for.
- A created for the given .
-
-
-
- Resolves the name of the property.
-
- Name of the property.
- Resolved name of the property.
-
-
-
- Resolves the name of the extension data. By default no changes are made to extension data names.
-
- Name of the extension data.
- Resolved name of the extension data.
-
-
-
- Resolves the key of the dictionary. By default is used to resolve dictionary keys.
-
- Key of the dictionary.
- Resolved key of the dictionary.
-
-
-
- Gets the resolved name of the property.
-
- Name of the property.
- Name of the property.
-
-
-
- The default naming strategy. Property names and dictionary keys are unchanged.
-
-
-
-
- Resolves the specified property name.
-
- The property name to resolve.
- The resolved property name.
-
-
-
- The default serialization binder used when resolving and loading classes from type names.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- When overridden in a derived class, controls the binding of a serialized object to a type.
-
- Specifies the name of the serialized object.
- Specifies the name of the serialized object.
-
- The type of the object the formatter creates a new instance of.
-
-
-
-
- When overridden in a derived class, controls the binding of a serialized object to a type.
-
- The type of the object the formatter creates a new instance of.
- Specifies the name of the serialized object.
- Specifies the name of the serialized object.
-
-
-
- Provides information surrounding an error.
-
-
-
-
- Gets the error.
-
- The error.
-
-
-
- Gets the original object that caused the error.
-
- The original object that caused the error.
-
-
-
- Gets the member that caused the error.
-
- The member that caused the error.
-
-
-
- Gets the path of the JSON location where the error occurred.
-
- The path of the JSON location where the error occurred.
-
-
-
- Gets or sets a value indicating whether this is handled.
-
- true if handled; otherwise, false.
-
-
-
- Provides data for the Error event.
-
-
-
-
- Gets the current object the error event is being raised against.
-
- The current object the error event is being raised against.
-
-
-
- Gets the error context.
-
- The error context.
-
-
-
- Initializes a new instance of the class.
-
- The current object.
- The error context.
-
-
-
- Get and set values for a using dynamic methods.
-
-
-
-
- Initializes a new instance of the class.
-
- The member info.
-
-
-
- Sets the value.
-
- The target to set the value on.
- The value to set on the target.
-
-
-
- Gets the value.
-
- The target to get the value from.
- The value.
-
-
-
- Provides methods to get attributes.
-
-
-
-
- Returns a collection of all of the attributes, or an empty collection if there are no attributes.
-
- When true, look up the hierarchy chain for the inherited custom attribute.
- A collection of s, or an empty collection.
-
-
-
- Returns a collection of attributes, identified by type, or an empty collection if there are no attributes.
-
- The type of the attributes.
- When true, look up the hierarchy chain for the inherited custom attribute.
- A collection of s, or an empty collection.
-
-
-
- Used by to resolve a for a given .
-
-
-
-
-
-
-
-
- Resolves the contract for a given type.
-
- The type to resolve a contract for.
- The contract for a given type.
-
-
-
- Used to resolve references when serializing and deserializing JSON by the .
-
-
-
-
- Resolves a reference to its object.
-
- The serialization context.
- The reference to resolve.
- The object that was resolved from the reference.
-
-
-
- Gets the reference for the specified object.
-
- The serialization context.
- The object to get a reference for.
- The reference to the object.
-
-
-
- Determines whether the specified object is referenced.
-
- The serialization context.
- The object to test for a reference.
-
- true if the specified object is referenced; otherwise, false.
-
-
-
-
- Adds a reference to the specified object.
-
- The serialization context.
- The reference.
- The object to reference.
-
-
-
- Allows users to control class loading and mandate what class to load.
-
-
-
-
- When implemented, controls the binding of a serialized object to a type.
-
- Specifies the name of the serialized object.
- Specifies the name of the serialized object
- The type of the object the formatter creates a new instance of.
-
-
-
- When implemented, controls the binding of a serialized object to a type.
-
- The type of the object the formatter creates a new instance of.
- Specifies the name of the serialized object.
- Specifies the name of the serialized object.
-
-
-
- Provides methods to get and set values.
-
-
-
-
- Sets the value.
-
- The target to set the value on.
- The value to set on the target.
-
-
-
- Gets the value.
-
- The target to get the value from.
- The value.
-
-
-
- Contract details for a used by the .
-
-
-
-
- Gets the of the collection items.
-
- The of the collection items.
-
-
-
- Gets a value indicating whether the collection type is a multidimensional array.
-
- true if the collection type is a multidimensional array; otherwise, false.
-
-
-
- Gets or sets the function used to create the object. When set this function will override .
-
- The function used to create the object.
-
-
-
- Gets a value indicating whether the creator has a parameter with the collection values.
-
- true if the creator has a parameter with the collection values; otherwise, false.
-
-
-
- Initializes a new instance of the class.
-
- The underlying type for the contract.
-
-
-
- Contract details for a used by the .
-
-
-
-
- Gets or sets the default collection items .
-
- The converter.
-
-
-
- Gets or sets a value indicating whether the collection items preserve object references.
-
- true if collection items preserve object references; otherwise, false.
-
-
-
- Gets or sets the collection item reference loop handling.
-
- The reference loop handling.
-
-
-
- Gets or sets the collection item type name handling.
-
- The type name handling.
-
-
-
- Initializes a new instance of the class.
-
- The underlying type for the contract.
-
-
-
- Sets extension data for an object during deserialization.
-
- The object to set extension data on.
- The extension data key.
- The extension data value.
-
-
-
- Gets extension data for an object during serialization.
-
- The object to set extension data on.
-
-
-
- Contract details for a used by the .
-
-
-
-
- Gets the underlying type for the contract.
-
- The underlying type for the contract.
-
-
-
- Gets or sets the type created during deserialization.
-
- The type created during deserialization.
-
-
-
- Gets or sets whether this type contract is serialized as a reference.
-
- Whether this type contract is serialized as a reference.
-
-
-
- Gets or sets the default for this contract.
-
- The converter.
-
-
-
- Gets or sets the default creator method used to create the object.
-
- The default creator method used to create the object.
-
-
-
- Gets or sets a value indicating whether the default creator is non-public.
-
- true if the default object creator is non-public; otherwise, false.
-
-
-
- Contract details for a used by the .
-
-
-
-
- Gets or sets the dictionary key resolver.
-
- The dictionary key resolver.
-
-
-
- Gets the of the dictionary keys.
-
- The of the dictionary keys.
-
-
-
- Gets the of the dictionary values.
-
- The of the dictionary values.
-
-
-
- Gets or sets the function used to create the object. When set this function will override .
-
- The function used to create the object.
-
-
-
- Gets a value indicating whether the creator has a parameter with the dictionary values.
-
- true if the creator has a parameter with the dictionary values; otherwise, false.
-
-
-
- Initializes a new instance of the class.
-
- The underlying type for the contract.
-
-
-
- Contract details for a used by the .
-
-
-
-
- Gets the object's properties.
-
- The object's properties.
-
-
-
- Gets or sets the property name resolver.
-
- The property name resolver.
-
-
-
- Initializes a new instance of the class.
-
- The underlying type for the contract.
-
-
-
- Contract details for a used by the .
-
-
-
-
- Initializes a new instance of the class.
-
- The underlying type for the contract.
-
-
-
- Contract details for a used by the .
-
-
-
-
- Gets or sets the object member serialization.
-
- The member object serialization.
-
-
-
- Gets or sets a value that indicates whether the object's properties are required.
-
-
- A value indicating whether the object's properties are required.
-
-
-
-
- Gets or sets how the object's properties with null values are handled during serialization and deserialization.
-
- How the object's properties with null values are handled during serialization and deserialization.
-
-
-
- Gets the object's properties.
-
- The object's properties.
-
-
-
- Gets a collection of instances that define the parameters used with .
-
-
-
-
- Gets or sets the function used to create the object. When set this function will override .
- This function is called with a collection of arguments which are defined by the collection.
-
- The function used to create the object.
-
-
-
- Gets or sets the extension data setter.
-
-
-
-
- Gets or sets the extension data getter.
-
-
-
-
- Gets or sets the extension data value type.
-
-
-
-
- Gets or sets the extension data name resolver.
-
- The extension data name resolver.
-
-
-
- Initializes a new instance of the class.
-
- The underlying type for the contract.
-
-
-
- Contract details for a used by the .
-
-
-
-
- Initializes a new instance of the class.
-
- The underlying type for the contract.
-
-
-
- Maps a JSON property to a .NET member or constructor parameter.
-
-
-
-
- Gets or sets the name of the property.
-
- The name of the property.
-
-
-
- Gets or sets the type that declared this property.
-
- The type that declared this property.
-
-
-
- Gets or sets the order of serialization of a member.
-
- The numeric order of serialization.
-
-
-
- Gets or sets the name of the underlying member or parameter.
-
- The name of the underlying member or parameter.
-
-
-
- Gets the that will get and set the during serialization.
-
- The that will get and set the during serialization.
-
-
-
- Gets or sets the for this property.
-
- The for this property.
-
-
-
- Gets or sets the type of the property.
-
- The type of the property.
-
-
-
- Gets or sets the for the property.
- If set this converter takes precedence over the contract converter for the property type.
-
- The converter.
-
-
-
- Gets or sets the member converter.
-
- The member converter.
-
-
-
- Gets or sets a value indicating whether this is ignored.
-
- true if ignored; otherwise, false.
-
-
-
- Gets or sets a value indicating whether this is readable.
-
- true if readable; otherwise, false.
-
-
-
- Gets or sets a value indicating whether this is writable.
-
- true if writable; otherwise, false.
-
-
-
- Gets or sets a value indicating whether this has a member attribute.
-
- true if has a member attribute; otherwise, false.
-
-
-
- Gets the default value.
-
- The default value.
-
-
-
- Gets or sets a value indicating whether this is required.
-
- A value indicating whether this is required.
-
-
-
- Gets or sets a value indicating whether this property preserves object references.
-
-
- true if this instance is reference; otherwise, false.
-
-
-
-
- Gets or sets the property null value handling.
-
- The null value handling.
-
-
-
- Gets or sets the property default value handling.
-
- The default value handling.
-
-
-
- Gets or sets the property reference loop handling.
-
- The reference loop handling.
-
-
-
- Gets or sets the property object creation handling.
-
- The object creation handling.
-
-
-
- Gets or sets or sets the type name handling.
-
- The type name handling.
-
-
-
- Gets or sets a predicate used to determine whether the property should be serialized.
-
- A predicate used to determine whether the property should be serialized.
-
-
-
- Gets or sets a predicate used to determine whether the property should be deserialized.
-
- A predicate used to determine whether the property should be deserialized.
-
-
-
- Gets or sets a predicate used to determine whether the property should be serialized.
-
- A predicate used to determine whether the property should be serialized.
-
-
-
- Gets or sets an action used to set whether the property has been deserialized.
-
- An action used to set whether the property has been deserialized.
-
-
-
- Returns a that represents this instance.
-
-
- A that represents this instance.
-
-
-
-
- Gets or sets the converter used when serializing the property's collection items.
-
- The collection's items converter.
-
-
-
- Gets or sets whether this property's collection items are serialized as a reference.
-
- Whether this property's collection items are serialized as a reference.
-
-
-
- Gets or sets the type name handling used when serializing the property's collection items.
-
- The collection's items type name handling.
-
-
-
- Gets or sets the reference loop handling used when serializing the property's collection items.
-
- The collection's items reference loop handling.
-
-
-
- A collection of objects.
-
-
-
-
- Initializes a new instance of the class.
-
- The type.
-
-
-
- When implemented in a derived class, extracts the key from the specified element.
-
- The element from which to extract the key.
- The key for the specified element.
-
-
-
- Adds a object.
-
- The property to add to the collection.
-
-
-
- Gets the closest matching object.
- First attempts to get an exact case match of and then
- a case insensitive match.
-
- Name of the property.
- A matching property if found.
-
-
-
- Gets a property by property name.
-
- The name of the property to get.
- Type property name string comparison.
- A matching property if found.
-
-
-
- The JSON writer.
-
-
-
-
-
- Gets the size of the serialize stack (amount of the objects serialized in the hierachy before the current).
-
-
-
-
- Contract details for a used by the .
-
-
-
-
- Initializes a new instance of the class.
-
- The underlying type for the contract.
-
-
-
- Lookup and create an instance of the type described by the argument.
-
- The type to create.
- Optional arguments to pass to an initializing constructor of the JsonConverter.
- If null, the default constructor is used.
-
-
-
- A base class for resolving how property names and dictionary keys are serialized.
-
-
-
-
- A flag indicating whether dictionary keys should be processed.
- Defaults to false.
-
-
-
-
- A flag indicating whether extension data names should be processed.
- Defaults to false.
-
-
-
-
- A flag indicating whether explicitly specified property names,
- e.g. a property name customized with a , should be processed.
- Defaults to false.
-
-
-
-
- Gets the serialized name for a given property name.
-
- The initial property name.
- A flag indicating whether the property has had a name explicitly specified.
- The serialized property name.
-
-
-
- Gets the serialized name for a given extension data name.
-
- The initial extension data name.
- The serialized extension data name.
-
-
-
- Gets the serialized key for a given dictionary key.
-
- The initial dictionary key.
- The serialized dictionary key.
-
-
-
- Resolves the specified property name.
-
- The property name to resolve.
- The resolved property name.
-
-
-
- Represents a method that constructs an object.
-
- The object type to create.
-
-
-
- When applied to a method, specifies that the method is called when an error occurs serializing an object.
-
-
-
-
- Provides methods to get attributes from a , , or .
-
-
-
-
- Initializes a new instance of the class.
-
- The instance to get attributes for. This parameter should be a , , or .
-
-
-
- Returns a collection of all of the attributes, or an empty collection if there are no attributes.
-
- When true, look up the hierarchy chain for the inherited custom attribute.
- A collection of s, or an empty collection.
-
-
-
- Returns a collection of attributes, identified by type, or an empty collection if there are no attributes.
-
- The type of the attributes.
- When true, look up the hierarchy chain for the inherited custom attribute.
- A collection of s, or an empty collection.
-
-
-
- Get and set values for a using reflection.
-
-
-
-
- Initializes a new instance of the class.
-
- The member info.
-
-
-
- Sets the value.
-
- The target to set the value on.
- The value to set on the target.
-
-
-
- Gets the value.
-
- The target to get the value from.
- The value.
-
-
-
- A snake case naming strategy.
-
-
-
-
- Initializes a new instance of the class.
-
-
- A flag indicating whether dictionary keys should be processed.
-
-
- A flag indicating whether explicitly specified property names should be processed,
- e.g. a property name customized with a .
-
-
-
-
- Initializes a new instance of the class.
-
-
- A flag indicating whether dictionary keys should be processed.
-
-
- A flag indicating whether explicitly specified property names should be processed,
- e.g. a property name customized with a .
-
-
- A flag indicating whether extension data names should be processed.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Resolves the specified property name.
-
- The property name to resolve.
- The resolved property name.
-
-
-
- Specifies how strings are escaped when writing JSON text.
-
-
-
-
- Only control characters (e.g. newline) are escaped.
-
-
-
-
- All non-ASCII and control characters (e.g. newline) are escaped.
-
-
-
-
- HTML (<, >, &, ', ") and control characters (e.g. newline) are escaped.
-
-
-
-
- Indicates the method that will be used during deserialization for locating and loading assemblies.
-
-
-
-
- In simple mode, the assembly used during deserialization need not match exactly the assembly used during serialization. Specifically, the version numbers need not match as the LoadWithPartialName method of the class is used to load the assembly.
-
-
-
-
- In full mode, the assembly used during deserialization must match exactly the assembly used during serialization. The Load method of the class is used to load the assembly.
-
-
-
-
- Specifies type name handling options for the .
-
-
- should be used with caution when your application deserializes JSON from an external source.
- Incoming types should be validated with a custom
- when deserializing with a value other than .
-
-
-
-
- Do not include the .NET type name when serializing types.
-
-
-
-
- Include the .NET type name when serializing into a JSON object structure.
-
-
-
-
- Include the .NET type name when serializing into a JSON array structure.
-
-
-
-
- Always include the .NET type name when serializing.
-
-
-
-
- Include the .NET type name when the type of the object being serialized is not the same as its declared type.
- Note that this doesn't include the root serialized object by default. To include the root object's type name in JSON
- you must specify a root type object with
- or .
-
-
-
-
- Determines whether the collection is null or empty.
-
- The collection.
-
- true if the collection is null or empty; otherwise, false.
-
-
-
-
- Adds the elements of the specified collection to the specified generic .
-
- The list to add to.
- The collection of elements to add.
-
-
-
- Converts the value to the specified type. If the value is unable to be converted, the
- value is checked whether it assignable to the specified type.
-
- The value to convert.
- The culture to use when converting.
- The type to convert or cast the value to.
-
- The converted type. If conversion was unsuccessful, the initial value
- is returned if assignable to the target type.
-
-
-
-
- Helper method for generating a MetaObject which calls a
- specific method on Dynamic that returns a result
-
-
-
-
- Helper method for generating a MetaObject which calls a
- specific method on Dynamic, but uses one of the arguments for
- the result.
-
-
-
-
- Helper method for generating a MetaObject which calls a
- specific method on Dynamic, but uses one of the arguments for
- the result.
-
-
-
-
- Returns a Restrictions object which includes our current restrictions merged
- with a restriction limiting our type
-
-
-
-
- Helper class for serializing immutable collections.
- Note that this is used by all builds, even those that don't support immutable collections, in case the DLL is GACed
- https://github.com/JamesNK/Newtonsoft.Json/issues/652
-
-
-
-
- Helper utilities.
-
-
-
-
- Compares two objects data.
-
- The object a.
- The object b.
- True if both objects are equal, otherwise false.
-
-
-
- The custom value comparision callback.
-
-
-
-
- The default implementation of the values comparision function.
-
- The object a.
- The object b.
- True if both objects are equal, otherwise false.
-
-
-
- Gets the type of the typed collection's items.
-
- The type.
- The type of the typed collection's items.
-
-
-
- Gets the member's underlying type.
-
- The member.
- The underlying type of the member.
-
-
-
- Determines whether the member is an indexed property.
-
- The member.
-
- true if the member is an indexed property; otherwise, false.
-
-
-
-
- Determines whether the property is an indexed property.
-
- The property.
-
- true if the property is an indexed property; otherwise, false.
-
-
-
-
- Gets the member's value on the object.
-
- The member.
- The target object.
- The member's value on the object.
-
-
-
- Sets the member's value on the target object.
-
- The member.
- The target.
- The value.
-
-
-
- Determines whether the specified MemberInfo can be read.
-
- The MemberInfo to determine whether can be read.
- /// if set to true then allow the member to be gotten non-publicly.
-
- true if the specified MemberInfo can be read; otherwise, false.
-
-
-
-
- Determines whether the specified MemberInfo can be set.
-
- The MemberInfo to determine whether can be set.
- if set to true then allow the member to be set non-publicly.
- if set to true then allow the member to be set if read-only.
-
- true if the specified MemberInfo can be set; otherwise, false.
-
-
-
-
- Builds a string. Unlike this class lets you reuse its internal buffer.
-
-
-
-
- Determines whether the string is all white space. Empty string will return false.
-
- The string to test whether it is all white space.
-
- true if the string is all white space; otherwise, false.
-
-
-
-
- Specifies the state of the .
-
-
-
-
- An exception has been thrown, which has left the in an invalid state.
- You may call the method to put the in the Closed state.
- Any other method calls result in an being thrown.
-
-
-
-
- The method has been called.
-
-
-
-
- An object is being written.
-
-
-
-
- An array is being written.
-
-
-
-
- A constructor is being written.
-
-
-
-
- A property is being written.
-
-
-
-
- A write method has not been called.
-
-
-
-
diff --git a/Source/Platforms/XboxOne/Binaries/Newtonsoft.Json.pdb b/Source/Platforms/XboxOne/Binaries/Newtonsoft.Json.pdb
deleted file mode 100644
index ae45100f6..000000000
--- a/Source/Platforms/XboxOne/Binaries/Newtonsoft.Json.pdb
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:b999346525f40ccb72ecbc560462d94c8c2cce6fa515722b8f2a53f0fa334b4f
-size 236420
diff --git a/Source/Platforms/XboxOne/Binaries/Newtonsoft.Json.xml b/Source/Platforms/XboxOne/Binaries/Newtonsoft.Json.xml
deleted file mode 100644
index 5e472c8a0..000000000
--- a/Source/Platforms/XboxOne/Binaries/Newtonsoft.Json.xml
+++ /dev/null
@@ -1,10588 +0,0 @@
-
-
-
- Newtonsoft.Json
-
-
-
-
- Represents a BSON Oid (object id).
-
-
-
-
- Gets or sets the value of the Oid.
-
- The value of the Oid.
-
-
-
- Initializes a new instance of the class.
-
- The Oid value.
-
-
-
- Represents a reader that provides fast, non-cached, forward-only access to serialized BSON data.
-
-
-
-
- Gets or sets a value indicating whether binary data reading should be compatible with incorrect Json.NET 3.5 written binary.
-
-
- true if binary data reading will be compatible with incorrect Json.NET 3.5 written binary; otherwise, false.
-
-
-
-
- Gets or sets a value indicating whether the root object will be read as a JSON array.
-
-
- true if the root object will be read as a JSON array; otherwise, false.
-
-
-
-
- Gets or sets the used when reading values from BSON.
-
- The used when reading values from BSON.
-
-
-
- Initializes a new instance of the class.
-
- The containing the BSON data to read.
-
-
-
- Initializes a new instance of the class.
-
- The containing the BSON data to read.
-
-
-
- Initializes a new instance of the class.
-
- The containing the BSON data to read.
- if set to true the root object will be read as a JSON array.
- The used when reading values from BSON.
-
-
-
- Initializes a new instance of the class.
-
- The containing the BSON data to read.
- if set to true the root object will be read as a JSON array.
- The used when reading values from BSON.
-
-
-
- Reads the next JSON token from the underlying .
-
-
- true if the next token was read successfully; false if there are no more tokens to read.
-
-
-
-
- Changes the reader's state to .
- If is set to true, the underlying is also closed.
-
-
-
-
- Represents a writer that provides a fast, non-cached, forward-only way of generating BSON data.
-
-
-
-
- Gets or sets the used when writing values to BSON.
- When set to no conversion will occur.
-
- The used when writing values to BSON.
-
-
-
- Initializes a new instance of the class.
-
- The to write to.
-
-
-
- Initializes a new instance of the class.
-
- The to write to.
-
-
-
- Flushes whatever is in the buffer to the underlying and also flushes the underlying stream.
-
-
-
-
- Writes the end.
-
- The token.
-
-
-
- Writes a comment /*...*/ containing the specified text.
-
- Text to place inside the comment.
-
-
-
- Writes the start of a constructor with the given name.
-
- The name of the constructor.
-
-
-
- Writes raw JSON.
-
- The raw JSON to write.
-
-
-
- Writes raw JSON where a value is expected and updates the writer's state.
-
- The raw JSON to write.
-
-
-
- Writes the beginning of a JSON array.
-
-
-
-
- Writes the beginning of a JSON object.
-
-
-
-
- Writes the property name of a name/value pair on a JSON object.
-
- The name of the property.
-
-
-
- Closes this writer.
- If is set to true, the underlying is also closed.
- If is set to true, the JSON is auto-completed.
-
-
-
-
- Writes a value.
- An error will raised if the value cannot be written as a single JSON token.
-
- The value to write.
-
-
-
- Writes a null value.
-
-
-
-
- Writes an undefined value.
-
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a [] value.
-
- The [] value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a [] value that represents a BSON object id.
-
- The Object ID value to write.
-
-
-
- Writes a BSON regex.
-
- The regex pattern.
- The regex options.
-
-
-
- Specifies how constructors are used when initializing objects during deserialization by the .
-
-
-
-
- First attempt to use the public default constructor, then fall back to a single parameterized constructor, then to the non-public default constructor.
-
-
-
-
- Json.NET will use a non-public default constructor before falling back to a parameterized constructor.
-
-
-
-
- Converts a binary value to and from a base 64 string value.
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Converts a to and from JSON and BSON.
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Creates a custom object.
-
- The object type to convert.
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Creates an object which will then be populated by the serializer.
-
- Type of the object.
- The created object.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Gets a value indicating whether this can write JSON.
-
-
- true if this can write JSON; otherwise, false.
-
-
-
-
- Provides a base class for converting a to and from JSON.
-
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Converts an to and from JSON.
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Gets a value indicating whether this can write JSON.
-
-
- true if this can write JSON; otherwise, false.
-
-
-
-
- Converts a to and from the ISO 8601 date format (e.g. "2008-04-12T12:53Z").
-
-
-
-
- Gets or sets the date time styles used when converting a date to and from JSON.
-
- The date time styles used when converting a date to and from JSON.
-
-
-
- Gets or sets the date time format used when converting a date to and from JSON.
-
- The date time format used when converting a date to and from JSON.
-
-
-
- Gets or sets the culture used when converting a date to and from JSON.
-
- The culture used when converting a date to and from JSON.
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Converts a to and from a JavaScript Date constructor (e.g. new Date(52231943)).
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing property value of the JSON that is being converted.
- The calling serializer.
- The object value.
-
-
-
- Converts a to and from JSON.
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Converts a to and from JSON and BSON.
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Converts an to and from its name string value.
-
-
-
-
- Gets or sets a value indicating whether the written enum text should be camel case.
- The default value is false.
-
- true if the written enum text will be camel case; otherwise, false.
-
-
-
- Gets or sets a value indicating whether integer values are allowed when deserializing.
- The default value is true.
-
- true if integers are allowed when deserializing; otherwise, false.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class.
-
- true if the written enum text will be camel case; otherwise, false.
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Converts a to and from Unix epoch time
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing property value of the JSON that is being converted.
- The calling serializer.
- The object value.
-
-
-
- Converts a to and from a string (e.g. "1.2.3.4").
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing property value of the JSON that is being converted.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Converts XML to and from JSON.
-
-
-
-
- Gets or sets the name of the root element to insert when deserializing to XML if the JSON structure has produced multiple root elements.
-
- The name of the deserialized root element.
-
-
-
- Gets or sets a flag to indicate whether to write the Json.NET array attribute.
- This attribute helps preserve arrays when converting the written XML back to JSON.
-
- true if the array attribute is written to the XML; otherwise, false.
-
-
-
- Gets or sets a value indicating whether to write the root JSON object.
-
- true if the JSON root object is omitted; otherwise, false.
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The calling serializer.
- The value.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Checks if the is a namespace attribute.
-
- Attribute name to test.
- The attribute name prefix if it has one, otherwise an empty string.
- true if attribute name is for a namespace attribute, otherwise false.
-
-
-
- Determines whether this instance can convert the specified value type.
-
- Type of the value.
-
- true if this instance can convert the specified value type; otherwise, false.
-
-
-
-
- Specifies how dates are formatted when writing JSON text.
-
-
-
-
- Dates are written in the ISO 8601 format, e.g. "2012-03-21T05:40Z".
-
-
-
-
- Dates are written in the Microsoft JSON format, e.g. "\/Date(1198908717056)\/".
-
-
-
-
- Specifies how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON text.
-
-
-
-
- Date formatted strings are not parsed to a date type and are read as strings.
-
-
-
-
- Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to .
-
-
-
-
- Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to .
-
-
-
-
- Specifies how to treat the time value when converting between string and .
-
-
-
-
- Treat as local time. If the object represents a Coordinated Universal Time (UTC), it is converted to the local time.
-
-
-
-
- Treat as a UTC. If the object represents a local time, it is converted to a UTC.
-
-
-
-
- Treat as a local time if a is being converted to a string.
- If a string is being converted to , convert to a local time if a time zone is specified.
-
-
-
-
- Time zone information should be preserved when converting.
-
-
-
-
- Specifies default value handling options for the .
-
-
-
-
-
-
-
-
- Include members where the member value is the same as the member's default value when serializing objects.
- Included members are written to JSON. Has no effect when deserializing.
-
-
-
-
- Ignore members where the member value is the same as the member's default value when serializing objects
- so that it is not written to JSON.
- This option will ignore all default values (e.g. null for objects and nullable types; 0 for integers,
- decimals and floating point numbers; and false for booleans). The default value ignored can be changed by
- placing the on the property.
-
-
-
-
- Members with a default value but no JSON will be set to their default value when deserializing.
-
-
-
-
- Ignore members where the member value is the same as the member's default value when serializing objects
- and set members to their default value when deserializing.
-
-
-
-
- Specifies float format handling options when writing special floating point numbers, e.g. ,
- and with .
-
-
-
-
- Write special floating point values as strings in JSON, e.g. "NaN", "Infinity", "-Infinity".
-
-
-
-
- Write special floating point values as symbols in JSON, e.g. NaN, Infinity, -Infinity.
- Note that this will produce non-valid JSON.
-
-
-
-
- Write special floating point values as the property's default value in JSON, e.g. 0.0 for a property, null for a of property.
-
-
-
-
- Specifies how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text.
-
-
-
-
- Floating point numbers are parsed to .
-
-
-
-
- Floating point numbers are parsed to .
-
-
-
-
- Specifies formatting options for the .
-
-
-
-
- No special formatting is applied. This is the default.
-
-
-
-
- Causes child objects to be indented according to the and settings.
-
-
-
-
- Provides an interface for using pooled arrays.
-
- The array type content.
-
-
-
- Rent an array from the pool. This array must be returned when it is no longer needed.
-
- The minimum required length of the array. The returned array may be longer.
- The rented array from the pool. This array must be returned when it is no longer needed.
-
-
-
- Return an array to the pool.
-
- The array that is being returned.
-
-
-
- Provides an interface to enable a class to return line and position information.
-
-
-
-
- Gets a value indicating whether the class can return line information.
-
-
- true if and can be provided; otherwise, false.
-
-
-
-
- Gets the current line number.
-
- The current line number or 0 if no line information is available (for example, when returns false).
-
-
-
- Gets the current line position.
-
- The current line position or 0 if no line information is available (for example, when returns false).
-
-
-
- Instructs the how to serialize the collection.
-
-
-
-
- Gets or sets a value indicating whether null items are allowed in the collection.
-
- true if null items are allowed in the collection; otherwise, false.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class with a flag indicating whether the array can contain null items.
-
- A flag indicating whether the array can contain null items.
-
-
-
- Initializes a new instance of the class with the specified container Id.
-
- The container Id.
-
-
-
- Instructs the to use the specified constructor when deserializing that object.
-
-
-
-
- Instructs the how to serialize the object.
-
-
-
-
- Gets or sets the id.
-
- The id.
-
-
-
- Gets or sets the title.
-
- The title.
-
-
-
- Gets or sets the description.
-
- The description.
-
-
-
- Gets or sets the collection's items converter.
-
- The collection's items converter.
-
-
-
- The parameter list to use when constructing the described by .
- If null, the default constructor is used.
- When non-null, there must be a constructor defined in the that exactly matches the number,
- order, and type of these parameters.
-
-
-
- [JsonContainer(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })]
-
-
-
-
-
- Gets or sets the of the .
-
- The of the .
-
-
-
- The parameter list to use when constructing the described by .
- If null, the default constructor is used.
- When non-null, there must be a constructor defined in the that exactly matches the number,
- order, and type of these parameters.
-
-
-
- [JsonContainer(NamingStrategyType = typeof(MyNamingStrategy), NamingStrategyParameters = new object[] { 123, "Four" })]
-
-
-
-
-
- Gets or sets a value that indicates whether to preserve object references.
-
-
- true to keep object reference; otherwise, false. The default is false.
-
-
-
-
- Gets or sets a value that indicates whether to preserve collection's items references.
-
-
- true to keep collection's items object references; otherwise, false. The default is false.
-
-
-
-
- Gets or sets the reference loop handling used when serializing the collection's items.
-
- The reference loop handling.
-
-
-
- Gets or sets the type name handling used when serializing the collection's items.
-
- The type name handling.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class with the specified container Id.
-
- The container Id.
-
-
-
- Provides methods for converting between .NET types and JSON types.
-
-
-
-
-
-
-
- Gets or sets a function that creates default .
- Default settings are automatically used by serialization methods on ,
- and and on .
- To serialize without using any default settings create a with
- .
-
-
-
-
- Represents JavaScript's boolean value true as a string. This field is read-only.
-
-
-
-
- Represents JavaScript's boolean value false as a string. This field is read-only.
-
-
-
-
- Represents JavaScript's null as a string. This field is read-only.
-
-
-
-
- Represents JavaScript's undefined as a string. This field is read-only.
-
-
-
-
- Represents JavaScript's positive infinity as a string. This field is read-only.
-
-
-
-
- Represents JavaScript's negative infinity as a string. This field is read-only.
-
-
-
-
- Represents JavaScript's NaN as a string. This field is read-only.
-
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation using the specified.
-
- The value to convert.
- The format the date will be converted to.
- The time zone handling when the date is converted to a string.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation using the specified.
-
- The value to convert.
- The format the date will be converted to.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- The string delimiter character.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- The string delimiter character.
- The string escape handling.
- A JSON string representation of the .
-
-
-
- Converts the to its JSON string representation.
-
- The value to convert.
- A JSON string representation of the .
-
-
-
- Serializes the specified object to a JSON string.
-
- The object to serialize.
- A JSON string representation of the object.
-
-
-
- Serializes the specified object to a JSON string using formatting.
-
- The object to serialize.
- Indicates how the output should be formatted.
-
- A JSON string representation of the object.
-
-
-
-
- Serializes the specified object to a JSON string using a collection of .
-
- The object to serialize.
- A collection of converters used while serializing.
- A JSON string representation of the object.
-
-
-
- Serializes the specified object to a JSON string using formatting and a collection of .
-
- The object to serialize.
- Indicates how the output should be formatted.
- A collection of converters used while serializing.
- A JSON string representation of the object.
-
-
-
- Serializes the specified object to a JSON string using .
-
- The object to serialize.
- The used to serialize the object.
- If this is null, default serialization settings will be used.
-
- A JSON string representation of the object.
-
-
-
-
- Serializes the specified object to a JSON string using a type, formatting and .
-
- The object to serialize.
- The used to serialize the object.
- If this is null, default serialization settings will be used.
-
- The type of the value being serialized.
- This parameter is used when is to write out the type name if the type of the value does not match.
- Specifying the type is optional.
-
-
- A JSON string representation of the object.
-
-
-
-
- Serializes the specified object to a JSON string using formatting and .
-
- The object to serialize.
- Indicates how the output should be formatted.
- The used to serialize the object.
- If this is null, default serialization settings will be used.
-
- A JSON string representation of the object.
-
-
-
-
- Serializes the specified object to a JSON string using a type, formatting and .
-
- The object to serialize.
- Indicates how the output should be formatted.
- The used to serialize the object.
- If this is null, default serialization settings will be used.
-
- The type of the value being serialized.
- This parameter is used when is to write out the type name if the type of the value does not match.
- Specifying the type is optional.
-
-
- A JSON string representation of the object.
-
-
-
-
- Deserializes the JSON to a .NET object.
-
- The JSON to deserialize.
- The deserialized object from the JSON string.
-
-
-
- Deserializes the JSON to a .NET object using .
-
- The JSON to deserialize.
-
- The used to deserialize the object.
- If this is null, default serialization settings will be used.
-
- The deserialized object from the JSON string.
-
-
-
- Deserializes the JSON to the specified .NET type.
-
- The JSON to deserialize.
- The of object being deserialized.
- The deserialized object from the JSON string.
-
-
-
- Deserializes the JSON to the specified .NET type.
-
- The type of the object to deserialize to.
- The JSON to deserialize.
- The deserialized object from the JSON string.
-
-
-
- Deserializes the JSON to the given anonymous type.
-
-
- The anonymous type to deserialize to. This can't be specified
- traditionally and must be inferred from the anonymous type passed
- as a parameter.
-
- The JSON to deserialize.
- The anonymous type object.
- The deserialized anonymous type from the JSON string.
-
-
-
- Deserializes the JSON to the given anonymous type using .
-
-
- The anonymous type to deserialize to. This can't be specified
- traditionally and must be inferred from the anonymous type passed
- as a parameter.
-
- The JSON to deserialize.
- The anonymous type object.
-
- The used to deserialize the object.
- If this is null, default serialization settings will be used.
-
- The deserialized anonymous type from the JSON string.
-
-
-
- Deserializes the JSON to the specified .NET type using a collection of .
-
- The type of the object to deserialize to.
- The JSON to deserialize.
- Converters to use while deserializing.
- The deserialized object from the JSON string.
-
-
-
- Deserializes the JSON to the specified .NET type using .
-
- The type of the object to deserialize to.
- The object to deserialize.
-
- The used to deserialize the object.
- If this is null, default serialization settings will be used.
-
- The deserialized object from the JSON string.
-
-
-
- Deserializes the JSON to the specified .NET type using a collection of .
-
- The JSON to deserialize.
- The type of the object to deserialize.
- Converters to use while deserializing.
- The deserialized object from the JSON string.
-
-
-
- Deserializes the JSON to the specified .NET type using .
-
- The JSON to deserialize.
- The type of the object to deserialize to.
-
- The used to deserialize the object.
- If this is null, default serialization settings will be used.
-
- The deserialized object from the JSON string.
-
-
-
- Populates the object with values from the JSON string.
-
- The JSON to populate values from.
- The target object to populate values onto.
-
-
-
- Populates the object with values from the JSON string using .
-
- The JSON to populate values from.
- The target object to populate values onto.
-
- The used to deserialize the object.
- If this is null, default serialization settings will be used.
-
-
-
-
- Serializes the to a JSON string.
-
- The node to serialize.
- A JSON string of the .
-
-
-
- Serializes the to a JSON string using formatting.
-
- The node to serialize.
- Indicates how the output should be formatted.
- A JSON string of the .
-
-
-
- Serializes the to a JSON string using formatting and omits the root object if is true.
-
- The node to serialize.
- Indicates how the output should be formatted.
- Omits writing the root object.
- A JSON string of the .
-
-
-
- Deserializes the from a JSON string.
-
- The JSON string.
- The deserialized .
-
-
-
- Deserializes the from a JSON string nested in a root element specified by .
-
- The JSON string.
- The name of the root element to append when deserializing.
- The deserialized .
-
-
-
- Deserializes the from a JSON string nested in a root element specified by
- and writes a Json.NET array attribute for collections.
-
- The JSON string.
- The name of the root element to append when deserializing.
-
- A flag to indicate whether to write the Json.NET array attribute.
- This attribute helps preserve arrays when converting the written XML back to JSON.
-
- The deserialized .
-
-
-
- Serializes the to a JSON string.
-
- The node to convert to JSON.
- A JSON string of the .
-
-
-
- Serializes the to a JSON string using formatting.
-
- The node to convert to JSON.
- Indicates how the output should be formatted.
- A JSON string of the .
-
-
-
- Serializes the to a JSON string using formatting and omits the root object if is true.
-
- The node to serialize.
- Indicates how the output should be formatted.
- Omits writing the root object.
- A JSON string of the .
-
-
-
- Deserializes the from a JSON string.
-
- The JSON string.
- The deserialized .
-
-
-
- Deserializes the from a JSON string nested in a root element specified by .
-
- The JSON string.
- The name of the root element to append when deserializing.
- The deserialized .
-
-
-
- Deserializes the from a JSON string nested in a root element specified by
- and writes a Json.NET array attribute for collections.
-
- The JSON string.
- The name of the root element to append when deserializing.
-
- A flag to indicate whether to write the Json.NET array attribute.
- This attribute helps preserve arrays when converting the written XML back to JSON.
-
- The deserialized .
-
-
-
- Converts an object to and from JSON.
-
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Gets a value indicating whether this can read JSON.
-
- true if this can read JSON; otherwise, false.
-
-
-
- Gets a value indicating whether this can write JSON.
-
- true if this can write JSON; otherwise, false.
-
-
-
- Converts an object to and from JSON.
-
- The object type to convert.
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Writes the JSON representation of the object.
-
- The to write to.
- The value.
- The calling serializer.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read.
- The calling serializer.
- The object value.
-
-
-
- Reads the JSON representation of the object.
-
- The to read from.
- Type of the object.
- The existing value of object being read. If there is no existing value then null will be used.
- The existing value has a value.
- The calling serializer.
- The object value.
-
-
-
- Determines whether this instance can convert the specified object type.
-
- Type of the object.
-
- true if this instance can convert the specified object type; otherwise, false.
-
-
-
-
- Instructs the to use the specified when serializing the member or class.
-
-
-
-
- Gets the of the .
-
- The of the .
-
-
-
- The parameter list to use when constructing the described by .
- If null, the default constructor is used.
-
-
-
-
- Initializes a new instance of the class.
-
- Type of the .
-
-
-
- Initializes a new instance of the class.
-
- Type of the .
- Parameter list to use when constructing the . Can be null.
-
-
-
- Represents a collection of .
-
-
-
-
- Instructs the how to serialize the collection.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class with the specified container Id.
-
- The container Id.
-
-
-
- The exception thrown when an error occurs during JSON serialization or deserialization.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class
- with a specified error message.
-
- The error message that explains the reason for the exception.
-
-
-
- Initializes a new instance of the class
- with a specified error message and a reference to the inner exception that is the cause of this exception.
-
- The error message that explains the reason for the exception.
- The exception that is the cause of the current exception, or null if no inner exception is specified.
-
-
-
- Instructs the to deserialize properties with no matching class member into the specified collection
- and write values during serialization.
-
-
-
-
- Gets or sets a value that indicates whether to write extension data when serializing the object.
-
-
- true to write extension data when serializing the object; otherwise, false. The default is true.
-
-
-
-
- Gets or sets a value that indicates whether to read extension data when deserializing the object.
-
-
- true to read extension data when deserializing the object; otherwise, false. The default is true.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Instructs the not to serialize the public field or public read/write property value.
-
-
-
-
- Instructs the how to serialize the object.
-
-
-
-
- Gets or sets the member serialization.
-
- The member serialization.
-
-
-
- Gets or sets how the object's properties with null values are handled during serialization and deserialization.
-
- How the object's properties with null values are handled during serialization and deserialization.
-
-
-
- Gets or sets a value that indicates whether the object's properties are required.
-
-
- A value indicating whether the object's properties are required.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class with the specified member serialization.
-
- The member serialization.
-
-
-
- Initializes a new instance of the class with the specified container Id.
-
- The container Id.
-
-
-
- Instructs the to always serialize the member with the specified name.
-
-
-
-
- Gets or sets the used when serializing the property's collection items.
-
- The collection's items .
-
-
-
- The parameter list to use when constructing the described by .
- If null, the default constructor is used.
- When non-null, there must be a constructor defined in the that exactly matches the number,
- order, and type of these parameters.
-
-
-
- [JsonProperty(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })]
-
-
-
-
-
- Gets or sets the of the .
-
- The of the .
-
-
-
- The parameter list to use when constructing the described by .
- If null, the default constructor is used.
- When non-null, there must be a constructor defined in the that exactly matches the number,
- order, and type of these parameters.
-
-
-
- [JsonProperty(NamingStrategyType = typeof(MyNamingStrategy), NamingStrategyParameters = new object[] { 123, "Four" })]
-
-
-
-
-
- Gets or sets the null value handling used when serializing this property.
-
- The null value handling.
-
-
-
- Gets or sets the default value handling used when serializing this property.
-
- The default value handling.
-
-
-
- Gets or sets the reference loop handling used when serializing this property.
-
- The reference loop handling.
-
-
-
- Gets or sets the object creation handling used when deserializing this property.
-
- The object creation handling.
-
-
-
- Gets or sets the type name handling used when serializing this property.
-
- The type name handling.
-
-
-
- Gets or sets whether this property's value is serialized as a reference.
-
- Whether this property's value is serialized as a reference.
-
-
-
- Gets or sets the order of serialization of a member.
-
- The numeric order of serialization.
-
-
-
- Gets or sets a value indicating whether this property is required.
-
-
- A value indicating whether this property is required.
-
-
-
-
- Gets or sets the name of the property.
-
- The name of the property.
-
-
-
- Gets or sets the reference loop handling used when serializing the property's collection items.
-
- The collection's items reference loop handling.
-
-
-
- Gets or sets the type name handling used when serializing the property's collection items.
-
- The collection's items type name handling.
-
-
-
- Gets or sets whether this property's collection items are serialized as a reference.
-
- Whether this property's collection items are serialized as a reference.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class with the specified name.
-
- Name of the property.
-
-
-
- Represents a reader that provides fast, non-cached, forward-only access to serialized JSON data.
-
-
-
-
- Asynchronously reads the next JSON token from the source.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns true if the next token was read successfully; false if there are no more tokens to read.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously skips the children of the current token.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously reads the next JSON token from the source as a [].
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the []. This result will be null at the end of an array.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously reads the next JSON token from the source as a .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the . This result will be null at the end of an array.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Specifies the state of the reader.
-
-
-
-
- A read method has not been called.
-
-
-
-
- The end of the file has been reached successfully.
-
-
-
-
- Reader is at a property.
-
-
-
-
- Reader is at the start of an object.
-
-
-
-
- Reader is in an object.
-
-
-
-
- Reader is at the start of an array.
-
-
-
-
- Reader is in an array.
-
-
-
-
- The method has been called.
-
-
-
-
- Reader has just read a value.
-
-
-
-
- Reader is at the start of a constructor.
-
-
-
-
- Reader is in a constructor.
-
-
-
-
- An error occurred that prevents the read operation from continuing.
-
-
-
-
- The end of the file has been reached successfully.
-
-
-
-
- Gets the current reader state.
-
- The current reader state.
-
-
-
- Gets or sets a value indicating whether the source should be closed when this reader is closed.
-
-
- true to close the source when this reader is closed; otherwise false. The default is true.
-
-
-
-
- Gets or sets a value indicating whether multiple pieces of JSON content can
- be read from a continuous stream without erroring.
-
-
- true to support reading multiple pieces of JSON content; otherwise false.
- The default is false.
-
-
-
-
- Gets the quotation mark character used to enclose the value of a string.
-
-
-
-
- Gets or sets how time zones are handled when reading JSON.
-
-
-
-
- Gets or sets how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON.
-
-
-
-
- Gets or sets how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text.
-
-
-
-
- Gets or sets how custom date formatted strings are parsed when reading JSON.
-
-
-
-
- Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a .
-
-
-
-
- Gets the type of the current JSON token.
-
-
-
-
- Gets the text value of the current JSON token.
-
-
-
-
- Gets the .NET type for the current JSON token.
-
-
-
-
- Gets the depth of the current token in the JSON document.
-
- The depth of the current token in the JSON document.
-
-
-
- Gets the path of the current JSON token.
-
-
-
-
- Gets or sets the culture used when reading JSON. Defaults to .
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Reads the next JSON token from the source.
-
- true if the next token was read successfully; false if there are no more tokens to read.
-
-
-
- Reads the next JSON token from the source as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the source as a .
-
- A . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the source as a [].
-
- A [] or null if the next JSON token is null. This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the source as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the source as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the source as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the source as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the source as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Skips the children of the current token.
-
-
-
-
- Sets the current token.
-
- The new token.
-
-
-
- Sets the current token and value.
-
- The new token.
- The value.
-
-
-
- Sets the current token and value.
-
- The new token.
- The value.
- A flag indicating whether the position index inside an array should be updated.
-
-
-
- Sets the state based on current token type.
-
-
-
-
- Releases unmanaged and - optionally - managed resources.
-
- true to release both managed and unmanaged resources; false to release only unmanaged resources.
-
-
-
- Changes the reader's state to .
- If is set to true, the source is also closed.
-
-
-
-
- The exception thrown when an error occurs while reading JSON text.
-
-
-
-
- Gets the line number indicating where the error occurred.
-
- The line number indicating where the error occurred.
-
-
-
- Gets the line position indicating where the error occurred.
-
- The line position indicating where the error occurred.
-
-
-
- Gets the path to the JSON where the error occurred.
-
- The path to the JSON where the error occurred.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class
- with a specified error message.
-
- The error message that explains the reason for the exception.
-
-
-
- Initializes a new instance of the class
- with a specified error message and a reference to the inner exception that is the cause of this exception.
-
- The error message that explains the reason for the exception.
- The exception that is the cause of the current exception, or null if no inner exception is specified.
-
-
-
- Initializes a new instance of the class
- with a specified error message, JSON path, line number, line position, and a reference to the inner exception that is the cause of this exception.
-
- The error message that explains the reason for the exception.
- The path to the JSON where the error occurred.
- The line number indicating where the error occurred.
- The line position indicating where the error occurred.
- The exception that is the cause of the current exception, or null if no inner exception is specified.
-
-
-
- Instructs the to always serialize the member, and to require that the member has a value.
-
-
-
-
- The exception thrown when an error occurs during JSON serialization or deserialization.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class
- with a specified error message.
-
- The error message that explains the reason for the exception.
-
-
-
- Initializes a new instance of the class
- with a specified error message and a reference to the inner exception that is the cause of this exception.
-
- The error message that explains the reason for the exception.
- The exception that is the cause of the current exception, or null if no inner exception is specified.
-
-
-
- Serializes and deserializes objects into and from the JSON format.
- The enables you to control how objects are encoded into JSON.
-
-
-
-
- Occurs when the errors during serialization and deserialization.
-
-
-
-
- Gets or sets the used by the serializer when resolving references.
-
-
-
-
- Gets or sets the used by the serializer when resolving type names.
-
-
-
-
- Gets or sets the equality comparer used by the serializer when comparing references.
-
- The equality comparer.
-
-
-
- Gets or sets how type name writing and reading is handled by the serializer.
- The default value is .
-
-
- should be used with caution when your application deserializes JSON from an external source.
- Incoming types should be validated with a custom
- when deserializing with a value other than .
-
-
-
-
- Gets or sets how a type name assembly is written and resolved by the serializer.
- The default value is .
-
- The type name assembly format.
-
-
-
- Gets or sets how object references are preserved by the serializer.
- The default value is .
-
-
-
-
- Gets or sets how reference loops (e.g. a class referencing itself) is handled.
- The default value is .
-
-
-
-
- Gets or sets how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization.
- The default value is .
-
-
-
-
- Gets or sets how null values are handled during serialization and deserialization.
- The default value is .
-
-
-
-
- Gets or sets how default values are handled during serialization and deserialization.
- The default value is .
-
-
-
-
- Gets or sets how objects are created during deserialization.
- The default value is .
-
- The object creation handling.
-
-
-
- Gets or sets how constructors are used during deserialization.
- The default value is .
-
- The constructor handling.
-
-
-
- Gets or sets how metadata properties are used during deserialization.
- The default value is .
-
- The metadata properties handling.
-
-
-
- Gets a collection that will be used during serialization.
-
- Collection that will be used during serialization.
-
-
-
- Gets or sets the contract resolver used by the serializer when
- serializing .NET objects to JSON and vice versa.
-
-
-
-
- Indicates how JSON text output is formatted.
- The default value is .
-
-
-
-
- Gets or sets how dates are written to JSON text.
- The default value is .
-
-
-
-
- Gets or sets how time zones are handled during serialization and deserialization.
- The default value is .
-
-
-
-
- Gets or sets how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON.
- The default value is .
-
-
-
-
- Gets or sets how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text.
- The default value is .
-
-
-
-
- Gets or sets how special floating point numbers, e.g. ,
- and ,
- are written as JSON text.
- The default value is .
-
-
-
-
- Gets or sets how strings are escaped when writing JSON text.
- The default value is .
-
-
-
-
- Gets or sets how and values are formatted when writing JSON text,
- and the expected date format when reading JSON text.
- The default value is "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK".
-
-
-
-
- Gets or sets the culture used when reading JSON.
- The default value is .
-
-
-
-
- Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a .
- A null value means there is no maximum.
- The default value is null.
-
-
-
-
- Gets a value indicating whether there will be a check for additional JSON content after deserializing an object.
- The default value is false.
-
-
- true if there will be a check for additional JSON content after deserializing an object; otherwise, false.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Clears all the cached types, attributes and methods to release references to any types of the other assemblies.
-
-
-
-
- Creates a new instance.
- The will not use default settings
- from .
-
-
- A new instance.
- The will not use default settings
- from .
-
-
-
-
- Creates a new instance using the specified .
- The will not use default settings
- from .
-
- The settings to be applied to the .
-
- A new instance using the specified .
- The will not use default settings
- from .
-
-
-
-
- Creates a new instance.
- The will use default settings
- from .
-
-
- A new instance.
- The will use default settings
- from .
-
-
-
-
- Creates a new instance using the specified .
- The will use default settings
- from as well as the specified .
-
- The settings to be applied to the .
-
- A new instance using the specified .
- The will use default settings
- from as well as the specified .
-
-
-
-
- Populates the JSON values onto the target object.
-
- The that contains the JSON structure to reader values from.
- The target object to populate values onto.
-
-
-
- Populates the JSON values onto the target object.
-
- The that contains the JSON structure to reader values from.
- The target object to populate values onto.
-
-
-
- Deserializes the JSON structure contained by the specified .
-
- The that contains the JSON structure to deserialize.
- The being deserialized.
-
-
-
- Deserializes the JSON structure contained by the specified
- into an instance of the specified type.
-
- The containing the object.
- The of object being deserialized.
- The instance of being deserialized.
-
-
-
- Deserializes the JSON structure contained by the specified
- into an instance of the specified type.
-
- The containing the object.
- The type of the object to deserialize.
- The instance of being deserialized.
-
-
-
- Deserializes the JSON structure contained by the specified
- into an instance of the specified type.
-
- The containing the object.
- The of object being deserialized.
- The instance of being deserialized.
-
-
-
- Serializes the specified difference to the other object of the same type. and writes the JSON structure using the specified .
-
- The used to write the JSON structure.
- The to serialize.
- The reference object.
-
-
-
- Serializes the specified difference to the other object of the same type. Writes the JSON structure using the specified .
-
- The used to write the JSON structure.
- The to serialize.
-
- The type of the value being serialized.
- This parameter is used when is to write out the type name if the type of the value does not match.
- Specifying the type is optional.
-
- The reference object.
-
-
-
- Serializes the specified difference to the other object of the same type. Writes the JSON structure using the specified .
-
- The used to write the JSON structure.
- The to serialize.
-
- The type of the value being serialized.
- This parameter is used when is Auto to write out the type name if the type of the value does not match.
- Specifying the type is optional.
-
- The reference object.
-
-
-
- Serializes the specified and writes the JSON structure
- using the specified .
-
- The used to write the JSON structure.
- The to serialize.
- The reference object.
-
-
-
- Serializes the specified and writes the JSON structure
- using the specified .
-
- The used to write the JSON structure.
- The to serialize.
-
-
-
- Serializes the specified and writes the JSON structure
- using the specified .
-
- The used to write the JSON structure.
- The to serialize.
-
- The type of the value being serialized.
- This parameter is used when is to write out the type name if the type of the value does not match.
- Specifying the type is optional.
-
-
-
-
- Serializes the specified and writes the JSON structure
- using the specified .
-
- The used to write the JSON structure.
- The to serialize.
-
- The type of the value being serialized.
- This parameter is used when is Auto to write out the type name if the type of the value does not match.
- Specifying the type is optional.
-
-
-
-
- Serializes the specified and writes the JSON structure
- using the specified .
-
- The used to write the JSON structure.
- The to serialize.
-
-
-
- Specifies the settings on a object.
-
-
-
-
- Gets or sets how reference loops (e.g. a class referencing itself) are handled.
- The default value is .
-
- Reference loop handling.
-
-
-
- Gets or sets how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization.
- The default value is .
-
- Missing member handling.
-
-
-
- Gets or sets how objects are created during deserialization.
- The default value is .
-
- The object creation handling.
-
-
-
- Gets or sets how null values are handled during serialization and deserialization.
- The default value is .
-
- Null value handling.
-
-
-
- Gets or sets how default values are handled during serialization and deserialization.
- The default value is .
-
- The default value handling.
-
-
-
- Gets or sets a collection that will be used during serialization.
-
- The converters.
-
-
-
- Gets or sets how object references are preserved by the serializer.
- The default value is .
-
- The preserve references handling.
-
-
-
- Gets or sets how type name writing and reading is handled by the serializer.
- The default value is .
-
-
- should be used with caution when your application deserializes JSON from an external source.
- Incoming types should be validated with a custom
- when deserializing with a value other than .
-
- The type name handling.
-
-
-
- Gets or sets how metadata properties are used during deserialization.
- The default value is .
-
- The metadata properties handling.
-
-
-
- Gets or sets how a type name assembly is written and resolved by the serializer.
- The default value is .
-
- The type name assembly format.
-
-
-
- Gets or sets how constructors are used during deserialization.
- The default value is .
-
- The constructor handling.
-
-
-
- Gets or sets the contract resolver used by the serializer when
- serializing .NET objects to JSON and vice versa.
-
- The contract resolver.
-
-
-
- Gets or sets the equality comparer used by the serializer when comparing references.
-
- The equality comparer.
-
-
-
- Gets or sets a function that creates the used by the serializer when resolving references.
-
- A function that creates the used by the serializer when resolving references.
-
-
-
- Gets or sets the used by the serializer when resolving type names.
-
- The binder.
-
-
-
- Gets or sets the error handler called during serialization and deserialization.
-
- The error handler called during serialization and deserialization.
-
-
-
- Gets or sets how and values are formatted when writing JSON text,
- and the expected date format when reading JSON text.
- The default value is "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK".
-
-
-
-
- Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a .
- A null value means there is no maximum.
- The default value is null.
-
-
-
-
- Indicates how JSON text output is formatted.
- The default value is .
-
-
-
-
- Gets or sets how dates are written to JSON text.
- The default value is .
-
-
-
-
- Gets or sets how time zones are handled during serialization and deserialization.
- The default value is .
-
-
-
-
- Gets or sets how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON.
- The default value is .
-
-
-
-
- Gets or sets how special floating point numbers, e.g. ,
- and ,
- are written as JSON.
- The default value is .
-
-
-
-
- Gets or sets how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text.
- The default value is .
-
-
-
-
- Gets or sets how strings are escaped when writing JSON text.
- The default value is .
-
-
-
-
- Gets or sets the culture used when reading JSON.
- The default value is .
-
-
-
-
- Gets a value indicating whether there will be a check for additional content after deserializing an object.
- The default value is false.
-
-
- true if there will be a check for additional content after deserializing an object; otherwise, false.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Represents a reader that provides fast, non-cached, forward-only access to JSON text data.
-
-
-
-
- Asynchronously reads the next JSON token from the source.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns true if the next token was read successfully; false if there are no more tokens to read.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously reads the next JSON token from the source as a [].
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the []. This result will be null at the end of an array.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously reads the next JSON token from the source as a of .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the of . This result will be null at the end of an array.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously reads the next JSON token from the source as a .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous read. The
- property returns the . This result will be null at the end of an array.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Initializes a new instance of the class with the specified .
-
- The containing the JSON data to read.
-
-
-
- Gets or sets the reader's character buffer pool.
-
-
-
-
- Reads the next JSON token from the underlying .
-
-
- true if the next token was read successfully; false if there are no more tokens to read.
-
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a .
-
- A . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a [].
-
- A [] or null if the next JSON token is null. This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Changes the reader's state to .
- If is set to true, the underlying is also closed.
-
-
-
-
- Gets a value indicating whether the class can return line information.
-
-
- true if and can be provided; otherwise, false.
-
-
-
-
- Gets the current line number.
-
-
- The current line number or 0 if no line information is available (for example, returns false).
-
-
-
-
- Gets the current line position.
-
-
- The current line position or 0 if no line information is available (for example, returns false).
-
-
-
-
- Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data.
-
-
-
-
- Asynchronously flushes whatever is in the buffer to the destination and also flushes the destination.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the JSON value delimiter.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the specified end token.
-
- The end token to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously closes this writer.
- If is set to true, the destination is also closed.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the end of the current JSON object or array.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes indent characters.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes an indent space.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes raw JSON without changing the writer's state.
-
- The raw JSON to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a null value.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the property name of a name/value pair of a JSON object.
-
- The name of the property.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the property name of a name/value pair of a JSON object.
-
- The name of the property.
- A flag to indicate whether the text should be escaped when it is written as a JSON property name.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the beginning of a JSON array.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the beginning of a JSON object.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the start of a constructor with the given name.
-
- The name of the constructor.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes an undefined value.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the given white space.
-
- The string of white space characters.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a [] value.
-
- The [] value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes a comment /*...*/ containing the specified text.
-
- Text to place inside the comment.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the end of an array.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the end of a constructor.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes the end of a JSON object.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Asynchronously writes raw JSON where a value is expected and updates the writer's state.
-
- The raw JSON to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- Derived classes must override this method to get asynchronous behaviour. Otherwise it will
- execute synchronously, returning an already-completed task.
-
-
-
- Gets or sets the writer's character array pool.
-
-
-
-
- Gets or sets how many s to write for each level in the hierarchy when is set to .
-
-
-
-
- Gets or sets which character to use to quote attribute values.
-
-
-
-
- Gets or sets which character to use for indenting when is set to .
-
-
-
-
- Gets or sets a value indicating whether object names will be surrounded with quotes.
-
-
-
-
- Initializes a new instance of the class using the specified .
-
- The to write to.
-
-
-
- Flushes whatever is in the buffer to the underlying and also flushes the underlying .
-
-
-
-
- Closes this writer.
- If is set to true, the underlying is also closed.
- If is set to true, the JSON is auto-completed.
-
-
-
-
- Writes the beginning of a JSON object.
-
-
-
-
- Writes the beginning of a JSON array.
-
-
-
-
- Writes the start of a constructor with the given name.
-
- The name of the constructor.
-
-
-
- Writes the specified end token.
-
- The end token to write.
-
-
-
- Writes the property name of a name/value pair on a JSON object.
-
- The name of the property.
-
-
-
- Writes the property name of a name/value pair on a JSON object.
-
- The name of the property.
- A flag to indicate whether the text should be escaped when it is written as a JSON property name.
-
-
-
- Writes indent characters.
-
-
-
-
- Writes the JSON value delimiter.
-
-
-
-
- Writes an indent space.
-
-
-
-
- Writes a value.
- An error will raised if the value cannot be written as a single JSON token.
-
- The value to write.
-
-
-
- Writes a null value.
-
-
-
-
- Writes an undefined value.
-
-
-
-
- Writes raw JSON.
-
- The raw JSON to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a [] value.
-
- The [] value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a comment /*...*/ containing the specified text.
-
- Text to place inside the comment.
-
-
-
- Writes the given white space.
-
- The string of white space characters.
-
-
-
- Specifies the type of JSON token.
-
-
-
-
- This is returned by the if a read method has not been called.
-
-
-
-
- An object start token.
-
-
-
-
- An array start token.
-
-
-
-
- A constructor start token.
-
-
-
-
- An object property name.
-
-
-
-
- A comment.
-
-
-
-
- Raw JSON.
-
-
-
-
- An integer.
-
-
-
-
- A float.
-
-
-
-
- A string.
-
-
-
-
- A boolean.
-
-
-
-
- A null token.
-
-
-
-
- An undefined token.
-
-
-
-
- An object end token.
-
-
-
-
- An array end token.
-
-
-
-
- A constructor end token.
-
-
-
-
- A Date.
-
-
-
-
- Byte data.
-
-
-
-
-
- Represents a reader that provides validation.
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- Sets an event handler for receiving schema validation errors.
-
-
-
-
- Gets the text value of the current JSON token.
-
-
-
-
-
- Gets the depth of the current token in the JSON document.
-
- The depth of the current token in the JSON document.
-
-
-
- Gets the path of the current JSON token.
-
-
-
-
- Gets the quotation mark character used to enclose the value of a string.
-
-
-
-
-
- Gets the type of the current JSON token.
-
-
-
-
-
- Gets the .NET type for the current JSON token.
-
-
-
-
-
- Initializes a new instance of the class that
- validates the content returned from the given .
-
- The to read from while validating.
-
-
-
- Gets or sets the schema.
-
- The schema.
-
-
-
- Gets the used to construct this .
-
- The specified in the constructor.
-
-
-
- Changes the reader's state to .
- If is set to true, the underlying is also closed.
-
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of .
-
-
-
- Reads the next JSON token from the underlying as a [].
-
-
- A [] or null if the next JSON token is null.
-
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of .
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of .
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of .
-
-
-
- Reads the next JSON token from the underlying as a .
-
- A . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of . This method will return null at the end of an array.
-
-
-
- Reads the next JSON token from the underlying as a of .
-
- A of .
-
-
-
- Reads the next JSON token from the underlying .
-
-
- true if the next token was read successfully; false if there are no more tokens to read.
-
-
-
-
- Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data.
-
-
-
-
- Asynchronously closes this writer.
- If is set to true, the destination is also closed.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously flushes whatever is in the buffer to the destination and also flushes the destination.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the specified end token.
-
- The end token to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes indent characters.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the JSON value delimiter.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes an indent space.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes raw JSON without changing the writer's state.
-
- The raw JSON to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the end of the current JSON object or array.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the end of an array.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the end of a constructor.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the end of a JSON object.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a null value.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the property name of a name/value pair of a JSON object.
-
- The name of the property.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the property name of a name/value pair of a JSON object.
-
- The name of the property.
- A flag to indicate whether the text should be escaped when it is written as a JSON property name.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the beginning of a JSON array.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a comment /*...*/ containing the specified text.
-
- Text to place inside the comment.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes raw JSON where a value is expected and updates the writer's state.
-
- The raw JSON to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the start of a constructor with the given name.
-
- The name of the constructor.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the beginning of a JSON object.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the current token.
-
- The to read the token from.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the current token.
-
- The to read the token from.
- A flag indicating whether the current token's children should be written.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the token and its value.
-
- The to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the token and its value.
-
- The to write.
-
- The value to write.
- A value is only required for tokens that have an associated value, e.g. the property name for .
- null can be passed to the method for tokens that don't have a value, e.g. .
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a [] value.
-
- The [] value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a value.
-
- The value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes a of value.
-
- The of value to write.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes an undefined value.
-
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously writes the given white space.
-
- The string of white space characters.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Asynchronously ets the state of the .
-
- The being written.
- The value being written.
- The token to monitor for cancellation requests. The default value is .
- A that represents the asynchronous operation.
- The default behaviour is to execute synchronously, returning an already-completed task. Derived
- classes can override this behaviour for true asynchronicity.
-
-
-
- Gets or sets a value indicating whether the destination should be closed when this writer is closed.
-
-
- true to close the destination when this writer is closed; otherwise false. The default is true.
-
-
-
-
- Gets or sets a value indicating whether the JSON should be auto-completed when this writer is closed.
-
-
- true to auto-complete the JSON when this writer is closed; otherwise false. The default is true.
-
-
-
-
- Gets the top.
-
- The top.
-
-
-
- Gets the state of the writer.
-
-
-
-
- Gets the path of the writer.
-
-
-
-
- Gets or sets a value indicating how JSON text output should be formatted.
-
-
-
-
- Gets or sets how dates are written to JSON text.
-
-
-
-
- Gets or sets how time zones are handled when writing JSON text.
-
-
-
-
- Gets or sets how strings are escaped when writing JSON text.
-
-
-
-
- Gets or sets how special floating point numbers, e.g. ,
- and ,
- are written to JSON text.
-
-
-
-
- Gets or sets how and values are formatted when writing JSON text.
-
-
-
-
- Gets or sets the culture used when writing JSON. Defaults to .
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Flushes whatever is in the buffer to the destination and also flushes the destination.
-
-
-
-
- Closes this writer.
- If is set to true, the destination is also closed.
- If is set to true, the JSON is auto-completed.
-
-
-
-
- Writes the beginning of a JSON object.
-
-
-
-
- Writes the end of a JSON object.
-
-
-
-
- Writes the beginning of a JSON array.
-
-
-
-
- Writes the end of an array.
-
-
-
-
- Writes the start of a constructor with the given name.
-
- The name of the constructor.
-
-
-
- Writes the end constructor.
-
-
-
-
- Writes the property name of a name/value pair of a JSON object.
-
- The name of the property.
-
-
-
- Writes the property name of a name/value pair of a JSON object.
-
- The name of the property.
- A flag to indicate whether the text should be escaped when it is written as a JSON property name.
-
-
-
- Writes the end of the current JSON object or array.
-
-
-
-
- Writes the current token and its children.
-
- The to read the token from.
-
-
-
- Writes the current token.
-
- The to read the token from.
- A flag indicating whether the current token's children should be written.
-
-
-
- Writes the token and its value.
-
- The to write.
-
- The value to write.
- A value is only required for tokens that have an associated value, e.g. the property name for .
- null can be passed to the method for tokens that don't have a value, e.g. .
-
-
-
-
- Writes the token.
-
- The to write.
-
-
-
- Writes the specified end token.
-
- The end token to write.
-
-
-
- Writes indent characters.
-
-
-
-
- Writes the JSON value delimiter.
-
-
-
-
- Writes an indent space.
-
-
-
-
- Writes a null value.
-
-
-
-
- Writes an undefined value.
-
-
-
-
- Writes raw JSON without changing the writer's state.
-
- The raw JSON to write.
-
-
-
- Writes raw JSON where a value is expected and updates the writer's state.
-
- The raw JSON to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a of value.
-
- The of value to write.
-
-
-
- Writes a [] value.
-
- The [] value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
- An error will raised if the value cannot be written as a single JSON token.
-
- The value to write.
-
-
-
- Writes a comment /*...*/ containing the specified text.
-
- Text to place inside the comment.
-
-
-
- Writes the given white space.
-
- The string of white space characters.
-
-
-
- Releases unmanaged and - optionally - managed resources.
-
- true to release both managed and unmanaged resources; false to release only unmanaged resources.
-
-
-
- Sets the state of the .
-
- The being written.
- The value being written.
-
-
-
- The exception thrown when an error occurs while writing JSON text.
-
-
-
-
- Gets the path to the JSON where the error occurred.
-
- The path to the JSON where the error occurred.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class
- with a specified error message.
-
- The error message that explains the reason for the exception.
-
-
-
- Initializes a new instance of the class
- with a specified error message and a reference to the inner exception that is the cause of this exception.
-
- The error message that explains the reason for the exception.
- The exception that is the cause of the current exception, or null if no inner exception is specified.
-
-
-
- Initializes a new instance of the class
- with a specified error message, JSON path and a reference to the inner exception that is the cause of this exception.
-
- The error message that explains the reason for the exception.
- The path to the JSON where the error occurred.
- The exception that is the cause of the current exception, or null if no inner exception is specified.
-
-
-
- Specifies how JSON comments are handled when loading JSON.
-
-
-
-
- Ignore comments.
-
-
-
-
- Load comments as a with type .
-
-
-
-
- Contains the LINQ to JSON extension methods.
-
-
-
-
- Returns a collection of tokens that contains the ancestors of every token in the source collection.
-
- The type of the objects in source, constrained to .
- An of that contains the source collection.
- An of that contains the ancestors of every token in the source collection.
-
-
-
- Returns a collection of tokens that contains every token in the source collection, and the ancestors of every token in the source collection.
-
- The type of the objects in source, constrained to .
- An of that contains the source collection.
- An of that contains every token in the source collection, the ancestors of every token in the source collection.
-
-
-
- Returns a collection of tokens that contains the descendants of every token in the source collection.
-
- The type of the objects in source, constrained to .
- An of that contains the source collection.
- An of that contains the descendants of every token in the source collection.
-
-
-
- Returns a collection of tokens that contains every token in the source collection, and the descendants of every token in the source collection.
-
- The type of the objects in source, constrained to .
- An of that contains the source collection.
- An of that contains every token in the source collection, and the descendants of every token in the source collection.
-
-
-
- Returns a collection of child properties of every object in the source collection.
-
- An of that contains the source collection.
- An of that contains the properties of every object in the source collection.
-
-
-
- Returns a collection of child values of every object in the source collection with the given key.
-
- An of that contains the source collection.
- The token key.
- An of that contains the values of every token in the source collection with the given key.
-
-
-
- Returns a collection of child values of every object in the source collection.
-
- An of that contains the source collection.
- An of that contains the values of every token in the source collection.
-
-
-
- Returns a collection of converted child values of every object in the source collection with the given key.
-
- The type to convert the values to.
- An of that contains the source collection.
- The token key.
- An that contains the converted values of every token in the source collection with the given key.
-
-
-
- Returns a collection of converted child values of every object in the source collection.
-
- The type to convert the values to.
- An of that contains the source collection.
- An that contains the converted values of every token in the source collection.
-
-
-
- Converts the value.
-
- The type to convert the value to.
- A cast as a of .
- A converted value.
-
-
-
- Converts the value.
-
- The source collection type.
- The type to convert the value to.
- A cast as a of .
- A converted value.
-
-
-
- Returns a collection of child tokens of every array in the source collection.
-
- The source collection type.
- An of that contains the source collection.
- An of that contains the values of every token in the source collection.
-
-
-
- Returns a collection of converted child tokens of every array in the source collection.
-
- An of that contains the source collection.
- The type to convert the values to.
- The source collection type.
- An that contains the converted values of every token in the source collection.
-
-
-
- Returns the input typed as .
-
- An of that contains the source collection.
- The input typed as .
-
-
-
- Returns the input typed as .
-
- The source collection type.
- An of that contains the source collection.
- The input typed as .
-
-
-
- Represents a collection of objects.
-
- The type of token.
-
-
-
- Gets the of with the specified key.
-
-
-
-
-
- Represents a JSON array.
-
-
-
-
-
-
-
- Writes this token to a asynchronously.
-
- A into which this method will write.
- The token to monitor for cancellation requests.
- A collection of which will be used when writing the token.
- A that represents the asynchronous write operation.
-
-
-
- Asynchronously loads a from a .
-
- A that will be read for the content of the .
- If this is null, default load settings will be used.
- The token to monitor for cancellation requests. The default value is .
- A representing the asynchronous load. The property contains the JSON that was read from the specified .
-
-
-
- Asynchronously loads a from a .
-
- A that will be read for the content of the .
- The used to load the JSON.
- If this is null, default load settings will be used.
- The token to monitor for cancellation requests. The default value is .
- A representing the asynchronous load. The property contains the JSON that was read from the specified .
-
-
-
- Gets the container's children tokens.
-
- The container's children tokens.
-
-
-
- Gets the node type for this .
-
- The type.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class from another object.
-
- A object to copy from.
-
-
-
- Initializes a new instance of the class with the specified content.
-
- The contents of the array.
-
-
-
- Initializes a new instance of the class with the specified content.
-
- The contents of the array.
-
-
-
- Loads an from a .
-
- A that will be read for the content of the .
- A that contains the JSON that was read from the specified .
-
-
-
- Loads an from a .
-
- A that will be read for the content of the .
- The used to load the JSON.
- If this is null, default load settings will be used.
- A that contains the JSON that was read from the specified .
-
-
-
- Load a from a string that contains JSON.
-
- A that contains JSON.
- A populated from the string that contains JSON.
-
-
-
-
-
-
- Load a from a string that contains JSON.
-
- A that contains JSON.
- The used to load the JSON.
- If this is null, default load settings will be used.
- A populated from the string that contains JSON.
-
-
-
-
-
-
- Creates a from an object.
-
- The object that will be used to create .
- A with the values of the specified object.
-
-
-
- Creates a from an object.
-
- The object that will be used to create .
- The that will be used to read the object.
- A with the values of the specified object.
-
-
-
- Writes this token to a .
-
- A into which this method will write.
- A collection of which will be used when writing the token.
-
-
-
- Gets the with the specified key.
-
- The with the specified key.
-
-
-
- Gets or sets the at the specified index.
-
-
-
-
-
- Determines the index of a specific item in the .
-
- The object to locate in the .
-
- The index of if found in the list; otherwise, -1.
-
-
-
-
- Inserts an item to the at the specified index.
-
- The zero-based index at which should be inserted.
- The object to insert into the .
-
- is not a valid index in the .
-
-
-
-
- Removes the item at the specified index.
-
- The zero-based index of the item to remove.
-
- is not a valid index in the .
-
-
-
-
- Returns an enumerator that iterates through the collection.
-
-
- A of that can be used to iterate through the collection.
-
-
-
-
- Adds an item to the .
-
- The object to add to the .
-
-
-
- Removes all items from the .
-
-
-
-
- Determines whether the contains a specific value.
-
- The object to locate in the .
-
- true if is found in the ; otherwise, false.
-
-
-
-
- Copies the elements of the to an array, starting at a particular array index.
-
- The array.
- Index of the array.
-
-
-
- Gets a value indicating whether the is read-only.
-
- true if the is read-only; otherwise, false.
-
-
-
- Removes the first occurrence of a specific object from the .
-
- The object to remove from the .
-
- true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original .
-
-
-
-
- Represents a JSON constructor.
-
-
-
-
- Writes this token to a asynchronously.
-
- A into which this method will write.
- The token to monitor for cancellation requests.
- A collection of which will be used when writing the token.
- A that represents the asynchronous write operation.
-
-
-
- Asynchronously loads a from a .
-
- A that will be read for the content of the .
- The token to monitor for cancellation requests. The default value is .
-
- A that represents the asynchronous load. The
- property returns a that contains the JSON that was read from the specified .
-
-
-
- Asynchronously loads a from a .
-
- A that will be read for the content of the .
- The used to load the JSON.
- If this is null, default load settings will be used.
- The token to monitor for cancellation requests. The default value is .
-
- A that represents the asynchronous load. The
- property returns a that contains the JSON that was read from the specified .
-
-
-
- Gets the container's children tokens.
-
- The container's children tokens.
-
-
-
- Gets or sets the name of this constructor.
-
- The constructor name.
-
-
-
- Gets the node type for this .
-
- The type.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class from another object.
-
- A object to copy from.
-
-
-
- Initializes a new instance of the class with the specified name and content.
-
- The constructor name.
- The contents of the constructor.
-
-
-
- Initializes a new instance of the class with the specified name and content.
-
- The constructor name.
- The contents of the constructor.
-
-
-
- Initializes a new instance of the class with the specified name.
-
- The constructor name.
-
-
-
- Writes this token to a .
-
- A into which this method will write.
- A collection of which will be used when writing the token.
-
-
-
- Gets the with the specified key.
-
- The with the specified key.
-
-
-
- Loads a from a .
-
- A that will be read for the content of the .
- A that contains the JSON that was read from the specified .
-
-
-
- Loads a from a .
-
- A that will be read for the content of the .
- The used to load the JSON.
- If this is null, default load settings will be used.
- A that contains the JSON that was read from the specified .
-
-
-
- Represents a token that can contain other tokens.
-
-
-
-
- Occurs when the list changes or an item in the list changes.
-
-
-
-
- Occurs before an item is added to the collection.
-
-
-
-
- Occurs when the items list of the collection has changed, or the collection is reset.
-
-
-
-
- Gets the container's children tokens.
-
- The container's children tokens.
-
-
-
- Raises the event.
-
- The instance containing the event data.
-
-
-
- Raises the event.
-
- The instance containing the event data.
-
-
-
- Raises the event.
-
- The instance containing the event data.
-
-
-
- Gets a value indicating whether this token has child tokens.
-
-
- true if this token has child values; otherwise, false.
-
-
-
-
- Get the first child token of this token.
-
-
- A containing the first child token of the .
-
-
-
-
- Get the last child token of this token.
-
-
- A containing the last child token of the .
-
-
-
-
- Returns a collection of the child tokens of this token, in document order.
-
-
- An of containing the child tokens of this , in document order.
-
-
-
-
- Returns a collection of the child values of this token, in document order.
-
- The type to convert the values to.
-
- A containing the child values of this , in document order.
-
-
-
-
- Returns a collection of the descendant tokens for this token in document order.
-
- An of containing the descendant tokens of the .
-
-
-
- Returns a collection of the tokens that contain this token, and all descendant tokens of this token, in document order.
-
- An of containing this token, and all the descendant tokens of the .
-
-
-
- Adds the specified content as children of this .
-
- The content to be added.
-
-
-
- Adds the specified content as the first children of this .
-
- The content to be added.
-
-
-
- Creates a that can be used to add tokens to the .
-
- A that is ready to have content written to it.
-
-
-
- Replaces the child nodes of this token with the specified content.
-
- The content.
-
-
-
- Removes the child nodes from this token.
-
-
-
-
- Merge the specified content into this .
-
- The content to be merged.
-
-
-
- Merge the specified content into this using .
-
- The content to be merged.
- The used to merge the content.
-
-
-
- Gets the count of child JSON tokens.
-
- The count of child JSON tokens.
-
-
-
- Represents a collection of objects.
-
- The type of token.
-
-
-
- An empty collection of objects.
-
-
-
-
- Initializes a new instance of the struct.
-
- The enumerable.
-
-
-
- Returns an enumerator that can be used to iterate through the collection.
-
-
- A that can be used to iterate through the collection.
-
-
-
-
- Gets the of with the specified key.
-
-
-
-
-
- Determines whether the specified is equal to this instance.
-
- The to compare with this instance.
-
- true if the specified is equal to this instance; otherwise, false.
-
-
-
-
- Determines whether the specified is equal to this instance.
-
- The to compare with this instance.
-
- true if the specified is equal to this instance; otherwise, false.
-
-
-
-
- Returns a hash code for this instance.
-
-
- A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
-
-
-
-
- Represents a JSON object.
-
-
-
-
-
-
-
- Writes this token to a asynchronously.
-
- A into which this method will write.
- The token to monitor for cancellation requests.
- A collection of which will be used when writing the token.
- A that represents the asynchronous write operation.
-
-
-
- Asynchronously loads a from a .
-
- A that will be read for the content of the .
- The token to monitor for cancellation requests. The default value is .
-
- A that represents the asynchronous load. The
- property returns a that contains the JSON that was read from the specified .
-
-
-
- Asynchronously loads a from a .
-
- A that will be read for the content of the .
- The used to load the JSON.
- If this is null, default load settings will be used.
- The token to monitor for cancellation requests. The default value is .
-
- A that represents the asynchronous load. The
- property returns a that contains the JSON that was read from the specified .
-
-
-
- Gets the container's children tokens.
-
- The container's children tokens.
-
-
-
- Occurs when a property value changes.
-
-
-
-
- Occurs when a property value is changing.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class from another object.
-
- A object to copy from.
-
-
-
- Initializes a new instance of the class with the specified content.
-
- The contents of the object.
-
-
-
- Initializes a new instance of the class with the specified content.
-
- The contents of the object.
-
-
-
- Gets the node type for this .
-
- The type.
-
-
-
- Gets an of of this object's properties.
-
- An of of this object's properties.
-
-
-
- Gets a the specified name.
-
- The property name.
- A with the specified name or null.
-
-
-
- Gets a of of this object's property values.
-
- A of of this object's property values.
-
-
-
- Gets the with the specified key.
-
- The with the specified key.
-
-
-
- Gets or sets the with the specified property name.
-
-
-
-
-
- Loads a from a .
-
- A that will be read for the content of the .
- A that contains the JSON that was read from the specified .
-
- is not valid JSON.
-
-
-
-
- Loads a from a .
-
- A that will be read for the content of the .
- The used to load the JSON.
- If this is null, default load settings will be used.
- A that contains the JSON that was read from the specified .
-
- is not valid JSON.
-
-
-
-
- Load a from a string that contains JSON.
-
- A that contains JSON.
- A populated from the string that contains JSON.
-
- is not valid JSON.
-
-
-
-
-
-
-
- Load a from a string that contains JSON.
-
- A that contains JSON.
- The used to load the JSON.
- If this is null, default load settings will be used.
- A populated from the string that contains JSON.
-
- is not valid JSON.
-
-
-
-
-
-
-
- Creates a from an object.
-
- The object that will be used to create .
- A with the values of the specified object.
-
-
-
- Creates a from an object.
-
- The object that will be used to create .
- The that will be used to read the object.
- A with the values of the specified object.
-
-
-
- Writes this token to a .
-
- A into which this method will write.
- A collection of which will be used when writing the token.
-
-
-
- Gets the with the specified property name.
-
- Name of the property.
- The with the specified property name.
-
-
-
- Gets the with the specified property name.
- The exact property name will be searched for first and if no matching property is found then
- the will be used to match a property.
-
- Name of the property.
- One of the enumeration values that specifies how the strings will be compared.
- The with the specified property name.
-
-
-
- Tries to get the with the specified property name.
- The exact property name will be searched for first and if no matching property is found then
- the will be used to match a property.
-
- Name of the property.
- The value.
- One of the enumeration values that specifies how the strings will be compared.
- true if a value was successfully retrieved; otherwise, false.
-
-
-
- Adds the specified property name.
-
- Name of the property.
- The value.
-
-
-
- Determines whether the JSON object has the specified property name.
-
- Name of the property.
- true if the JSON object has the specified property name; otherwise, false.
-
-
-
- Removes the property with the specified name.
-
- Name of the property.
- true if item was successfully removed; otherwise, false.
-
-
-
- Tries to get the with the specified property name.
-
- Name of the property.
- The value.
- true if a value was successfully retrieved; otherwise, false.
-
-
-
- Returns an enumerator that can be used to iterate through the collection.
-
-
- A that can be used to iterate through the collection.
-
-
-
-
- Raises the event with the provided arguments.
-
- Name of the property.
-
-
-
- Raises the event with the provided arguments.
-
- Name of the property.
-
-
-
- Returns the responsible for binding operations performed on this object.
-
- The expression tree representation of the runtime value.
-
- The to bind this object.
-
-
-
-
- Represents a JSON property.
-
-
-
-
- Writes this token to a asynchronously.
-
- A into which this method will write.
- The token to monitor for cancellation requests.
- A collection of which will be used when writing the token.
- A that represents the asynchronous write operation.
-
-
-
- Asynchronously loads a from a .
-
- A that will be read for the content of the .
- The token to monitor for cancellation requests. The default value is .
- A representing the asynchronous creation. The
- property returns a that contains the JSON that was read from the specified .
-
-
-
- Asynchronously loads a from a .
-
- A that will be read for the content of the .
- The used to load the JSON.
- If this is null, default load settings will be used.
- The token to monitor for cancellation requests. The default value is .
- A representing the asynchronous creation. The
- property returns a that contains the JSON that was read from the specified .
-
-
-
- Gets the container's children tokens.
-
- The container's children tokens.
-
-
-
- Gets the property name.
-
- The property name.
-
-
-
- Gets or sets the property value.
-
- The property value.
-
-
-
- Initializes a new instance of the class from another object.
-
- A object to copy from.
-
-
-
- Gets the node type for this .
-
- The type.
-
-
-
- Initializes a new instance of the class.
-
- The property name.
- The property content.
-
-
-
- Initializes a new instance of the class.
-
- The property name.
- The property content.
-
-
-
- Writes this token to a .
-
- A into which this method will write.
- A collection of which will be used when writing the token.
-
-
-
- Loads a from a .
-
- A that will be read for the content of the .
- A that contains the JSON that was read from the specified .
-
-
-
- Loads a from a .
-
- A that will be read for the content of the .
- The used to load the JSON.
- If this is null, default load settings will be used.
- A that contains the JSON that was read from the specified .
-
-
-
- Represents a view of a .
-
-
-
-
- Initializes a new instance of the class.
-
- The name.
-
-
-
- When overridden in a derived class, returns whether resetting an object changes its value.
-
-
- true if resetting the component changes its value; otherwise, false.
-
- The component to test for reset capability.
-
-
-
- When overridden in a derived class, gets the current value of the property on a component.
-
-
- The value of a property for a given component.
-
- The component with the property for which to retrieve the value.
-
-
-
- When overridden in a derived class, resets the value for this property of the component to the default value.
-
- The component with the property value that is to be reset to the default value.
-
-
-
- When overridden in a derived class, sets the value of the component to a different value.
-
- The component with the property value that is to be set.
- The new value.
-
-
-
- When overridden in a derived class, determines a value indicating whether the value of this property needs to be persisted.
-
-
- true if the property should be persisted; otherwise, false.
-
- The component with the property to be examined for persistence.
-
-
-
- When overridden in a derived class, gets the type of the component this property is bound to.
-
-
- A that represents the type of component this property is bound to.
- When the or
-
- methods are invoked, the object specified might be an instance of this type.
-
-
-
-
- When overridden in a derived class, gets a value indicating whether this property is read-only.
-
-
- true if the property is read-only; otherwise, false.
-
-
-
-
- When overridden in a derived class, gets the type of the property.
-
-
- A that represents the type of the property.
-
-
-
-
- Gets the hash code for the name of the member.
-
-
-
- The hash code for the name of the member.
-
-
-
-
- Represents a raw JSON string.
-
-
-
-
- Asynchronously creates an instance of with the content of the reader's current token.
-
- The reader.
- The token to monitor for cancellation requests. The default value is .
- A representing the asynchronous creation. The
- property returns an instance of with the content of the reader's current token.
-
-
-
- Initializes a new instance of the class from another object.
-
- A object to copy from.
-
-
-
- Initializes a new instance of the class.
-
- The raw json.
-
-
-
- Creates an instance of with the content of the reader's current token.
-
- The reader.
- An instance of with the content of the reader's current token.
-
-
-
- Specifies the settings used when loading JSON.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Gets or sets how JSON comments are handled when loading JSON.
-
- The JSON comment handling.
-
-
-
- Gets or sets how JSON line info is handled when loading JSON.
-
- The JSON line info handling.
-
-
-
- Specifies the settings used when merging JSON.
-
-
-
-
- Gets or sets the method used when merging JSON arrays.
-
- The method used when merging JSON arrays.
-
-
-
- Gets or sets how null value properties are merged.
-
- How null value properties are merged.
-
-
-
- Represents an abstract JSON token.
-
-
-
-
- Writes this token to a asynchronously.
-
- A into which this method will write.
- The token to monitor for cancellation requests.
- A collection of which will be used when writing the token.
- A that represents the asynchronous write operation.
-
-
-
- Writes this token to a asynchronously.
-
- A into which this method will write.
- A collection of which will be used when writing the token.
- A that represents the asynchronous write operation.
-
-
-
- Asynchronously creates a from a .
-
- An positioned at the token to read into this .
- The token to monitor for cancellation requests. The default value is .
-
- A that represents the asynchronous creation. The
- property returns a that contains
- the token and its descendant tokens
- that were read from the reader. The runtime type of the token is determined
- by the token type of the first token encountered in the reader.
-
-
-
-
- Asynchronously creates a from a .
-
- An positioned at the token to read into this .
- The used to load the JSON.
- If this is null, default load settings will be used.
- The token to monitor for cancellation requests. The default value is .
-
- A that represents the asynchronous creation. The
- property returns a that contains
- the token and its descendant tokens
- that were read from the reader. The runtime type of the token is determined
- by the token type of the first token encountered in the reader.
-
-
-
-
- Asynchronously creates a from a .
-
- A positioned at the token to read into this .
- The token to monitor for cancellation requests. The default value is .
-
- A that represents the asynchronous creation. The
- property returns a that contains the token and its descendant tokens
- that were read from the reader. The runtime type of the token is determined
- by the token type of the first token encountered in the reader.
-
-
-
-
- Asynchronously creates a from a .
-
- A positioned at the token to read into this .
- The used to load the JSON.
- If this is null, default load settings will be used.
- The token to monitor for cancellation requests. The default value is .
-
- A that represents the asynchronous creation. The
- property returns a that contains the token and its descendant tokens
- that were read from the reader. The runtime type of the token is determined
- by the token type of the first token encountered in the reader.
-
-
-
-
- Gets a comparer that can compare two tokens for value equality.
-
- A that can compare two nodes for value equality.
-
-
-
- Gets or sets the parent.
-
- The parent.
-
-
-
- Gets the root of this .
-
- The root of this .
-
-
-
- Gets the node type for this .
-
- The type.
-
-
-
- Gets a value indicating whether this token has child tokens.
-
-
- true if this token has child values; otherwise, false.
-
-
-
-
- Compares the values of two tokens, including the values of all descendant tokens.
-
- The first to compare.
- The second to compare.
- true if the tokens are equal; otherwise false.
-
-
-
- Gets the next sibling token of this node.
-
- The that contains the next sibling token.
-
-
-
- Gets the previous sibling token of this node.
-
- The that contains the previous sibling token.
-
-
-
- Gets the path of the JSON token.
-
-
-
-
- Adds the specified content immediately after this token.
-
- A content object that contains simple content or a collection of content objects to be added after this token.
-
-
-
- Adds the specified content immediately before this token.
-
- A content object that contains simple content or a collection of content objects to be added before this token.
-
-
-
- Returns a collection of the ancestor tokens of this token.
-
- A collection of the ancestor tokens of this token.
-
-
-
- Returns a collection of tokens that contain this token, and the ancestors of this token.
-
- A collection of tokens that contain this token, and the ancestors of this token.
-
-
-
- Returns a collection of the sibling tokens after this token, in document order.
-
- A collection of the sibling tokens after this tokens, in document order.
-
-
-
- Returns a collection of the sibling tokens before this token, in document order.
-
- A collection of the sibling tokens before this token, in document order.
-
-
-
- Gets the with the specified key.
-
- The with the specified key.
-
-
-
- Gets the with the specified key converted to the specified type.
-
- The type to convert the token to.
- The token key.
- The converted token value.
-
-
-
- Get the first child token of this token.
-
- A containing the first child token of the .
-
-
-
- Get the last child token of this token.
-
- A containing the last child token of the .
-
-
-
- Returns a collection of the child tokens of this token, in document order.
-
- An of containing the child tokens of this , in document order.
-
-
-
- Returns a collection of the child tokens of this token, in document order, filtered by the specified type.
-
- The type to filter the child tokens on.
- A containing the child tokens of this , in document order.
-
-
-
- Returns a collection of the child values of this token, in document order.
-
- The type to convert the values to.
- A containing the child values of this , in document order.
-
-
-
- Removes this token from its parent.
-
-
-
-
- Replaces this token with the specified token.
-
- The value.
-
-
-
- Writes this token to a .
-
- A into which this method will write.
- A collection of which will be used when writing the token.
-
-
-
- Returns the indented JSON for this token.
-
-
- The indented JSON for this token.
-
-
-
-
- Returns the JSON for this token using the given formatting and converters.
-
- Indicates how the output should be formatted.
- A collection of s which will be used when writing the token.
- The JSON for this token using the given formatting and converters.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to [].
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to of .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an explicit conversion from to .
-
- The value.
- The result of the conversion.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from [] to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Performs an implicit conversion from of to .
-
- The value to create a from.
- The initialized with the specified value.
-
-
-
- Creates a for this token.
-
- A that can be used to read this token and its descendants.
-
-
-
- Creates a from an object.
-
- The object that will be used to create .
- A with the value of the specified object.
-
-
-
- Creates a from an object using the specified .
-
- The object that will be used to create .
- The that will be used when reading the object.
- A with the value of the specified object.
-
-
-
- Creates an instance of the specified .NET type from the .
-
- The object type that the token will be deserialized to.
- The new object created from the JSON value.
-
-
-
- Creates an instance of the specified .NET type from the .
-
- The object type that the token will be deserialized to.
- The new object created from the JSON value.
-
-
-
- Creates an instance of the specified .NET type from the using the specified .
-
- The object type that the token will be deserialized to.
- The that will be used when creating the object.
- The new object created from the JSON value.
-
-
-
- Creates an instance of the specified .NET type from the using the specified .
-
- The object type that the token will be deserialized to.
- The that will be used when creating the object.
- The new object created from the JSON value.
-
-
-
- Creates a from a .
-
- A positioned at the token to read into this .
-
- A that contains the token and its descendant tokens
- that were read from the reader. The runtime type of the token is determined
- by the token type of the first token encountered in the reader.
-
-
-
-
- Creates a from a .
-
- An positioned at the token to read into this .
- The used to load the JSON.
- If this is null, default load settings will be used.
-
- A that contains the token and its descendant tokens
- that were read from the reader. The runtime type of the token is determined
- by the token type of the first token encountered in the reader.
-
-
-
-
- Load a from a string that contains JSON.
-
- A that contains JSON.
- A populated from the string that contains JSON.
-
-
-
- Load a from a string that contains JSON.
-
- A that contains JSON.
- The used to load the JSON.
- If this is null, default load settings will be used.
- A populated from the string that contains JSON.
-
-
-
- Creates a from a .
-
- A positioned at the token to read into this .
- The used to load the JSON.
- If this is null, default load settings will be used.
-
- A that contains the token and its descendant tokens
- that were read from the reader. The runtime type of the token is determined
- by the token type of the first token encountered in the reader.
-
-
-
-
- Creates a from a .
-
- A positioned at the token to read into this .
-
- A that contains the token and its descendant tokens
- that were read from the reader. The runtime type of the token is determined
- by the token type of the first token encountered in the reader.
-
-
-
-
- Selects a using a JPath expression. Selects the token that matches the object path.
-
-
- A that contains a JPath expression.
-
- A , or null.
-
-
-
- Selects a using a JPath expression. Selects the token that matches the object path.
-
-
- A that contains a JPath expression.
-
- A flag to indicate whether an error should be thrown if no tokens are found when evaluating part of the expression.
- A .
-
-
-
- Selects a collection of elements using a JPath expression.
-
-
- A that contains a JPath expression.
-
- An of that contains the selected elements.
-
-
-
- Selects a collection of elements using a JPath expression.
-
-
- A that contains a JPath expression.
-
- A flag to indicate whether an error should be thrown if no tokens are found when evaluating part of the expression.
- An of that contains the selected elements.
-
-
-
- Returns the responsible for binding operations performed on this object.
-
- The expression tree representation of the runtime value.
-
- The to bind this object.
-
-
-
-
- Returns the responsible for binding operations performed on this object.
-
- The expression tree representation of the runtime value.
-
- The to bind this object.
-
-
-
-
- Creates a new instance of the . All child tokens are recursively cloned.
-
- A new instance of the .
-
-
-
- Adds an object to the annotation list of this .
-
- The annotation to add.
-
-
-
- Get the first annotation object of the specified type from this .
-
- The type of the annotation to retrieve.
- The first annotation object that matches the specified type, or null if no annotation is of the specified type.
-
-
-
- Gets the first annotation object of the specified type from this .
-
- The of the annotation to retrieve.
- The first annotation object that matches the specified type, or null if no annotation is of the specified type.
-
-
-
- Gets a collection of annotations of the specified type for this .
-
- The type of the annotations to retrieve.
- An that contains the annotations for this .
-
-
-
- Gets a collection of annotations of the specified type for this .
-
- The of the annotations to retrieve.
- An of that contains the annotations that match the specified type for this .
-
-
-
- Removes the annotations of the specified type from this .
-
- The type of annotations to remove.
-
-
-
- Removes the annotations of the specified type from this .
-
- The of annotations to remove.
-
-
-
- Compares tokens to determine whether they are equal.
-
-
-
-
- Determines whether the specified objects are equal.
-
- The first object of type to compare.
- The second object of type to compare.
-
- true if the specified objects are equal; otherwise, false.
-
-
-
-
- Returns a hash code for the specified object.
-
- The for which a hash code is to be returned.
- A hash code for the specified object.
- The type of is a reference type and is null.
-
-
-
- Represents a reader that provides fast, non-cached, forward-only access to serialized JSON data.
-
-
-
-
- Gets the at the reader's current position.
-
-
-
-
- Initializes a new instance of the class.
-
- The token to read from.
-
-
-
- Reads the next JSON token from the underlying .
-
-
- true if the next token was read successfully; false if there are no more tokens to read.
-
-
-
-
- Gets the path of the current JSON token.
-
-
-
-
- Specifies the type of token.
-
-
-
-
- No token type has been set.
-
-
-
-
- A JSON object.
-
-
-
-
- A JSON array.
-
-
-
-
- A JSON constructor.
-
-
-
-
- A JSON object property.
-
-
-
-
- A comment.
-
-
-
-
- An integer value.
-
-
-
-
- A float value.
-
-
-
-
- A string value.
-
-
-
-
- A boolean value.
-
-
-
-
- A null value.
-
-
-
-
- An undefined value.
-
-
-
-
- A date value.
-
-
-
-
- A raw JSON value.
-
-
-
-
- A collection of bytes value.
-
-
-
-
- A Guid value.
-
-
-
-
- A Uri value.
-
-
-
-
- A TimeSpan value.
-
-
-
-
- Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data.
-
-
-
-
- Gets the at the writer's current position.
-
-
-
-
- Gets the token being written.
-
- The token being written.
-
-
-
- Initializes a new instance of the class writing to the given .
-
- The container being written to.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Flushes whatever is in the buffer to the underlying .
-
-
-
-
- Closes this writer.
- If is set to true, the JSON is auto-completed.
-
-
- Setting to true has no additional effect, since the underlying is a type that cannot be closed.
-
-
-
-
- Writes the beginning of a JSON object.
-
-
-
-
- Writes the beginning of a JSON array.
-
-
-
-
- Writes the start of a constructor with the given name.
-
- The name of the constructor.
-
-
-
- Writes the end.
-
- The token.
-
-
-
- Writes the property name of a name/value pair on a JSON object.
-
- The name of the property.
-
-
-
- Writes a value.
- An error will be raised if the value cannot be written as a single JSON token.
-
- The value to write.
-
-
-
- Writes a null value.
-
-
-
-
- Writes an undefined value.
-
-
-
-
- Writes raw JSON.
-
- The raw JSON to write.
-
-
-
- Writes a comment /*...*/ containing the specified text.
-
- Text to place inside the comment.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a [] value.
-
- The [] value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Writes a value.
-
- The value to write.
-
-
-
- Represents a value in JSON (string, integer, date, etc).
-
-
-
-
- Writes this token to a asynchronously.
-
- A into which this method will write.
- The token to monitor for cancellation requests.
- A collection of which will be used when writing the token.
- A that represents the asynchronous write operation.
-
-
-
- Initializes a new instance of the class from another object.
-
- A object to copy from.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Initializes a new instance of the class with the given value.
-
- The value.
-
-
-
- Gets a value indicating whether this token has child tokens.
-
-
- true if this token has child values; otherwise, false.
-
-
-
-
- Creates a comment with the given value.
-
- The value.
- A comment with the given value.
-
-
-
- Creates a string with the given value.
-
- The value.
- A string with the given value.
-
-
-
- Creates a null value.
-
- A null value.
-
-
-
- Creates a undefined value.
-
- A undefined value.
-
-
-
- Gets the node type for this .
-
- The type.
-
-
-
- Gets or sets the underlying token value.
-
- The underlying token value.
-
-
-
- Writes this token to a .
-
- A into which this method will write.
- A collection of s which will be used when writing the token.
-
-
-
- Indicates whether the current object is equal to another object of the same type.
-
-
- true if the current object is equal to the parameter; otherwise, false.
-
- An object to compare with this object.
-
-
-
- Determines whether the specified is equal to the current .
-
- The to compare with the current .
-
- true if the specified is equal to the current ; otherwise, false.
-
-
-
-
- Serves as a hash function for a particular type.
-
-
- A hash code for the current .
-
-
-
-
- Returns a that represents this instance.
-
-
- A that represents this instance.
-
-
-
-
- Returns a that represents this instance.
-
- The format.
-
- A that represents this instance.
-
-
-
-
- Returns a that represents this instance.
-
- The format provider.
-
- A that represents this instance.
-
-
-
-
- Returns a that represents this instance.
-
- The format.
- The format provider.
-
- A that represents this instance.
-
-
-
-
- Returns the responsible for binding operations performed on this object.
-
- The expression tree representation of the runtime value.
-
- The to bind this object.
-
-
-
-
- Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
-
- An object to compare with this instance.
-
- A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has these meanings:
- Value
- Meaning
- Less than zero
- This instance is less than .
- Zero
- This instance is equal to .
- Greater than zero
- This instance is greater than .
-
-
- is not of the same type as this instance.
-
-
-
-
- Specifies how line information is handled when loading JSON.
-
-
-
-
- Ignore line information.
-
-
-
-
- Load line information.
-
-
-
-
- Specifies how JSON arrays are merged together.
-
-
-
- Concatenate arrays.
-
-
- Union arrays, skipping items that already exist.
-
-
- Replace all array items.
-
-
- Merge array items together, matched by index.
-
-
-
- Specifies how null value properties are merged.
-
-
-
-
- The content's null value properties will be ignored during merging.
-
-
-
-
- The content's null value properties will be merged.
-
-
-
-
- Specifies the member serialization options for the .
-
-
-
-
- All public members are serialized by default. Members can be excluded using or .
- This is the default member serialization mode.
-
-
-
-
- Only members marked with or are serialized.
- This member serialization mode can also be set by marking the class with .
-
-
-
-
- All public and private fields are serialized. Members can be excluded using or .
- This member serialization mode can also be set by marking the class with
- and setting IgnoreSerializableAttribute on to false.
-
-
-
-
- Specifies metadata property handling options for the .
-
-
-
-
- Read metadata properties located at the start of a JSON object.
-
-
-
-
- Read metadata properties located anywhere in a JSON object. Note that this setting will impact performance.
-
-
-
-
- Do not try to read metadata properties.
-
-
-
-
- Specifies missing member handling options for the .
-
-
-
-
- Ignore a missing member and do not attempt to deserialize it.
-
-
-
-
- Throw a when a missing member is encountered during deserialization.
-
-
-
-
- Specifies null value handling options for the .
-
-
-
-
-
-
-
-
- Include null values when serializing and deserializing objects.
-
-
-
-
- Ignore null values when serializing and deserializing objects.
-
-
-
-
- Specifies how object creation is handled by the .
-
-
-
-
- Reuse existing objects, create new objects when needed.
-
-
-
-
- Only reuse existing objects.
-
-
-
-
- Always create new objects.
-
-
-
-
- Specifies reference handling options for the .
- Note that references cannot be preserved when a value is set via a non-default constructor such as types that implement .
-
-
-
-
-
-
-
- Do not preserve references when serializing types.
-
-
-
-
- Preserve references when serializing into a JSON object structure.
-
-
-
-
- Preserve references when serializing into a JSON array structure.
-
-
-
-
- Preserve references when serializing.
-
-
-
-
- Specifies reference loop handling options for the .
-
-
-
-
- Throw a when a loop is encountered.
-
-
-
-
- Ignore loop references and do not serialize.
-
-
-
-
- Serialize loop references.
-
-
-
-
- Indicating whether a property is required.
-
-
-
-
- The property is not required. The default state.
-
-
-
-
- The property must be defined in JSON but can be a null value.
-
-
-
-
- The property must be defined in JSON and cannot be a null value.
-
-
-
-
- The property is not required but it cannot be a null value.
-
-
-
-
-
- Contains the JSON schema extension methods.
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
-
- Determines whether the is valid.
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
- The source to test.
- The schema to test with.
-
- true if the specified is valid; otherwise, false.
-
-
-
-
-
- Determines whether the is valid.
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
- The source to test.
- The schema to test with.
- When this method returns, contains any error messages generated while validating.
-
- true if the specified is valid; otherwise, false.
-
-
-
-
-
- Validates the specified .
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
- The source to test.
- The schema to test with.
-
-
-
-
- Validates the specified .
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
- The source to test.
- The schema to test with.
- The validation event handler.
-
-
-
-
- An in-memory representation of a JSON Schema.
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- Gets or sets the id.
-
-
-
-
- Gets or sets the title.
-
-
-
-
- Gets or sets whether the object is required.
-
-
-
-
- Gets or sets whether the object is read-only.
-
-
-
-
- Gets or sets whether the object is visible to users.
-
-
-
-
- Gets or sets whether the object is transient.
-
-
-
-
- Gets or sets the description of the object.
-
-
-
-
- Gets or sets the types of values allowed by the object.
-
- The type.
-
-
-
- Gets or sets the pattern.
-
- The pattern.
-
-
-
- Gets or sets the minimum length.
-
- The minimum length.
-
-
-
- Gets or sets the maximum length.
-
- The maximum length.
-
-
-
- Gets or sets a number that the value should be divisible by.
-
- A number that the value should be divisible by.
-
-
-
- Gets or sets the minimum.
-
- The minimum.
-
-
-
- Gets or sets the maximum.
-
- The maximum.
-
-
-
- Gets or sets a flag indicating whether the value can not equal the number defined by the minimum attribute ().
-
- A flag indicating whether the value can not equal the number defined by the minimum attribute ().
-
-
-
- Gets or sets a flag indicating whether the value can not equal the number defined by the maximum attribute ().
-
- A flag indicating whether the value can not equal the number defined by the maximum attribute ().
-
-
-
- Gets or sets the minimum number of items.
-
- The minimum number of items.
-
-
-
- Gets or sets the maximum number of items.
-
- The maximum number of items.
-
-
-
- Gets or sets the of items.
-
- The of items.
-
-
-
- Gets or sets a value indicating whether items in an array are validated using the instance at their array position from .
-
-
- true if items are validated using their array position; otherwise, false.
-
-
-
-
- Gets or sets the of additional items.
-
- The of additional items.
-
-
-
- Gets or sets a value indicating whether additional items are allowed.
-
-
- true if additional items are allowed; otherwise, false.
-
-
-
-
- Gets or sets whether the array items must be unique.
-
-
-
-
- Gets or sets the of properties.
-
- The of properties.
-
-
-
- Gets or sets the of additional properties.
-
- The of additional properties.
-
-
-
- Gets or sets the pattern properties.
-
- The pattern properties.
-
-
-
- Gets or sets a value indicating whether additional properties are allowed.
-
-
- true if additional properties are allowed; otherwise, false.
-
-
-
-
- Gets or sets the required property if this property is present.
-
- The required property if this property is present.
-
-
-
- Gets or sets the a collection of valid enum values allowed.
-
- A collection of valid enum values allowed.
-
-
-
- Gets or sets disallowed types.
-
- The disallowed types.
-
-
-
- Gets or sets the default value.
-
- The default value.
-
-
-
- Gets or sets the collection of that this schema extends.
-
- The collection of that this schema extends.
-
-
-
- Gets or sets the format.
-
- The format.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Reads a from the specified .
-
- The containing the JSON Schema to read.
- The object representing the JSON Schema.
-
-
-
- Reads a from the specified .
-
- The containing the JSON Schema to read.
- The to use when resolving schema references.
- The object representing the JSON Schema.
-
-
-
- Load a from a string that contains JSON Schema.
-
- A that contains JSON Schema.
- A populated from the string that contains JSON Schema.
-
-
-
- Load a from a string that contains JSON Schema using the specified .
-
- A that contains JSON Schema.
- The resolver.
- A populated from the string that contains JSON Schema.
-
-
-
- Writes this schema to a .
-
- A into which this method will write.
-
-
-
- Writes this schema to a using the specified .
-
- A into which this method will write.
- The resolver used.
-
-
-
- Returns a that represents the current .
-
-
- A that represents the current .
-
-
-
-
-
- Returns detailed information about the schema exception.
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- Gets the line number indicating where the error occurred.
-
- The line number indicating where the error occurred.
-
-
-
- Gets the line position indicating where the error occurred.
-
- The line position indicating where the error occurred.
-
-
-
- Gets the path to the JSON where the error occurred.
-
- The path to the JSON where the error occurred.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Initializes a new instance of the class
- with a specified error message.
-
- The error message that explains the reason for the exception.
-
-
-
- Initializes a new instance of the class
- with a specified error message and a reference to the inner exception that is the cause of this exception.
-
- The error message that explains the reason for the exception.
- The exception that is the cause of the current exception, or null if no inner exception is specified.
-
-
-
-
- Generates a from a specified .
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- Gets or sets how undefined schemas are handled by the serializer.
-
-
-
-
- Gets or sets the contract resolver.
-
- The contract resolver.
-
-
-
- Generate a from the specified type.
-
- The type to generate a from.
- A generated from the specified type.
-
-
-
- Generate a from the specified type.
-
- The type to generate a from.
- The used to resolve schema references.
- A generated from the specified type.
-
-
-
- Generate a from the specified type.
-
- The type to generate a from.
- Specify whether the generated root will be nullable.
- A generated from the specified type.
-
-
-
- Generate a from the specified type.
-
- The type to generate a from.
- The used to resolve schema references.
- Specify whether the generated root will be nullable.
- A generated from the specified type.
-
-
-
-
- Resolves from an id.
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- Gets or sets the loaded schemas.
-
- The loaded schemas.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Gets a for the specified reference.
-
- The id.
- A for the specified reference.
-
-
-
-
- The value types allowed by the .
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- No type specified.
-
-
-
-
- String type.
-
-
-
-
- Float type.
-
-
-
-
- Integer type.
-
-
-
-
- Boolean type.
-
-
-
-
- Object type.
-
-
-
-
- Array type.
-
-
-
-
- Null type.
-
-
-
-
- Any type.
-
-
-
-
-
- Specifies undefined schema Id handling options for the .
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- Do not infer a schema Id.
-
-
-
-
- Use the .NET type name as the schema Id.
-
-
-
-
- Use the assembly qualified .NET type name as the schema Id.
-
-
-
-
-
- Returns detailed information related to the .
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- Gets the associated with the validation error.
-
- The JsonSchemaException associated with the validation error.
-
-
-
- Gets the path of the JSON location where the validation error occurred.
-
- The path of the JSON location where the validation error occurred.
-
-
-
- Gets the text description corresponding to the validation error.
-
- The text description.
-
-
-
-
- Represents the callback method that will handle JSON schema validation events and the .
-
-
- JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.
-
-
-
-
-
- A camel case naming strategy.
-
-
-
-
- Initializes a new instance of the class.
-
-
- A flag indicating whether dictionary keys should be processed.
-
-
- A flag indicating whether explicitly specified property names should be processed,
- e.g. a property name customized with a .
-
-
-
-
- Initializes a new instance of the class.
-
-
- A flag indicating whether dictionary keys should be processed.
-
-
- A flag indicating whether explicitly specified property names should be processed,
- e.g. a property name customized with a .
-
-
- A flag indicating whether extension data names should be processed.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Resolves the specified property name.
-
- The property name to resolve.
- The resolved property name.
-
-
-
- Resolves member mappings for a type, camel casing property names.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Resolves the contract for a given type.
-
- The type to resolve a contract for.
- The contract for a given type.
-
-
-
- Used by to resolve a for a given .
-
-
-
-
- Gets a value indicating whether members are being get and set using dynamic code generation.
- This value is determined by the runtime permissions available.
-
-
- true if using dynamic code generation; otherwise, false.
-
-
-
-
- Gets or sets the default members search flags.
-
- The default members search flags.
-
-
-
- Gets or sets a value indicating whether compiler generated members should be serialized.
-
-
- true if serialized compiler generated members; otherwise, false.
-
-
-
-
- Gets or sets a value indicating whether to ignore the interface when serializing and deserializing types.
-
-
- true if the interface will be ignored when serializing and deserializing types; otherwise, false.
-
-
-
-
- Gets or sets a value indicating whether to ignore the attribute when serializing and deserializing types.
-
-
- true if the attribute will be ignored when serializing and deserializing types; otherwise, false.
-
-
-
-
- Gets or sets a value indicating whether to ignore IsSpecified members when serializing and deserializing types.
-
-
- true if the IsSpecified members will be ignored when serializing and deserializing types; otherwise, false.
-
-
-
-
- Gets or sets a value indicating whether to ignore ShouldSerialize members when serializing and deserializing types.
-
-
- true if the ShouldSerialize members will be ignored when serializing and deserializing types; otherwise, false.
-
-
-
-
- Gets or sets the naming strategy used to resolve how property names and dictionary keys are serialized.
-
- The naming strategy used to resolve how property names and dictionary keys are serialized.
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Resolves the contract for a given type.
-
- The type to resolve a contract for.
- The contract for a given type.
-
-
-
- Gets the serializable members for the type.
-
- The type to get serializable members for.
- The serializable members for the type.
-
-
-
- Creates a for the given type.
-
- Type of the object.
- A for the given type.
-
-
-
- Creates the constructor parameters.
-
- The constructor to create properties for.
- The type's member properties.
- Properties for the given .
-
-
-
- Creates a for the given .
-
- The matching member property.
- The constructor parameter.
- A created for the given .
-
-
-
- Resolves the default for the contract.
-
- Type of the object.
- The contract's default .
-
-
-
- Creates a for the given type.
-
- Type of the object.
- A for the given type.
-
-
-
- Creates a for the given type.
-
- Type of the object.
- A for the given type.
-
-
-
- Creates a for the given type.
-
- Type of the object.
- A for the given type.
-
-
-
- Creates a for the given type.
-
- Type of the object.
- A for the given type.
-
-
-
- Creates a for the given type.
-
- Type of the object.
- A for the given type.
-
-
-
- Creates a for the given type.
-
- Type of the object.
- A for the given type.
-
-
-
- Determines which contract type is created for the given type.
-
- Type of the object.
- A for the given type.
-
-
-
- Creates properties for the given .
-
- The type to create properties for.
- /// The member serialization mode for the type.
- Properties for the given .
-
-
-
- Creates the used by the serializer to get and set values from a member.
-
- The member.
- The used by the serializer to get and set values from a member.
-
-
-
- Creates a for the given .
-
- The member's parent .
- The member to create a for.
- A created for the given .
-
-
-
- Resolves the name of the property.
-
- Name of the property.
- Resolved name of the property.
-
-
-
- Resolves the name of the extension data. By default no changes are made to extension data names.
-
- Name of the extension data.
- Resolved name of the extension data.
-
-
-
- Resolves the key of the dictionary. By default is used to resolve dictionary keys.
-
- Key of the dictionary.
- Resolved key of the dictionary.
-
-
-
- Gets the resolved name of the property.
-
- Name of the property.
- Name of the property.
-
-
-
- The default naming strategy. Property names and dictionary keys are unchanged.
-
-
-
-
- Resolves the specified property name.
-
- The property name to resolve.
- The resolved property name.
-
-
-
- The default serialization binder used when resolving and loading classes from type names.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- When overridden in a derived class, controls the binding of a serialized object to a type.
-
- Specifies the name of the serialized object.
- Specifies the name of the serialized object.
-
- The type of the object the formatter creates a new instance of.
-
-
-
-
- When overridden in a derived class, controls the binding of a serialized object to a type.
-
- The type of the object the formatter creates a new instance of.
- Specifies the name of the serialized object.
- Specifies the name of the serialized object.
-
-
-
- Provides information surrounding an error.
-
-
-
-
- Gets the error.
-
- The error.
-
-
-
- Gets the original object that caused the error.
-
- The original object that caused the error.
-
-
-
- Gets the member that caused the error.
-
- The member that caused the error.
-
-
-
- Gets the path of the JSON location where the error occurred.
-
- The path of the JSON location where the error occurred.
-
-
-
- Gets or sets a value indicating whether this is handled.
-
- true if handled; otherwise, false.
-
-
-
- Provides data for the Error event.
-
-
-
-
- Gets the current object the error event is being raised against.
-
- The current object the error event is being raised against.
-
-
-
- Gets the error context.
-
- The error context.
-
-
-
- Initializes a new instance of the class.
-
- The current object.
- The error context.
-
-
-
- Get and set values for a using dynamic methods.
-
-
-
-
- Initializes a new instance of the class.
-
- The member info.
-
-
-
- Sets the value.
-
- The target to set the value on.
- The value to set on the target.
-
-
-
- Gets the value.
-
- The target to get the value from.
- The value.
-
-
-
- Provides methods to get attributes.
-
-
-
-
- Returns a collection of all of the attributes, or an empty collection if there are no attributes.
-
- When true, look up the hierarchy chain for the inherited custom attribute.
- A collection of s, or an empty collection.
-
-
-
- Returns a collection of attributes, identified by type, or an empty collection if there are no attributes.
-
- The type of the attributes.
- When true, look up the hierarchy chain for the inherited custom attribute.
- A collection of s, or an empty collection.
-
-
-
- Used by to resolve a for a given .
-
-
-
-
-
-
-
-
- Resolves the contract for a given type.
-
- The type to resolve a contract for.
- The contract for a given type.
-
-
-
- Used to resolve references when serializing and deserializing JSON by the .
-
-
-
-
- Resolves a reference to its object.
-
- The serialization context.
- The reference to resolve.
- The object that was resolved from the reference.
-
-
-
- Gets the reference for the specified object.
-
- The serialization context.
- The object to get a reference for.
- The reference to the object.
-
-
-
- Determines whether the specified object is referenced.
-
- The serialization context.
- The object to test for a reference.
-
- true if the specified object is referenced; otherwise, false.
-
-
-
-
- Adds a reference to the specified object.
-
- The serialization context.
- The reference.
- The object to reference.
-
-
-
- Allows users to control class loading and mandate what class to load.
-
-
-
-
- When implemented, controls the binding of a serialized object to a type.
-
- Specifies the name of the serialized object.
- Specifies the name of the serialized object
- The type of the object the formatter creates a new instance of.
-
-
-
- When implemented, controls the binding of a serialized object to a type.
-
- The type of the object the formatter creates a new instance of.
- Specifies the name of the serialized object.
- Specifies the name of the serialized object.
-
-
-
- Provides methods to get and set values.
-
-
-
-
- Sets the value.
-
- The target to set the value on.
- The value to set on the target.
-
-
-
- Gets the value.
-
- The target to get the value from.
- The value.
-
-
-
- Contract details for a used by the .
-
-
-
-
- Gets the of the collection items.
-
- The of the collection items.
-
-
-
- Gets a value indicating whether the collection type is a multidimensional array.
-
- true if the collection type is a multidimensional array; otherwise, false.
-
-
-
- Gets or sets the function used to create the object. When set this function will override .
-
- The function used to create the object.
-
-
-
- Gets a value indicating whether the creator has a parameter with the collection values.
-
- true if the creator has a parameter with the collection values; otherwise, false.
-
-
-
- Initializes a new instance of the class.
-
- The underlying type for the contract.
-
-
-
- Contract details for a used by the .
-
-
-
-
- Gets or sets the default collection items .
-
- The converter.
-
-
-
- Gets or sets a value indicating whether the collection items preserve object references.
-
- true if collection items preserve object references; otherwise, false.
-
-
-
- Gets or sets the collection item reference loop handling.
-
- The reference loop handling.
-
-
-
- Gets or sets the collection item type name handling.
-
- The type name handling.
-
-
-
- Initializes a new instance of the class.
-
- The underlying type for the contract.
-
-
-
- Sets extension data for an object during deserialization.
-
- The object to set extension data on.
- The extension data key.
- The extension data value.
-
-
-
- Gets extension data for an object during serialization.
-
- The object to set extension data on.
-
-
-
- Contract details for a used by the .
-
-
-
-
- Gets the underlying type for the contract.
-
- The underlying type for the contract.
-
-
-
- Gets or sets the type created during deserialization.
-
- The type created during deserialization.
-
-
-
- Gets or sets whether this type contract is serialized as a reference.
-
- Whether this type contract is serialized as a reference.
-
-
-
- Gets or sets the default for this contract.
-
- The converter.
-
-
-
- Gets or sets the default creator method used to create the object.
-
- The default creator method used to create the object.
-
-
-
- Gets or sets a value indicating whether the default creator is non-public.
-
- true if the default object creator is non-public; otherwise, false.
-
-
-
- Contract details for a used by the .
-
-
-
-
- Gets or sets the dictionary key resolver.
-
- The dictionary key resolver.
-
-
-
- Gets the of the dictionary keys.
-
- The of the dictionary keys.
-
-
-
- Gets the of the dictionary values.
-
- The of the dictionary values.
-
-
-
- Gets or sets the function used to create the object. When set this function will override .
-
- The function used to create the object.
-
-
-
- Gets a value indicating whether the creator has a parameter with the dictionary values.
-
- true if the creator has a parameter with the dictionary values; otherwise, false.
-
-
-
- Initializes a new instance of the class.
-
- The underlying type for the contract.
-
-
-
- Contract details for a used by the .
-
-
-
-
- Gets the object's properties.
-
- The object's properties.
-
-
-
- Gets or sets the property name resolver.
-
- The property name resolver.
-
-
-
- Initializes a new instance of the class.
-
- The underlying type for the contract.
-
-
-
- Contract details for a used by the .
-
-
-
-
- Initializes a new instance of the class.
-
- The underlying type for the contract.
-
-
-
- Contract details for a used by the .
-
-
-
-
- Gets or sets the object member serialization.
-
- The member object serialization.
-
-
-
- Gets or sets a value that indicates whether the object's properties are required.
-
-
- A value indicating whether the object's properties are required.
-
-
-
-
- Gets or sets how the object's properties with null values are handled during serialization and deserialization.
-
- How the object's properties with null values are handled during serialization and deserialization.
-
-
-
- Gets the object's properties.
-
- The object's properties.
-
-
-
- Gets a collection of instances that define the parameters used with .
-
-
-
-
- Gets or sets the function used to create the object. When set this function will override .
- This function is called with a collection of arguments which are defined by the collection.
-
- The function used to create the object.
-
-
-
- Gets or sets the extension data setter.
-
-
-
-
- Gets or sets the extension data getter.
-
-
-
-
- Gets or sets the extension data value type.
-
-
-
-
- Gets or sets the extension data name resolver.
-
- The extension data name resolver.
-
-
-
- Initializes a new instance of the class.
-
- The underlying type for the contract.
-
-
-
- Contract details for a used by the .
-
-
-
-
- Initializes a new instance of the class.
-
- The underlying type for the contract.
-
-
-
- Maps a JSON property to a .NET member or constructor parameter.
-
-
-
-
- Gets or sets the name of the property.
-
- The name of the property.
-
-
-
- Gets or sets the type that declared this property.
-
- The type that declared this property.
-
-
-
- Gets or sets the order of serialization of a member.
-
- The numeric order of serialization.
-
-
-
- Gets or sets the name of the underlying member or parameter.
-
- The name of the underlying member or parameter.
-
-
-
- Gets the that will get and set the during serialization.
-
- The that will get and set the during serialization.
-
-
-
- Gets or sets the for this property.
-
- The for this property.
-
-
-
- Gets or sets the type of the property.
-
- The type of the property.
-
-
-
- Gets or sets the for the property.
- If set this converter takes precedence over the contract converter for the property type.
-
- The converter.
-
-
-
- Gets or sets the member converter.
-
- The member converter.
-
-
-
- Gets or sets a value indicating whether this is ignored.
-
- true if ignored; otherwise, false.
-
-
-
- Gets or sets a value indicating whether this is readable.
-
- true if readable; otherwise, false.
-
-
-
- Gets or sets a value indicating whether this is writable.
-
- true if writable; otherwise, false.
-
-
-
- Gets or sets a value indicating whether this has a member attribute.
-
- true if has a member attribute; otherwise, false.
-
-
-
- Gets the default value.
-
- The default value.
-
-
-
- Gets or sets a value indicating whether this is required.
-
- A value indicating whether this is required.
-
-
-
- Gets or sets a value indicating whether this property preserves object references.
-
-
- true if this instance is reference; otherwise, false.
-
-
-
-
- Gets or sets the property null value handling.
-
- The null value handling.
-
-
-
- Gets or sets the property default value handling.
-
- The default value handling.
-
-
-
- Gets or sets the property reference loop handling.
-
- The reference loop handling.
-
-
-
- Gets or sets the property object creation handling.
-
- The object creation handling.
-
-
-
- Gets or sets or sets the type name handling.
-
- The type name handling.
-
-
-
- Gets or sets a predicate used to determine whether the property should be serialized.
-
- A predicate used to determine whether the property should be serialized.
-
-
-
- Gets or sets a predicate used to determine whether the property should be deserialized.
-
- A predicate used to determine whether the property should be deserialized.
-
-
-
- Gets or sets a predicate used to determine whether the property should be serialized.
-
- A predicate used to determine whether the property should be serialized.
-
-
-
- Gets or sets an action used to set whether the property has been deserialized.
-
- An action used to set whether the property has been deserialized.
-
-
-
- Returns a that represents this instance.
-
-
- A that represents this instance.
-
-
-
-
- Gets or sets the converter used when serializing the property's collection items.
-
- The collection's items converter.
-
-
-
- Gets or sets whether this property's collection items are serialized as a reference.
-
- Whether this property's collection items are serialized as a reference.
-
-
-
- Gets or sets the type name handling used when serializing the property's collection items.
-
- The collection's items type name handling.
-
-
-
- Gets or sets the reference loop handling used when serializing the property's collection items.
-
- The collection's items reference loop handling.
-
-
-
- A collection of objects.
-
-
-
-
- Initializes a new instance of the class.
-
- The type.
-
-
-
- When implemented in a derived class, extracts the key from the specified element.
-
- The element from which to extract the key.
- The key for the specified element.
-
-
-
- Adds a object.
-
- The property to add to the collection.
-
-
-
- Gets the closest matching object.
- First attempts to get an exact case match of and then
- a case insensitive match.
-
- Name of the property.
- A matching property if found.
-
-
-
- Gets a property by property name.
-
- The name of the property to get.
- Type property name string comparison.
- A matching property if found.
-
-
-
- The JSON writer.
-
-
-
-
-
- Gets the size of the serialize stack (amount of the objects serialized in the hierachy before the current).
-
-
-
-
- Contract details for a used by the .
-
-
-
-
- Initializes a new instance of the class.
-
- The underlying type for the contract.
-
-
-
- Lookup and create an instance of the type described by the argument.
-
- The type to create.
- Optional arguments to pass to an initializing constructor of the JsonConverter.
- If null, the default constructor is used.
-
-
-
- A base class for resolving how property names and dictionary keys are serialized.
-
-
-
-
- A flag indicating whether dictionary keys should be processed.
- Defaults to false.
-
-
-
-
- A flag indicating whether extension data names should be processed.
- Defaults to false.
-
-
-
-
- A flag indicating whether explicitly specified property names,
- e.g. a property name customized with a , should be processed.
- Defaults to false.
-
-
-
-
- Gets the serialized name for a given property name.
-
- The initial property name.
- A flag indicating whether the property has had a name explicitly specified.
- The serialized property name.
-
-
-
- Gets the serialized name for a given extension data name.
-
- The initial extension data name.
- The serialized extension data name.
-
-
-
- Gets the serialized key for a given dictionary key.
-
- The initial dictionary key.
- The serialized dictionary key.
-
-
-
- Resolves the specified property name.
-
- The property name to resolve.
- The resolved property name.
-
-
-
- Represents a method that constructs an object.
-
- The object type to create.
-
-
-
- When applied to a method, specifies that the method is called when an error occurs serializing an object.
-
-
-
-
- Provides methods to get attributes from a , , or .
-
-
-
-
- Initializes a new instance of the class.
-
- The instance to get attributes for. This parameter should be a , , or .
-
-
-
- Returns a collection of all of the attributes, or an empty collection if there are no attributes.
-
- When true, look up the hierarchy chain for the inherited custom attribute.
- A collection of s, or an empty collection.
-
-
-
- Returns a collection of attributes, identified by type, or an empty collection if there are no attributes.
-
- The type of the attributes.
- When true, look up the hierarchy chain for the inherited custom attribute.
- A collection of s, or an empty collection.
-
-
-
- Get and set values for a using reflection.
-
-
-
-
- Initializes a new instance of the class.
-
- The member info.
-
-
-
- Sets the value.
-
- The target to set the value on.
- The value to set on the target.
-
-
-
- Gets the value.
-
- The target to get the value from.
- The value.
-
-
-
- A snake case naming strategy.
-
-
-
-
- Initializes a new instance of the class.
-
-
- A flag indicating whether dictionary keys should be processed.
-
-
- A flag indicating whether explicitly specified property names should be processed,
- e.g. a property name customized with a .
-
-
-
-
- Initializes a new instance of the class.
-
-
- A flag indicating whether dictionary keys should be processed.
-
-
- A flag indicating whether explicitly specified property names should be processed,
- e.g. a property name customized with a .
-
-
- A flag indicating whether extension data names should be processed.
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
- Resolves the specified property name.
-
- The property name to resolve.
- The resolved property name.
-
-
-
- Specifies how strings are escaped when writing JSON text.
-
-
-
-
- Only control characters (e.g. newline) are escaped.
-
-
-
-
- All non-ASCII and control characters (e.g. newline) are escaped.
-
-
-
-
- HTML (<, >, &, ', ") and control characters (e.g. newline) are escaped.
-
-
-
-
- Indicates the method that will be used during deserialization for locating and loading assemblies.
-
-
-
-
- In simple mode, the assembly used during deserialization need not match exactly the assembly used during serialization. Specifically, the version numbers need not match as the LoadWithPartialName method of the class is used to load the assembly.
-
-
-
-
- In full mode, the assembly used during deserialization must match exactly the assembly used during serialization. The Load method of the class is used to load the assembly.
-
-
-
-
- Specifies type name handling options for the .
-
-
- should be used with caution when your application deserializes JSON from an external source.
- Incoming types should be validated with a custom
- when deserializing with a value other than .
-
-
-
-
- Do not include the .NET type name when serializing types.
-
-
-
-
- Include the .NET type name when serializing into a JSON object structure.
-
-
-
-
- Include the .NET type name when serializing into a JSON array structure.
-
-
-
-
- Always include the .NET type name when serializing.
-
-
-
-
- Include the .NET type name when the type of the object being serialized is not the same as its declared type.
- Note that this doesn't include the root serialized object by default. To include the root object's type name in JSON
- you must specify a root type object with
- or .
-
-
-
-
- Determines whether the collection is null or empty.
-
- The collection.
-
- true if the collection is null or empty; otherwise, false.
-
-
-
-
- Adds the elements of the specified collection to the specified generic .
-
- The list to add to.
- The collection of elements to add.
-
-
-
- Converts the value to the specified type. If the value is unable to be converted, the
- value is checked whether it assignable to the specified type.
-
- The value to convert.
- The culture to use when converting.
- The type to convert or cast the value to.
-
- The converted type. If conversion was unsuccessful, the initial value
- is returned if assignable to the target type.
-
-
-
-
- Helper method for generating a MetaObject which calls a
- specific method on Dynamic that returns a result
-
-
-
-
- Helper method for generating a MetaObject which calls a
- specific method on Dynamic, but uses one of the arguments for
- the result.
-
-
-
-
- Helper method for generating a MetaObject which calls a
- specific method on Dynamic, but uses one of the arguments for
- the result.
-
-
-
-
- Returns a Restrictions object which includes our current restrictions merged
- with a restriction limiting our type
-
-
-
-
- Helper class for serializing immutable collections.
- Note that this is used by all builds, even those that don't support immutable collections, in case the DLL is GACed
- https://github.com/JamesNK/Newtonsoft.Json/issues/652
-
-
-
-
- Helper utilities.
-
-
-
-
- Compares two objects data.
-
- The object a.
- The object b.
- True if both objects are equal, otherwise false.
-
-
-
- The custom value comparision callback.
-
-
-
-
- The default implementation of the values comparision function.
-
- The object a.
- The object b.
- True if both objects are equal, otherwise false.
-
-
-
- Gets the type of the typed collection's items.
-
- The type.
- The type of the typed collection's items.
-
-
-
- Gets the member's underlying type.
-
- The member.
- The underlying type of the member.
-
-
-
- Determines whether the member is an indexed property.
-
- The member.
-
- true if the member is an indexed property; otherwise, false.
-
-
-
-
- Determines whether the property is an indexed property.
-
- The property.
-
- true if the property is an indexed property; otherwise, false.
-
-
-
-
- Gets the member's value on the object.
-
- The member.
- The target object.
- The member's value on the object.
-
-
-
- Sets the member's value on the target object.
-
- The member.
- The target.
- The value.
-
-
-
- Determines whether the specified MemberInfo can be read.
-
- The MemberInfo to determine whether can be read.
- /// if set to true then allow the member to be gotten non-publicly.
-
- true if the specified MemberInfo can be read; otherwise, false.
-
-
-
-
- Determines whether the specified MemberInfo can be set.
-
- The MemberInfo to determine whether can be set.
- if set to true then allow the member to be set non-publicly.
- if set to true then allow the member to be set if read-only.
-
- true if the specified MemberInfo can be set; otherwise, false.
-
-
-
-
- Builds a string. Unlike this class lets you reuse its internal buffer.
-
-
-
-
- Determines whether the string is all white space. Empty string will return false.
-
- The string to test whether it is all white space.
-
- true if the string is all white space; otherwise, false.
-
-
-
-
- Specifies the state of the .
-
-
-
-
- An exception has been thrown, which has left the in an invalid state.
- You may call the method to put the in the Closed state.
- Any other method calls result in an being thrown.
-
-
-
-
- The method has been called.
-
-
-
-
- An object is being written.
-
-
-
-
- An array is being written.
-
-
-
-
- A constructor is being written.
-
-
-
-
- A property is being written.
-
-
-
-
- A write method has not been called.
-
-
-
-
diff --git a/Source/Shaders/BitonicSort.shader b/Source/Shaders/BitonicSort.shader
index 8a53802d0..8d2172b77 100644
--- a/Source/Shaders/BitonicSort.shader
+++ b/Source/Shaders/BitonicSort.shader
@@ -10,7 +10,8 @@ struct Item
};
META_CB_BEGIN(0, Data)
-Item NullItem;
+float NullItemKey;
+uint NullItemValue;
uint CounterOffset;
uint MaxIterations;
uint LoopK;
@@ -95,10 +96,17 @@ groupshared Item SortData[2048];
void LoadItem(uint element, uint count)
{
// Unused elements must sort to the end
+ Item item;
if (element < count)
- SortData[element & 2047] = SortBuffer[element];
+ {
+ item = SortBuffer[element];
+ }
else
- SortData[element & 2047] = NullItem;
+ {
+ item.Key = NullItemKey;
+ item.Value = NullItemValue;
+ }
+ SortData[element & 2047] = item;
}
void StoreItem(uint element, uint count)
diff --git a/Source/ThirdParty/PhysX/PhysX.Build.cs b/Source/ThirdParty/PhysX/PhysX.Build.cs
index 3c57c5cb4..d9ef72882 100644
--- a/Source/ThirdParty/PhysX/PhysX.Build.cs
+++ b/Source/ThirdParty/PhysX/PhysX.Build.cs
@@ -38,7 +38,7 @@ public class PhysX : DepsModule
bool useDynamicLinking = false;
bool usePVD = false;
- bool useVehicle = false;
+ bool useVehicle = true;
bool usePhysicsCooking = Physics.WithCooking;
var depsRoot = options.DepsFolder;
@@ -96,7 +96,7 @@ public class PhysX : DepsModule
if (useVehicle)
{
- AddLib(options, depsRoot, string.Format("PhysXVehicle_static_{0}", archPostFix));
+ AddLib(options, depsRoot, string.Format("PhysXVehicle_static{0}", archPostFix));
}
}
}
diff --git a/Source/ThirdParty/PhysX/foundation/PxIntrinsics.h b/Source/ThirdParty/PhysX/foundation/PxIntrinsics.h
index 8ddea2a0f..9f6d4a13a 100644
--- a/Source/ThirdParty/PhysX/foundation/PxIntrinsics.h
+++ b/Source/ThirdParty/PhysX/foundation/PxIntrinsics.h
@@ -39,7 +39,7 @@
#elif PX_XBOXONE
#include "foundation/XboxOne/PxXboxOneIntrinsics.h"
#elif PX_SWITCH
-#include "foundation/switch/PxSwitchIntrinsics.h"
+#include
#else
#error "Platform not supported!"
#endif
diff --git a/Source/ThirdParty/fmt/core.h b/Source/ThirdParty/fmt/core.h
index e109ecbd4..77b113a0a 100644
--- a/Source/ThirdParty/fmt/core.h
+++ b/Source/ThirdParty/fmt/core.h
@@ -22,7 +22,7 @@
#define FMT_ASSERT(condition, message) \
if (!(condition)) \
{ \
- Platform::Assert(message, __FILE__, __LINE__); \
+ Platform::CheckFailed(message, __FILE__, __LINE__); \
}
#else
#define FMT_ASSERT(condition, message) ((void)0)
diff --git a/Source/ThirdParty/freetype/freetype.Build.cs b/Source/ThirdParty/freetype/freetype.Build.cs
index 7cf93e32c..a5f697538 100644
--- a/Source/ThirdParty/freetype/freetype.Build.cs
+++ b/Source/ThirdParty/freetype/freetype.Build.cs
@@ -40,6 +40,7 @@ public class freetype : DepsModule
case TargetPlatform.Linux:
case TargetPlatform.PS4:
case TargetPlatform.Android:
+ case TargetPlatform.Switch:
options.OutputFiles.Add(Path.Combine(depsRoot, "libfreetype.a"));
break;
default: throw new InvalidPlatformException(options.Platform.Target);
diff --git a/Source/ThirdParty/glib.h b/Source/ThirdParty/glib.h
new file mode 100644
index 000000000..a8460bbe9
--- /dev/null
+++ b/Source/ThirdParty/glib.h
@@ -0,0 +1,36 @@
+// Wrapper for mono/mono/eglib/glib.h to mock the types for embedding
+
+#ifndef _GLIB_H_
+#define _GLIB_H_
+
+#include
+#include
+
+/*
+ * Basic data types
+ */
+typedef int gint;
+typedef unsigned int guint;
+typedef short gshort;
+typedef unsigned short gushort;
+typedef long glong;
+typedef unsigned long gulong;
+typedef void * gpointer;
+typedef const void * gconstpointer;
+typedef char gchar;
+typedef unsigned char guchar;
+
+/* Types defined in terms of the stdint.h */
+typedef int8_t gint8;
+typedef uint8_t guint8;
+typedef int16_t gint16;
+typedef uint16_t guint16;
+typedef int32_t gint32;
+typedef uint32_t guint32;
+typedef int64_t gint64;
+typedef uint64_t guint64;
+typedef float gfloat;
+typedef double gdouble;
+typedef int32_t gboolean;
+
+#endif
diff --git a/Source/ThirdParty/mono-2.0/mono.Build.cs b/Source/ThirdParty/mono-2.0/mono.Build.cs
index cfd942240..9fa592f35 100644
--- a/Source/ThirdParty/mono-2.0/mono.Build.cs
+++ b/Source/ThirdParty/mono-2.0/mono.Build.cs
@@ -86,6 +86,9 @@ public class mono : DepsModule
options.DependencyFiles.Add(Path.Combine(depsRoot, "libmonosgen-2.0.so"));
options.Libraries.Add(Path.Combine(depsRoot, "libmonosgen-2.0.so"));
break;
+ case TargetPlatform.Switch:
+ // TODO: mono for Switch
+ break;
default: throw new InvalidPlatformException(options.Platform.Target);
}
diff --git a/Source/ThirdParty/ogg/ogg.Build.cs b/Source/ThirdParty/ogg/ogg.Build.cs
index 5a2e1d7db..168391012 100644
--- a/Source/ThirdParty/ogg/ogg.Build.cs
+++ b/Source/ThirdParty/ogg/ogg.Build.cs
@@ -39,6 +39,7 @@ public class ogg : DepsModule
case TargetPlatform.Linux:
case TargetPlatform.PS4:
case TargetPlatform.Android:
+ case TargetPlatform.Switch:
options.OutputFiles.Add(Path.Combine(depsRoot, "libogg.a"));
break;
default: throw new InvalidPlatformException(options.Platform.Target);
diff --git a/Source/ThirdParty/pugixml/pugixml.cpp b/Source/ThirdParty/pugixml/pugixml.cpp
index 5b77a271c..af52e1ea8 100644
--- a/Source/ThirdParty/pugixml/pugixml.cpp
+++ b/Source/ThirdParty/pugixml/pugixml.cpp
@@ -4799,6 +4799,16 @@ namespace pugi
return xml_node();
}
+ PUGI__FN xml_node xml_node::child_or_append(const char_t* name_)
+ {
+ if (!_root) return xml_node();
+
+ for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
+ if (i->name && impl::strequal(name_, i->name)) return xml_node(i);
+
+ return append_child(name_);
+ }
+
PUGI__FN xml_attribute xml_node::attribute(const char_t* name_) const
{
if (!_root) return xml_attribute();
@@ -4869,7 +4879,18 @@ namespace pugi
return PUGIXML_TEXT("");
}
- PUGI__FN const char_t* xml_node::child_value(const char_t* name_) const
+ PUGI__FN bool xml_node::set_child_value(const char_t* rhs)
+ {
+ if (!_root) return false;
+
+ for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling)
+ if (i->value && impl::is_text_node(i))
+ return xml_node(i).set_value(rhs);
+
+ return append_child(node_pcdata).set_value(rhs);
+ }
+
+ PUGI__FN const char_t* xml_node::child_value(const char_t* name_) const
{
return child(name_).child_value();
}
diff --git a/Source/ThirdParty/pugixml/pugixml.hpp b/Source/ThirdParty/pugixml/pugixml.hpp
index d937bff47..fd71dfb1a 100644
--- a/Source/ThirdParty/pugixml/pugixml.hpp
+++ b/Source/ThirdParty/pugixml/pugixml.hpp
@@ -452,12 +452,14 @@ namespace pugi
// Get child, attribute or next/previous sibling with the specified name
xml_node child(const char_t* name) const;
+ xml_node child_or_append(const char_t* name);
xml_attribute attribute(const char_t* name) const;
xml_node next_sibling(const char_t* name) const;
xml_node previous_sibling(const char_t* name) const;
// Get child value of current node; that is, value of the first child node of type PCDATA/CDATA
const char_t* child_value() const;
+ bool set_child_value(const char_t* rhs);
// Get child value of child with specified name. Equivalent to child(name).child_value().
const char_t* child_value(const char_t* name) const;
diff --git a/Source/ThirdParty/vorbis/vorbis.Build.cs b/Source/ThirdParty/vorbis/vorbis.Build.cs
index d743ff327..33580959c 100644
--- a/Source/ThirdParty/vorbis/vorbis.Build.cs
+++ b/Source/ThirdParty/vorbis/vorbis.Build.cs
@@ -40,6 +40,7 @@ public class vorbis : DepsModule
break;
case TargetPlatform.Linux:
case TargetPlatform.Android:
+ case TargetPlatform.Switch:
options.OutputFiles.Add(Path.Combine(depsRoot, "libvorbis.a"));
options.OutputFiles.Add(Path.Combine(depsRoot, "libvorbisenc.a"));
options.OutputFiles.Add(Path.Combine(depsRoot, "libvorbisfile.a"));
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
index 44d3b457c..d41ecd501 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
@@ -11,6 +11,9 @@ namespace Flax.Build.Bindings
{
partial class BindingsGenerator
{
+ private static readonly HashSet CSharpUsedNamespaces = new HashSet();
+ private static readonly List CSharpUsedNamespacesSorted = new List();
+
private static readonly Dictionary CSharpNativeToManagedBasicTypes = new Dictionary()
{
// Language types
@@ -50,12 +53,52 @@ namespace Flax.Build.Bindings
{ "MonoArray", "Array" },
};
- private static string GenerateCSharpDefaultValueNativeToManaged(BuildData buildData, string value, ApiTypeInfo caller)
+ private static string GenerateCSharpDefaultValueNativeToManaged(BuildData buildData, string value, ApiTypeInfo caller, bool attribute = false)
{
if (string.IsNullOrEmpty(value))
return null;
+
+ // Special case for Engine TEXT macro
+ if (value.StartsWith("TEXT(\"") && value.EndsWith("\")"))
+ return value.Substring(5, value.Length - 6);
+
value = value.Replace("::", ".");
+ if (attribute)
+ {
+ // Value constructors (eg. Vector2(1, 2))
+ if (value.Contains('(') && value.Contains(')'))
+ {
+ // Support for in-built types
+ if (value.StartsWith("Vector2("))
+ return $"typeof(Vector2), \"{value.Substring(8, value.Length - 9).Replace("f", "")}\"";
+ if (value.StartsWith("Vector3("))
+ return $"typeof(Vector3), \"{value.Substring(8, value.Length - 9).Replace("f", "")}\"";
+ if (value.StartsWith("Vector4("))
+ return $"typeof(Vector4), \"{value.Substring(8, value.Length - 9).Replace("f", "")}\"";
+
+ return null;
+ }
+
+ // Constants (eg. Vector2::Zero)
+ if (value.Contains('.'))
+ {
+ // Support for in-built constants
+ switch (value)
+ {
+ case "Vector2.Zero": return "typeof(Vector2), \"0,0\"";
+ case "Vector2.One": return "typeof(Vector2), \"1,1\"";
+ case "Vector3.Zero": return "typeof(Vector3), \"0,0,0\"";
+ case "Vector3.One": return "typeof(Vector3), \"1,1,1\"";
+ case "Vector4.Zero": return "typeof(Vector4), \"0,0,0,0\"";
+ case "Vector4.One": return "typeof(Vector4), \"1,1,1,1\"";
+ case "Quaternion.Identity": return "typeof(Quaternion), \"0,0,0,1\"";
+ }
+
+ return null;
+ }
+ }
+
// Skip constants unsupported in C#
var dot = value.LastIndexOf('.');
if (dot != -1)
@@ -66,10 +109,6 @@ namespace Flax.Build.Bindings
return null;
}
- // Special case for Engine TEXT macro
- if (value.Contains("TEXT(\""))
- return value.Replace("TEXT(\"", "(\"");
-
// Special case for value constructors
if (value.Contains('(') && value.Contains(')'))
return "new " + value;
@@ -100,6 +139,8 @@ namespace Flax.Build.Bindings
private static string GenerateCSharpNativeToManaged(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo caller)
{
string result;
+ if (typeInfo?.Type == null)
+ throw new ArgumentNullException();
// Use dynamic array as wrapper container for fixed-size native arrays
if (typeInfo.IsArray)
@@ -394,26 +435,6 @@ namespace Flax.Build.Bindings
}
}
- private static bool IsDefaultValueSupported(string value)
- {
- // TEXT macro (eg. TEXT("text"))
- // TODO: support string for default value attribute
- if (value.Contains("TEXT(\""))
- return false;
-
- // Value constructors (eg. Vector2(1, 2))
- // TODO: support value constructors for default value attribute
- if (value.Contains('(') && value.Contains(')'))
- return false;
-
- // Constants (eg. Vector2::Zero)
- // TODO: support constants for default value attribute
- if (value.Contains("::"))
- return false;
-
- return true;
- }
-
private static void GenerateCSharpAttributes(BuildData buildData, StringBuilder contents, string indent, ApiTypeInfo apiTypeInfo, string attributes, string[] comment, bool canUseTooltip, bool useUnmanaged, string defaultValue = null)
{
var writeTooltip = true;
@@ -438,21 +459,27 @@ namespace Flax.Build.Bindings
if (comment.Length >= 3 &&
comment[0] == "/// " &&
comment[1].StartsWith("/// ") &&
- comment[2] == "/// ")
+ comment[comment.Length - 1] == "/// ")
{
var tooltip = comment[1].Substring(4);
if (tooltip.StartsWith("Gets the "))
tooltip = "The " + tooltip.Substring(9);
+ for (int i = 3; i < comment.Length; i++)
+ {
+ if (comment[i - 1].StartsWith("/// "))
+ tooltip += " " + comment[i - 1].Substring(4);
+ }
if (tooltip.IndexOf('\"') != -1)
tooltip = tooltip.Replace("\"", "\\\"");
contents.Append(indent).Append("[Tooltip(\"").Append(tooltip).Append("\")]").AppendLine();
}
}
- if (!string.IsNullOrEmpty(defaultValue) && writeDefaultValue && IsDefaultValueSupported(defaultValue))
+ if (writeDefaultValue)
{
// Write default value attribute
- defaultValue = GenerateCSharpDefaultValueNativeToManaged(buildData, defaultValue, apiTypeInfo);
- contents.Append(indent).Append("[DefaultValue(").Append(defaultValue).Append(")]").AppendLine();
+ defaultValue = GenerateCSharpDefaultValueNativeToManaged(buildData, defaultValue, apiTypeInfo, true);
+ if (defaultValue != null)
+ contents.Append(indent).Append("[DefaultValue(").Append(defaultValue).Append(")]").AppendLine();
}
}
@@ -642,12 +669,9 @@ namespace Flax.Build.Bindings
contents.Append(returnValueType).Append(' ').Append(fieldInfo.Name);
if (!useUnmanaged)
{
- if (fieldInfo.DefaultValue != null)
- {
- var defaultValue = GenerateCSharpDefaultValueNativeToManaged(buildData, fieldInfo.DefaultValue, classInfo);
- if (!string.IsNullOrEmpty(defaultValue))
- contents.Append(" = ").Append(defaultValue);
- }
+ var defaultValue = GenerateCSharpDefaultValueNativeToManaged(buildData, fieldInfo.DefaultValue, classInfo);
+ if (!string.IsNullOrEmpty(defaultValue))
+ contents.Append(" = ").Append(defaultValue);
contents.AppendLine(";");
continue;
}
@@ -773,12 +797,9 @@ namespace Flax.Build.Bindings
contents.Append(' ');
contents.Append(parameterInfo.Name);
- if (parameterInfo.DefaultValue != null)
- {
- var defaultValue = GenerateCSharpDefaultValueNativeToManaged(buildData, parameterInfo.DefaultValue, classInfo);
- if (!string.IsNullOrEmpty(defaultValue))
- contents.Append(" = ").Append(defaultValue);
- }
+ var defaultValue = GenerateCSharpDefaultValueNativeToManaged(buildData, parameterInfo.DefaultValue, classInfo);
+ if (!string.IsNullOrEmpty(defaultValue))
+ contents.Append(" = ").Append(defaultValue);
}
contents.Append(')').AppendLine().AppendLine(indent + "{");
@@ -1027,6 +1048,30 @@ namespace Flax.Build.Bindings
return true;
}
+ private static void GenerateCSharpCollectNamespaces(BuildData buildData, ApiTypeInfo apiType, HashSet usedNamespaces)
+ {
+ if (apiType is ClassInfo classInfo)
+ {
+ foreach (var field in classInfo.Fields)
+ {
+ var fieldInfo = FindApiTypeInfo(buildData, field.Type, classInfo);
+ if (fieldInfo != null && !string.IsNullOrWhiteSpace(fieldInfo.Namespace) && fieldInfo.Namespace != apiType.Namespace)
+ usedNamespaces.Add(fieldInfo.Namespace);
+ }
+ }
+ else if (apiType is StructureInfo structureInfo)
+ {
+ foreach (var field in structureInfo.Fields)
+ {
+ var fieldInfo = FindApiTypeInfo(buildData, field.Type, structureInfo);
+ if (fieldInfo != null && !string.IsNullOrWhiteSpace(fieldInfo.Namespace) && fieldInfo.Namespace != apiType.Namespace)
+ usedNamespaces.Add(fieldInfo.Namespace);
+ }
+ }
+ foreach (var child in apiType.Children)
+ GenerateCSharpCollectNamespaces(buildData, child, usedNamespaces);
+ }
+
private static void GenerateCSharp(BuildData buildData, ModuleInfo moduleInfo, ref BindingsResult bindings)
{
var contents = new StringBuilder();
@@ -1041,25 +1086,25 @@ namespace Flax.Build.Bindings
contents.AppendLine();
// Using declarations
- contents.AppendLine("using System;");
- contents.AppendLine("using System.ComponentModel;");
- contents.AppendLine("using System.Runtime.CompilerServices;");
- contents.AppendLine("using System.Runtime.InteropServices;");
+ CSharpUsedNamespaces.Clear();
+ CSharpUsedNamespaces.Add("System");
+ CSharpUsedNamespaces.Add("System.ComponentModel");
+ CSharpUsedNamespaces.Add("System.Globalization");
+ CSharpUsedNamespaces.Add("System.Runtime.CompilerServices");
+ CSharpUsedNamespaces.Add("System.Runtime.InteropServices");
+ CSharpUsedNamespaces.Add("FlaxEngine");
foreach (var e in moduleInfo.Children)
{
- bool tmp = false;
foreach (var apiTypeInfo in e.Children)
{
- if (apiTypeInfo.Namespace != "FlaxEngine")
- {
- tmp = true;
- contents.AppendLine("using FlaxEngine;");
- break;
- }
+ GenerateCSharpCollectNamespaces(buildData, apiTypeInfo, CSharpUsedNamespaces);
}
- if (tmp)
- break;
}
+ CSharpUsedNamespacesSorted.Clear();
+ CSharpUsedNamespacesSorted.AddRange(CSharpUsedNamespaces);
+ CSharpUsedNamespacesSorted.Sort();
+ foreach (var e in CSharpUsedNamespacesSorted)
+ contents.AppendLine($"using {e};");
// TODO: custom using declarations support
// TODO: generate using declarations based on references modules (eg. using FlaxEngine, using Plugin1 in game API)
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs
index 5f74e0403..1f8ab4249 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs
@@ -223,6 +223,7 @@ namespace Flax.Build.Bindings
if (!apiType.IsInBuild && !apiType.IsEnum)
{
// Use declared type initializer
+ CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h");
return $"{apiType.FullNameNative}::TypeInitializer.GetType().ManagedClass->GetNative()";
}
}
@@ -262,6 +263,67 @@ namespace Flax.Build.Bindings
return "Scripting::FindClassNative(\"" + managedType + "\")";
}
+ private static string GenerateCppGetNativeType(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo caller, FunctionInfo functionInfo)
+ {
+ // Optimal path for in-build types
+ var managedType = GenerateCSharpNativeToManaged(buildData, typeInfo, caller);
+ switch (managedType)
+ {
+ case "bool":
+ case "sbyte":
+ case "byte":
+ case "short":
+ case "ushort":
+ case "int":
+ case "uint":
+ case "long":
+ case "ulong":
+ case "float":
+ case "double":
+ case "string":
+ case "object":
+ case "void":
+ case "char":
+ case "IntPtr":
+ case "UIntPtr": return "mono_class_get_type(" + GenerateCppGetNativeClass(buildData, typeInfo, caller, null) + ')';
+ }
+
+ // Find API type
+ var apiType = FindApiTypeInfo(buildData, typeInfo, caller);
+ if (apiType != null)
+ {
+ CppReferencesFiles.Add(apiType.File);
+ if (apiType.IsStruct && !apiType.IsPod && !CppUsedNonPodTypes.Contains(apiType))
+ CppUsedNonPodTypes.Add(apiType);
+ if (!apiType.IsInBuild && !apiType.IsEnum)
+ {
+ // Use declared type initializer
+ CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h");
+ return $"mono_class_get_type({apiType.FullNameNative}::TypeInitializer.GetType().ManagedClass->GetNative())";
+ }
+ }
+
+ // Pass it from C# in glue parameter if used inside the wrapper function
+ if (functionInfo != null)
+ {
+ var customParam = new FunctionInfo.ParameterInfo
+ {
+ Name = "resultArrayItemType" + functionInfo.Glue.CustomParameters.Count,
+ DefaultValue = "typeof(" + managedType + ')',
+ Type = new TypeInfo
+ {
+ Type = "MonoReflectionType",
+ IsPtr = true,
+ },
+ };
+ functionInfo.Glue.CustomParameters.Add(customParam);
+ return "mono_reflection_type_get_type(" + customParam.Name + ')';
+ }
+
+ // Convert MonoClass* into MonoType*
+ return "mono_class_get_type" + GenerateCppGetNativeClass(buildData, typeInfo, caller, null) + ')';
+ }
+
private static string GenerateCppWrapperNativeToManaged(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo caller, out string type, FunctionInfo functionInfo)
{
// Use dynamic array as wrapper container for fixed-size native arrays
@@ -307,40 +369,10 @@ namespace Flax.Build.Bindings
case "MClass":
type = "MonoReflectionType*";
return "MUtils::GetType({0})";
+ case "CultureInfo":
+ type = "void*";
+ return "MUtils::ToManaged({0})";
default:
- var apiType = FindApiTypeInfo(buildData, typeInfo, caller);
- if (apiType != null)
- {
- CppReferencesFiles.Add(apiType.File);
-
- // Scripting Object
- if (apiType.IsScriptingObject)
- {
- type = "MonoObject*";
- return "ScriptingObject::ToManaged((ScriptingObject*){0})";
- }
-
- // Non-POD structure passed as value (eg. it contains string or array inside)
- if (apiType.IsStruct && !apiType.IsPod)
- {
- // Use wrapper structure that represents the memory layout of the managed data
- if (!CppUsedNonPodTypes.Contains(apiType))
- CppUsedNonPodTypes.Add(apiType);
- if (functionInfo != null)
- type = apiType.Name + "Managed*";
- else
- type = apiType.Name + "Managed";
- return "ToManaged({0})";
- }
-
- // Nested type (namespace prefix is required)
- if (!(apiType.Parent is FileInfo))
- {
- type = apiType.FullNameNative;
- return string.Empty;
- }
- }
-
// ScriptingObjectReference or AssetReference or WeakAssetReference or SoftObjectReference
if ((typeInfo.Type == "ScriptingObjectReference" || typeInfo.Type == "AssetReference" || typeInfo.Type == "WeakAssetReference" || typeInfo.Type == "SoftObjectReference") && typeInfo.GenericArgs != null)
{
@@ -368,8 +400,8 @@ namespace Flax.Build.Bindings
{
CppIncludeFiles.Add("Engine/Scripting/InternalCalls/ManagedDictionary.h");
type = "MonoObject*";
- var keyClass = GenerateCppGetNativeClass(buildData, typeInfo.GenericArgs[0], caller, functionInfo);
- var valueClass = GenerateCppGetNativeClass(buildData, typeInfo.GenericArgs[1], caller, functionInfo);
+ var keyClass = GenerateCppGetNativeType(buildData, typeInfo.GenericArgs[0], caller, functionInfo);
+ var valueClass = GenerateCppGetNativeType(buildData, typeInfo.GenericArgs[1], caller, functionInfo);
return "ManagedDictionary::ToManaged({0}, " + keyClass + ", " + valueClass + ")";
}
@@ -388,8 +420,54 @@ namespace Flax.Build.Bindings
return "ManagedBitArray::ToManaged({0})";
}
+ var apiType = FindApiTypeInfo(buildData, typeInfo, caller);
+ if (apiType != null)
+ {
+ CppReferencesFiles.Add(apiType.File);
+
+ // Scripting Object
+ if (apiType.IsScriptingObject)
+ {
+ type = "MonoObject*";
+ return "ScriptingObject::ToManaged((ScriptingObject*){0})";
+ }
+
+ // Non-POD structure passed as value (eg. it contains string or array inside)
+ if (apiType.IsStruct && !apiType.IsPod)
+ {
+ // Use wrapper structure that represents the memory layout of the managed data
+ if (!CppUsedNonPodTypes.Contains(apiType))
+ CppUsedNonPodTypes.Add(apiType);
+ if (functionInfo != null)
+ type = apiType.Name + "Managed*";
+ else
+ type = apiType.Name + "Managed";
+ return "ToManaged({0})";
+ }
+
+ // Managed class
+ if (apiType.IsClass)
+ {
+ // Use wrapper structure that represents the memory layout of the managed data
+ if (!CppUsedNonPodTypes.Contains(apiType))
+ {
+ CppUsedNonPodTypes.Add(apiType);
+ CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h");
+ }
+ type = "MonoObject*";
+ return "MConverter<" + apiType.Name + ">::Box({0})";
+ }
+
+ // Nested type (namespace prefix is required)
+ if (!(apiType.Parent is FileInfo))
+ {
+ type = apiType.FullNameNative;
+ return string.Empty;
+ }
+ }
+
type = typeInfo.ToString();
- return "{0}";
+ return string.Empty;
}
}
@@ -448,6 +526,9 @@ namespace Flax.Build.Bindings
case "VariantType":
type = "MonoReflectionType*";
return "MUtils::UnboxVariantType({0})";
+ case "CultureInfo":
+ type = "void*";
+ return "MUtils::ToNative({0})";
default:
// ScriptingObjectReference or AssetReference or WeakAssetReference or SoftObjectReference
if ((typeInfo.Type == "ScriptingObjectReference" || typeInfo.Type == "AssetReference" || typeInfo.Type == "WeakAssetReference" || typeInfo.Type == "SoftObjectReference") && typeInfo.GenericArgs != null)
@@ -547,6 +628,19 @@ namespace Flax.Build.Bindings
return "ToNative({0})";
}
+ // Managed class
+ if (apiType.IsClass && !apiType.IsScriptingObject)
+ {
+ // Use wrapper structure that represents the memory layout of the managed data
+ if (!CppUsedNonPodTypes.Contains(apiType))
+ {
+ CppUsedNonPodTypes.Add(apiType);
+ CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h");
+ }
+ type = "MonoObject*";
+ return "MConverter<" + apiType.Name + ">::Unbox({0})";
+ }
+
// Nested type (namespace prefix is required)
if (!(apiType.Parent is FileInfo))
{
@@ -997,6 +1091,8 @@ namespace Flax.Build.Bindings
var baseType = classInfo?.BaseType ?? structureInfo?.BaseType;
if (classInfo != null && classInfo.IsBaseTypeHidden)
baseType = null;
+ if (baseType != null && (baseType.Type == "PersistentScriptingObject" || baseType.Type == "ScriptingObject"))
+ baseType = null;
CppAutoSerializeFields.Clear();
CppAutoSerializeProperties.Clear();
CppIncludeFiles.Add("Engine/Serialization/Serialization.h");
@@ -1131,6 +1227,7 @@ namespace Flax.Build.Bindings
// C# event invoking wrapper (calls C# event from C++ delegate)
CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h");
CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MEvent.h");
+ CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h");
contents.Append(" ");
if (eventInfo.IsStatic)
contents.Append("static ");
@@ -1145,7 +1242,7 @@ namespace Flax.Build.Bindings
contents.Append(" {").AppendLine();
contents.Append(" static MMethod* mmethod = nullptr;").AppendLine();
contents.Append(" if (!mmethod)").AppendLine();
- contents.AppendFormat(" mmethod = {1}::GetStaticClass()->GetMethod(\"Internal_{0}_Invoke\", {2});", eventInfo.Name, classTypeNameNative, paramsCount).AppendLine();
+ contents.AppendFormat(" mmethod = {1}::TypeInitializer.GetType().ManagedClass->GetMethod(\"Internal_{0}_Invoke\", {2});", eventInfo.Name, classTypeNameNative, paramsCount).AppendLine();
contents.Append(" CHECK(mmethod);").AppendLine();
contents.Append(" MonoObject* exception = nullptr;").AppendLine();
if (paramsCount == 0)
@@ -1252,7 +1349,13 @@ namespace Flax.Build.Bindings
if (fieldInfo.Getter != null)
GenerateCppWrapperFunction(buildData, contents, classInfo, fieldInfo.Getter, "{0}");
if (fieldInfo.Setter != null)
- GenerateCppWrapperFunction(buildData, contents, classInfo, fieldInfo.Setter, "{0} = {1}");
+ {
+ var callFormat = "{0} = {1}";
+ var type = fieldInfo.Setter.Parameters[0].Type;
+ if (type.IsArray)
+ callFormat = $"auto __tmp = {{1}}; for (int32 i = 0; i < {type.ArraySize}; i++) {{0}}[i] = __tmp[i]";
+ GenerateCppWrapperFunction(buildData, contents, classInfo, fieldInfo.Setter, callFormat);
+ }
}
// Properties
@@ -1874,41 +1977,53 @@ namespace Flax.Build.Bindings
foreach (var apiType in CppUsedNonPodTypesList)
{
header.AppendLine();
- if (apiType is StructureInfo structureInfo)
+ var structureInfo = apiType as StructureInfo;
+ var classInfo = apiType as ClassInfo;
+ List fields;
+ if (structureInfo != null)
+ fields = structureInfo.Fields;
+ else if (classInfo != null)
+ fields = classInfo.Fields;
+ else
+ throw new Exception("Not supported Non-POD type " + apiType);
+
+ // Get the full typename with nested parent prefix
+ var fullName = apiType.FullNameNative;
+
+ // Generate managed type memory layout
+ header.Append("struct ").Append(apiType.Name).Append("Managed").AppendLine();
+ header.Append('{').AppendLine();
+ if (classInfo != null)
+ header.AppendLine(" MonoObject obj;");
+ for (var i = 0; i < fields.Count; i++)
{
- // Get the full typename with nested parent prefix
- var fullName = apiType.FullNameNative;
+ var fieldInfo = fields[i];
+ if (fieldInfo.IsStatic)
+ continue;
+ string type;
- // Generate managed structure memory layout
- header.Append("struct ").Append(apiType.Name).Append("Managed").AppendLine();
- header.Append('{').AppendLine();
- for (var i = 0; i < structureInfo.Fields.Count; i++)
+ if (fieldInfo.NoArray && fieldInfo.Type.IsArray)
{
- var fieldInfo = structureInfo.Fields[i];
- if (fieldInfo.IsStatic)
- continue;
- string type;
-
- if (fieldInfo.NoArray && fieldInfo.Type.IsArray)
- {
- // Fixed-size array that needs to be inlined into structure instead of passing it as managed array
- fieldInfo.Type.IsArray = false;
- CppParamsWrappersCache[i] = GenerateCppWrapperNativeToManaged(buildData, fieldInfo.Type, structureInfo, out type, null);
- fieldInfo.Type.IsArray = true;
- header.AppendFormat(" {0} {1}[{2}];", type, fieldInfo.Name, fieldInfo.Type.ArraySize).AppendLine();
- continue;
- }
-
- CppParamsWrappersCache[i] = GenerateCppWrapperNativeToManaged(buildData, fieldInfo.Type, structureInfo, out type, null);
- header.AppendFormat(" {0} {1};", type, fieldInfo.Name).AppendLine();
+ // Fixed-size array that needs to be inlined into structure instead of passing it as managed array
+ fieldInfo.Type.IsArray = false;
+ CppParamsWrappersCache[i] = GenerateCppWrapperNativeToManaged(buildData, fieldInfo.Type, apiType, out type, null);
+ fieldInfo.Type.IsArray = true;
+ header.AppendFormat(" {0} {1}[{2}];", type, fieldInfo.Name, fieldInfo.Type.ArraySize).AppendLine();
+ continue;
}
- header.Append('}').Append(';').AppendLine();
+ CppParamsWrappersCache[i] = GenerateCppWrapperNativeToManaged(buildData, fieldInfo.Type, apiType, out type, null);
+ header.AppendFormat(" {0} {1};", type, fieldInfo.Name).AppendLine();
+ }
+ header.Append('}').Append(';').AppendLine();
+
+ if (structureInfo != null)
+ {
// Generate forward declarations of structure converting functions
header.AppendLine();
header.AppendLine("namespace {");
- header.AppendFormat("{0}Managed ToManaged(const {1}& value);", structureInfo.Name, fullName).AppendLine();
- header.AppendFormat("{1} ToNative(const {0}Managed& value);", structureInfo.Name, fullName).AppendLine();
+ header.AppendFormat("{0}Managed ToManaged(const {1}& value);", apiType.Name, fullName).AppendLine();
+ header.AppendFormat("{1} ToNative(const {0}Managed& value);", apiType.Name, fullName).AppendLine();
header.AppendLine("}");
// Generate MConverter
@@ -1939,19 +2054,19 @@ namespace Flax.Build.Bindings
// Generate converting function native -> managed
header.AppendLine();
header.AppendLine("namespace {");
- header.AppendFormat("{0}Managed ToManaged(const {1}& value)", structureInfo.Name, fullName).AppendLine();
+ header.AppendFormat("{0}Managed ToManaged(const {1}& value)", apiType.Name, fullName).AppendLine();
header.Append('{').AppendLine();
- header.AppendFormat(" {0}Managed result;", structureInfo.Name).AppendLine();
- for (var i = 0; i < structureInfo.Fields.Count; i++)
+ header.AppendFormat(" {0}Managed result;", apiType.Name).AppendLine();
+ for (var i = 0; i < fields.Count; i++)
{
- var fieldInfo = structureInfo.Fields[i];
+ var fieldInfo = fields[i];
if (fieldInfo.IsStatic)
continue;
if (fieldInfo.NoArray && fieldInfo.Type.IsArray)
{
// Fixed-size array needs to unbox every item manually if not using managed array
- if (fieldInfo.Type.IsPod(buildData, structureInfo))
+ if (fieldInfo.Type.IsPod(buildData, apiType))
header.AppendFormat(" Platform::MemoryCopy(result.{0}, value.{0}, sizeof({2}) * {1});", fieldInfo.Name, fieldInfo.Type.ArraySize, fieldInfo.Type).AppendLine();
else
header.AppendFormat(" for (int32 i = 0; i < {0}; i++)", fieldInfo.Type.ArraySize).AppendLine().AppendFormat(" result.{0}[i] = value.{0}[i];", fieldInfo.Name).AppendLine();
@@ -1971,17 +2086,17 @@ namespace Flax.Build.Bindings
// Generate converting function managed -> native
header.AppendLine();
- header.AppendFormat("{1} ToNative(const {0}Managed& value)", structureInfo.Name, fullName).AppendLine();
+ header.AppendFormat("{1} ToNative(const {0}Managed& value)", apiType.Name, fullName).AppendLine();
header.Append('{').AppendLine();
header.AppendFormat(" {0} result;", fullName).AppendLine();
- for (var i = 0; i < structureInfo.Fields.Count; i++)
+ for (var i = 0; i < fields.Count; i++)
{
- var fieldInfo = structureInfo.Fields[i];
+ var fieldInfo = fields[i];
if (fieldInfo.IsStatic)
continue;
CppNonPodTypesConvertingGeneration = true;
- var wrapper = GenerateCppWrapperManagedToNative(buildData, fieldInfo.Type, structureInfo, out _, null, out _);
+ var wrapper = GenerateCppWrapperManagedToNative(buildData, fieldInfo.Type, apiType, out _, null, out _);
CppNonPodTypesConvertingGeneration = false;
if (fieldInfo.Type.IsArray)
@@ -1989,7 +2104,7 @@ namespace Flax.Build.Bindings
// Fixed-size array needs to unbox every item manually
if (fieldInfo.NoArray)
{
- if (fieldInfo.Type.IsPod(buildData, structureInfo))
+ if (fieldInfo.Type.IsPod(buildData, apiType))
header.AppendFormat(" Platform::MemoryCopy(result.{0}, value.{0}, sizeof({2}) * {1});", fieldInfo.Name, fieldInfo.Type.ArraySize, fieldInfo.Type).AppendLine();
else
header.AppendFormat(" for (int32 i = 0; i < {0}; i++)", fieldInfo.Type.ArraySize).AppendLine().AppendFormat(" result.{0}[i] = value.{0}[i];", fieldInfo.Name).AppendLine();
@@ -2013,6 +2128,110 @@ namespace Flax.Build.Bindings
header.Append('}').AppendLine();
header.AppendLine("}");
}
+ else if (classInfo != null)
+ {
+ // Generate MConverter
+ header.Append("template<>").AppendLine();
+ header.AppendFormat("struct MConverter<{0}>", fullName).AppendLine();
+ header.Append('{').AppendLine();
+
+ header.AppendFormat(" static MonoObject* Box(const {0}& data, MonoClass* klass)", fullName).AppendLine();
+ header.Append(" {").AppendLine();
+ header.AppendFormat(" auto obj = ({0}Managed*)mono_object_new(mono_domain_get(), klass);", fullName).AppendLine();
+ for (var i = 0; i < fields.Count; i++)
+ {
+ var fieldInfo = fields[i];
+ if (fieldInfo.IsStatic)
+ continue;
+
+ if (fieldInfo.NoArray && fieldInfo.Type.IsArray)
+ {
+ // Fixed-size array needs to unbox every item manually if not using managed array
+ if (fieldInfo.Type.IsPod(buildData, apiType))
+ header.AppendFormat(" Platform::MemoryCopy(obj->{0}, data.{0}, sizeof({2}) * {1});", fieldInfo.Name, fieldInfo.Type.ArraySize, fieldInfo.Type).AppendLine();
+ else
+ header.AppendFormat(" for (int32 i = 0; i < {0}; i++)", fieldInfo.Type.ArraySize).AppendLine().AppendFormat(" obj->{0}[i] = data.{0}[i];", fieldInfo.Name).AppendLine();
+ continue;
+ }
+
+ var wrapper = CppParamsWrappersCache[i];
+ header.AppendFormat(" MONO_OBJECT_SETREF(obj, {0}, ", fieldInfo.Name);
+ if (string.IsNullOrEmpty(wrapper))
+ header.Append("data." + fieldInfo.Name);
+ else
+ header.AppendFormat(wrapper, "data." + fieldInfo.Name);
+ header.Append(')').Append(';').AppendLine();
+ }
+ header.Append(" return (MonoObject*)obj;").AppendLine();
+ header.Append(" }").AppendLine();
+
+ header.AppendFormat(" static MonoObject* Box(const {0}& data)", fullName).AppendLine();
+ header.Append(" {").AppendLine();
+ header.AppendFormat(" MonoClass* klass = {0}::TypeInitializer.GetType().ManagedClass->GetNative();", fullName).AppendLine();
+ header.Append(" return Box(data, klass);").AppendLine();
+ header.Append(" }").AppendLine();
+
+ header.AppendFormat(" static void Unbox({0}& result, MonoObject* data)", fullName).AppendLine();
+ header.Append(" {").AppendLine();
+ header.AppendFormat(" auto obj = ({0}Managed*)data;", fullName).AppendLine();
+ for (var i = 0; i < fields.Count; i++)
+ {
+ var fieldInfo = fields[i];
+ if (fieldInfo.IsStatic)
+ continue;
+
+ CppNonPodTypesConvertingGeneration = true;
+ var wrapper = GenerateCppWrapperManagedToNative(buildData, fieldInfo.Type, apiType, out _, null, out _);
+ CppNonPodTypesConvertingGeneration = false;
+
+ if (fieldInfo.Type.IsArray)
+ {
+ // Fixed-size array needs to unbox every item manually
+ if (fieldInfo.NoArray)
+ {
+ if (fieldInfo.Type.IsPod(buildData, apiType))
+ header.AppendFormat(" Platform::MemoryCopy(result.{0}, obj->{0}, sizeof({2}) * {1});", fieldInfo.Name, fieldInfo.Type.ArraySize, fieldInfo.Type).AppendLine();
+ else
+ header.AppendFormat(" for (int32 i = 0; i < {0}; i++)", fieldInfo.Type.ArraySize).AppendLine().AppendFormat(" result.{0}[i] = obj->{0}[i];", fieldInfo.Name).AppendLine();
+ }
+ else
+ {
+ wrapper = string.Format(wrapper.Remove(wrapper.Length - 6), string.Format("obj->{0}", fieldInfo.Name));
+ header.AppendFormat(" auto tmp{0} = {1};", fieldInfo.Name, wrapper).AppendLine();
+ header.AppendFormat(" for (int32 i = 0; i < {0} && i < tmp{1}.Count(); i++)", fieldInfo.Type.ArraySize, fieldInfo.Name).AppendLine();
+ header.AppendFormat(" result.{0}[i] = tmp{0}[i];", fieldInfo.Name).AppendLine();
+ }
+ continue;
+ }
+
+ if (string.IsNullOrEmpty(wrapper))
+ header.AppendFormat(" result.{0} = obj->{0};", fieldInfo.Name).AppendLine();
+ else
+ header.AppendFormat(" result.{0} = {1};", fieldInfo.Name, string.Format(wrapper, string.Format("obj->{0}", fieldInfo.Name))).AppendLine();
+ }
+ header.Append(" }").AppendLine();
+
+ header.AppendFormat(" static {0} Unbox(MonoObject* data)", fullName).AppendLine();
+ header.Append(" {").AppendLine();
+ header.AppendFormat(" {0} result;", fullName).AppendLine();
+ header.Append(" Unbox(result, data);").AppendLine();
+ header.Append(" return result;").AppendLine();
+ header.Append(" }").AppendLine();
+
+ header.AppendFormat(" void ToManagedArray(MonoArray* result, const Span<{0}>& data)", fullName).AppendLine();
+ header.Append(" {").AppendLine();
+ header.Append(" for (int32 i = 0; i < data.Length(); i++)").AppendLine();
+ header.Append(" mono_array_setref(result, i, Box(data[i]));").AppendLine();
+ header.Append(" }").AppendLine();
+
+ header.AppendFormat(" void ToNativeArray(Array<{0}>& result, MonoArray* data, int32 length)", fullName).AppendLine();
+ header.Append(" {").AppendLine();
+ header.Append(" for (int32 i = 0; i < length; i++)").AppendLine();
+ header.AppendFormat(" Unbox(result[i], (MonoObject*)mono_array_addr_with_size(data, sizeof({0}Managed), length));", fullName).AppendLine();
+ header.Append(" }").AppendLine();
+
+ header.Append('}').Append(';').AppendLine();
+ }
}
contents.Insert(headerPos, header.ToString());
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs
index 7714e6abd..c7ef8ff59 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs
@@ -213,7 +213,9 @@ namespace Flax.Build.Bindings
type.GenericArgs = new List();
do
{
- type.GenericArgs.Add(ParseType(ref context));
+ var argType = ParseType(ref context);
+ if (argType.Type != null)
+ type.GenericArgs.Add(argType);
token = context.Tokenizer.NextToken();
} while (token.Type != TokenType.RightAngleBracket);
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.cs
index 742aa6f63..f8d26314f 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.cs
@@ -623,9 +623,6 @@ namespace Flax.Build.Bindings
if (!fieldInfo.IsReadOnly)
{
- if (fieldInfo.Type.IsArray)
- throw new NotImplementedException("Use ReadOnly on field. TODO: add support for setter for fixed-array fields.");
-
fieldInfo.Setter = new FunctionInfo
{
Name = "Set" + fieldInfo.Name,
diff --git a/Source/Tools/Flax.Build/Build/Builder.Projects.cs b/Source/Tools/Flax.Build/Build/Builder.Projects.cs
index ba3c4c7bd..c91fd9f9c 100644
--- a/Source/Tools/Flax.Build/Build/Builder.Projects.cs
+++ b/Source/Tools/Flax.Build/Build/Builder.Projects.cs
@@ -187,6 +187,8 @@ namespace Flax.Build
// Setup
var rules = GenerateRulesAssembly();
var rootProject = Globals.Project;
+ if (rootProject == null)
+ throw new Exception("Missing project.");
var projectFiles = rootProject.GetAllProjects();
var targetGroups = rules.Targets.GroupBy(x => x.ProjectName);
var workspaceRoot = rootProject.ProjectFolderPath;
diff --git a/Source/Tools/Flax.Build/Build/DepsModule.cs b/Source/Tools/Flax.Build/Build/DepsModule.cs
index 96e921015..423485b1c 100644
--- a/Source/Tools/Flax.Build/Build/DepsModule.cs
+++ b/Source/Tools/Flax.Build/Build/DepsModule.cs
@@ -31,6 +31,7 @@ namespace Flax.Build
case TargetPlatform.Linux:
case TargetPlatform.PS4:
case TargetPlatform.Android:
+ case TargetPlatform.Switch:
options.OutputFiles.Add(Path.Combine(path, string.Format("lib{0}.a", name)));
break;
default: throw new InvalidPlatformException(options.Platform.Target);
diff --git a/Source/Tools/Flax.Build/Build/Module.cs b/Source/Tools/Flax.Build/Build/Module.cs
index c623de92d..a5c1dddc5 100644
--- a/Source/Tools/Flax.Build/Build/Module.cs
+++ b/Source/Tools/Flax.Build/Build/Module.cs
@@ -90,6 +90,7 @@ namespace Flax.Build
case TargetPlatform.PS4: return "PLATFORM_PS4";
case TargetPlatform.XboxScarlett: return "PLATFORM_XBOX_SCARLETT";
case TargetPlatform.Android: return "PLATFORM_ANDROID";
+ case TargetPlatform.Switch: return "PLATFORM_SWITCH";
default: throw new InvalidPlatformException(platform);
}
}
diff --git a/Source/Tools/Flax.Build/Build/Platform.cs b/Source/Tools/Flax.Build/Build/Platform.cs
index 79c30f969..96f187a37 100644
--- a/Source/Tools/Flax.Build/Build/Platform.cs
+++ b/Source/Tools/Flax.Build/Build/Platform.cs
@@ -230,6 +230,7 @@ namespace Flax.Build
case TargetPlatform.Linux: return targetArchitecture == TargetArchitecture.x64;
case TargetPlatform.PS4: return targetArchitecture == TargetArchitecture.x64;
case TargetPlatform.Android: return targetArchitecture == TargetArchitecture.ARM64;
+ case TargetPlatform.Switch: return targetArchitecture == TargetArchitecture.ARM64;
default: return false;
}
}
diff --git a/Source/Tools/Flax.Build/Build/TargetPlatform.cs b/Source/Tools/Flax.Build/Build/TargetPlatform.cs
index 27e7fe02a..8efb50cea 100644
--- a/Source/Tools/Flax.Build/Build/TargetPlatform.cs
+++ b/Source/Tools/Flax.Build/Build/TargetPlatform.cs
@@ -41,6 +41,11 @@ namespace Flax.Build
/// Running on Android.
///
Android = 7,
+
+ ///
+ /// Running on Switch.
+ ///
+ Switch = 8,
}
///
diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/NewtonsoftJson.cs b/Source/Tools/Flax.Build/Deps/Dependencies/NewtonsoftJson.cs
index de9b115ad..5d3683ef3 100644
--- a/Source/Tools/Flax.Build/Deps/Dependencies/NewtonsoftJson.cs
+++ b/Source/Tools/Flax.Build/Deps/Dependencies/NewtonsoftJson.cs
@@ -27,6 +27,7 @@ namespace Flax.Deps.Dependencies
TargetPlatform.XboxOne,
TargetPlatform.XboxScarlett,
TargetPlatform.PS4,
+ TargetPlatform.Switch,
};
default: return new TargetPlatform[0];
}
@@ -81,6 +82,7 @@ namespace Flax.Deps.Dependencies
case TargetPlatform.XboxOne:
case TargetPlatform.PS4:
case TargetPlatform.XboxScarlett:
+ case TargetPlatform.Switch:
{
var file = "Newtonsoft.Json.dll";
Utilities.FileCopy(Path.Combine(binFolder, file), Path.Combine(options.PlatformsFolder, platform.ToString(), "Binaries", file));
diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/PhysX.cs b/Source/Tools/Flax.Build/Deps/Dependencies/PhysX.cs
index 32a408828..ddafc8cf4 100644
--- a/Source/Tools/Flax.Build/Deps/Dependencies/PhysX.cs
+++ b/Source/Tools/Flax.Build/Deps/Dependencies/PhysX.cs
@@ -33,6 +33,7 @@ namespace Flax.Deps.Dependencies
TargetPlatform.PS4,
TargetPlatform.XboxScarlett,
TargetPlatform.Android,
+ TargetPlatform.Switch,
};
case TargetPlatform.Linux:
return new[]
@@ -166,6 +167,12 @@ namespace Flax.Deps.Dependencies
binariesPrefix = "lib";
suppressBitsPostfix = true;
break;
+ case TargetPlatform.Switch:
+ binariesSubDir = "switch64";
+ buildPlatform = "NX64";
+ suppressBitsPostfix = true;
+ binariesPrefix = "lib";
+ break;
default: throw new InvalidPlatformException(targetPlatform);
}
@@ -354,6 +361,12 @@ namespace Flax.Deps.Dependencies
Build(options, "android", platform, TargetArchitecture.ARM64);
break;
}
+ case TargetPlatform.Switch:
+ {
+ Utilities.DirectoryCopy(Path.Combine(options.PlatformsFolder, "Switch", "Data", "PhysX"), root, true, true);
+ Build(options, "switch64", platform, TargetArchitecture.ARM64);
+ break;
+ }
}
}
diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/freetype.cs b/Source/Tools/Flax.Build/Deps/Dependencies/freetype.cs
index 2cd229e40..3790c3f49 100644
--- a/Source/Tools/Flax.Build/Deps/Dependencies/freetype.cs
+++ b/Source/Tools/Flax.Build/Deps/Dependencies/freetype.cs
@@ -31,6 +31,7 @@ namespace Flax.Deps.Dependencies
TargetPlatform.PS4,
TargetPlatform.XboxScarlett,
TargetPlatform.Android,
+ TargetPlatform.Switch,
};
case TargetPlatform.Linux:
return new[]
@@ -209,6 +210,17 @@ namespace Flax.Deps.Dependencies
Utilities.FileCopy(Path.Combine(buildDir, libraryFileName), Path.Combine(depsFolder, libraryFileName));
break;
}
+ case TargetPlatform.Switch:
+ {
+ // Build for Switch
+ var buildDir = Path.Combine(root, "build");
+ SetupDirectory(buildDir, true);
+ RunCmake(buildDir, platform, TargetArchitecture.ARM64, ".. -DCMAKE_BUILD_TYPE=Release");
+ Utilities.Run("cmake", "--build .", null, buildDir, Utilities.RunOptions.None);
+ var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.ARM64);
+ Utilities.FileCopy(Path.Combine(buildDir, libraryFileName), Path.Combine(depsFolder, libraryFileName));
+ break;
+ }
}
}
diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/ogg.cs b/Source/Tools/Flax.Build/Deps/Dependencies/ogg.cs
index 899fefd88..8bd8e4d95 100644
--- a/Source/Tools/Flax.Build/Deps/Dependencies/ogg.cs
+++ b/Source/Tools/Flax.Build/Deps/Dependencies/ogg.cs
@@ -30,6 +30,7 @@ namespace Flax.Deps.Dependencies
TargetPlatform.PS4,
TargetPlatform.XboxScarlett,
TargetPlatform.Android,
+ TargetPlatform.Switch,
};
case TargetPlatform.Linux:
return new[]
@@ -180,6 +181,20 @@ namespace Flax.Deps.Dependencies
Utilities.FileCopy(Path.Combine(buildDir, libraryFileName), Path.Combine(depsFolder, libraryFileName));
break;
}
+ case TargetPlatform.Switch:
+ {
+ // Get the build data files
+ Utilities.DirectoryCopy(Path.Combine(options.PlatformsFolder, "Switch", "Data", "ogg"), root, true, true);
+
+ // Build for Switch
+ var buildDir = Path.Combine(root, "build");
+ SetupDirectory(buildDir, true);
+ RunCmake(buildDir, platform, TargetArchitecture.ARM64, ".. -DCMAKE_BUILD_TYPE=Release");
+ Utilities.Run("cmake", "--build .", null, buildDir, Utilities.RunOptions.None);
+ var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.ARM64);
+ Utilities.FileCopy(Path.Combine(buildDir, libraryFileName), Path.Combine(depsFolder, libraryFileName));
+ break;
+ }
}
}
diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/vorbis.cs b/Source/Tools/Flax.Build/Deps/Dependencies/vorbis.cs
index 714a14630..8146c4dc0 100644
--- a/Source/Tools/Flax.Build/Deps/Dependencies/vorbis.cs
+++ b/Source/Tools/Flax.Build/Deps/Dependencies/vorbis.cs
@@ -31,6 +31,7 @@ namespace Flax.Deps.Dependencies
TargetPlatform.PS4,
TargetPlatform.XboxScarlett,
TargetPlatform.Android,
+ TargetPlatform.Switch,
};
case TargetPlatform.Linux:
return new[]
@@ -291,7 +292,8 @@ namespace Flax.Deps.Dependencies
// Get the source
CloneGitRepoFast(root, "https://github.com/xiph/vorbis.git");
- CloneGitRepoFast(oggRoot, "https://github.com/xiph/ogg.git");
+ CloneGitRepo(oggRoot, "https://github.com/xiph/ogg.git");
+ GitCheckout(oggRoot, "master", "4380566a44b8d5e85ad511c9c17eb04197863ec5");
// Build for Android
SetupDirectory(oggBuildDir, true);
@@ -305,6 +307,33 @@ namespace Flax.Deps.Dependencies
Utilities.FileCopy(Path.Combine(buildDir, file.SrcFolder, file.Filename), Path.Combine(depsFolder, file.Filename));
break;
}
+ case TargetPlatform.Switch:
+ {
+ var oggRoot = Path.Combine(root, "ogg");
+ var oggBuildDir = Path.Combine(oggRoot, "build");
+ var buildDir = Path.Combine(root, "build");
+
+ // Get the source
+ CloneGitRepo(root, "https://github.com/xiph/vorbis.git");
+ GitCheckout(root, "master", "98eddc72d36e3421519d54b101c09b57e4d4d10d");
+ CloneGitRepo(oggRoot, "https://github.com/xiph/ogg.git");
+ GitCheckout(oggRoot, "master", "4380566a44b8d5e85ad511c9c17eb04197863ec5");
+ Utilities.DirectoryCopy(Path.Combine(options.PlatformsFolder, "Switch", "Data", "ogg"), oggRoot, true, true);
+ Utilities.DirectoryCopy(Path.Combine(options.PlatformsFolder, "Switch", "Data", "vorbis"), buildDir, true, true);
+
+ // Build for Switch
+ SetupDirectory(oggBuildDir, true);
+ RunCmake(oggBuildDir, platform, TargetArchitecture.ARM64, ".. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=\"../install\"");
+ Utilities.Run("cmake", "--build . --target install", null, oggBuildDir, Utilities.RunOptions.None);
+ Utilities.FileCopy(Path.Combine(options.PlatformsFolder, "Switch", "Data", "ogg", "include", "ogg", "config_types.h"), Path.Combine(oggRoot, "install", "include", "ogg", "config_types.h"));
+ SetupDirectory(buildDir, true);
+ RunCmake(buildDir, platform, TargetArchitecture.ARM64, string.Format(".. -DCMAKE_BUILD_TYPE=Release -DOGG_INCLUDE_DIR=\"{0}/install/include\" -DOGG_LIBRARY=\"{0}/install/lib\"", oggRoot));
+ Utilities.Run("cmake", "--build .", null, buildDir, Utilities.RunOptions.None);
+ var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.ARM64);
+ foreach (var file in binariesToCopyUnix)
+ Utilities.FileCopy(Path.Combine(buildDir, file.SrcFolder, file.Filename), Path.Combine(depsFolder, file.Filename));
+ break;
+ }
}
}
diff --git a/Source/Tools/Flax.Build/Deps/Dependency.cs b/Source/Tools/Flax.Build/Deps/Dependency.cs
index 6b105d2e8..c19687c2a 100644
--- a/Source/Tools/Flax.Build/Deps/Dependency.cs
+++ b/Source/Tools/Flax.Build/Deps/Dependency.cs
@@ -1,5 +1,6 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+using System;
using System.Collections.Generic;
using System.IO;
using Flax.Build;
@@ -241,6 +242,11 @@ namespace Flax.Deps
cmdLine = "CMakeLists.txt";
break;
}
+ case TargetPlatform.Switch:
+ {
+ cmdLine = string.Format("-DCMAKE_TOOLCHAIN_FILE=\"{1}\\Source\\Platforms\\Switch\\Data\\Switch.cmake\" -G \"NMake Makefiles\" -DCMAKE_MAKE_PROGRAM=\"{0}..\\..\\VC\\bin\\nmake.exe\"", Environment.GetEnvironmentVariable("VS140COMNTOOLS"), Globals.EngineRoot);
+ break;
+ }
case TargetPlatform.Android:
{
var ndk = AndroidNdk.Instance.RootPath;
diff --git a/Source/Tools/Flax.Build/Deps/DepsBuilder.cs b/Source/Tools/Flax.Build/Deps/DepsBuilder.cs
index 6d6eaf5b3..0b254195d 100644
--- a/Source/Tools/Flax.Build/Deps/DepsBuilder.cs
+++ b/Source/Tools/Flax.Build/Deps/DepsBuilder.cs
@@ -85,7 +85,8 @@ namespace Flax.Deps
continue;
}
- Dependency.SetupDirectory(options.IntermediateFolder, true);
+ var forceEmpty = Configuration.ReBuildDeps;
+ Dependency.SetupDirectory(options.IntermediateFolder, forceEmpty);
dependency.Build(options);
}
diff --git a/Source/Tools/Flax.Build/Flax.Build.csproj b/Source/Tools/Flax.Build/Flax.Build.csproj
index 236348032..0de0bd0a0 100644
--- a/Source/Tools/Flax.Build/Flax.Build.csproj
+++ b/Source/Tools/Flax.Build/Flax.Build.csproj
@@ -143,6 +143,7 @@
+
diff --git a/Source/Tools/Flax.Build/Globals.cs b/Source/Tools/Flax.Build/Globals.cs
index d33251a94..27bb78ac3 100644
--- a/Source/Tools/Flax.Build/Globals.cs
+++ b/Source/Tools/Flax.Build/Globals.cs
@@ -34,6 +34,7 @@ namespace Flax.Build
TargetPlatform.PS4,
TargetPlatform.XboxScarlett,
TargetPlatform.Android,
+ TargetPlatform.Switch,
};
///
diff --git a/Source/Tools/Flax.Build/Platforms/Windows/WindowsPlatform.cs b/Source/Tools/Flax.Build/Platforms/Windows/WindowsPlatform.cs
index 145eaaf02..3e34e1eb3 100644
--- a/Source/Tools/Flax.Build/Platforms/Windows/WindowsPlatform.cs
+++ b/Source/Tools/Flax.Build/Platforms/Windows/WindowsPlatform.cs
@@ -61,6 +61,7 @@ namespace Flax.Build.Platforms
case TargetPlatform.PS4: return Sdk.HasValid("PS4Sdk");
case TargetPlatform.XboxScarlett: return GetSDKs().ContainsKey(WindowsPlatformSDK.v10_0_19041_0) && Sdk.HasValid("GDK");
case TargetPlatform.Android: return AndroidSdk.Instance.IsValid && AndroidNdk.Instance.IsValid;
+ case TargetPlatform.Switch: return Sdk.HasValid("SwitchSdk");
default: return false;
}
}
diff --git a/Source/flax.natvis b/Source/flax.natvis
index 774badad3..3337ccdd5 100644
--- a/Source/flax.natvis
+++ b/Source/flax.natvis
@@ -100,7 +100,7 @@
Empty
Invalid
- {_data,su}
+ {_data,[_length]su}
_data
- _length
@@ -130,7 +130,7 @@
Empty
Invalid
- {_data}
+ {_data,[_length]}
_data
- _length
@@ -143,7 +143,7 @@
- {_data._allocation._data,su}
+ {_data._allocation._data,[_data._count]su}
- _data._allocation._data
- _data._count