Merge remote-tracking branch 'origin/master' into gi
# Conflicts: # Flax.flaxproj # Source/Engine/Core/Math/Vector3.h # Source/Engine/Graphics/Textures/GPUTexture.cpp # Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp # Source/Engine/Terrain/Terrain.cpp # Source/Engine/Tools/ModelTool/ModelTool.Build.cs # Source/FlaxEngine.Gen.cs # Source/FlaxEngine.Gen.h
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Asset.h"
|
||||
#include "Content.h"
|
||||
#include "SoftAssetReference.h"
|
||||
#include "Cache/AssetsCache.h"
|
||||
#include "Loading/ContentLoadingManager.h"
|
||||
#include "Loading/Tasks/LoadAssetTask.h"
|
||||
@@ -102,6 +103,65 @@ void WeakAssetReferenceBase::OnUnloaded(Asset* asset)
|
||||
_asset = nullptr;
|
||||
}
|
||||
|
||||
String SoftAssetReferenceBase::ToString() const
|
||||
{
|
||||
return _asset ? _asset->ToString() : (_id.IsValid() ? _id.ToString() : TEXT("<null>"));
|
||||
}
|
||||
|
||||
void SoftAssetReferenceBase::OnSet(Asset* asset)
|
||||
{
|
||||
if (_asset == asset)
|
||||
return;
|
||||
if (_asset)
|
||||
{
|
||||
_asset->OnUnloaded.Unbind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
|
||||
_asset->RemoveReference();
|
||||
}
|
||||
_asset = asset;
|
||||
_id = asset ? asset->GetID() : Guid::Empty;
|
||||
if (asset)
|
||||
{
|
||||
asset->AddReference();
|
||||
asset->OnUnloaded.Bind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
|
||||
}
|
||||
Changed();
|
||||
}
|
||||
|
||||
void SoftAssetReferenceBase::OnSet(const Guid& id)
|
||||
{
|
||||
if (_id == id)
|
||||
return;
|
||||
if (_asset)
|
||||
{
|
||||
_asset->OnUnloaded.Unbind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
|
||||
_asset->RemoveReference();
|
||||
}
|
||||
_asset = nullptr;
|
||||
_id = id;
|
||||
Changed();
|
||||
}
|
||||
|
||||
void SoftAssetReferenceBase::OnResolve(const ScriptingTypeHandle& type)
|
||||
{
|
||||
ASSERT(!_asset);
|
||||
_asset = ::LoadAsset(_id, type);
|
||||
if (_asset)
|
||||
{
|
||||
_asset->OnUnloaded.Bind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
|
||||
_asset->AddReference();
|
||||
}
|
||||
}
|
||||
|
||||
void SoftAssetReferenceBase::OnUnloaded(Asset* asset)
|
||||
{
|
||||
ASSERT(_asset == asset);
|
||||
_asset->RemoveReference();
|
||||
_asset->OnUnloaded.Unbind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
|
||||
_asset = nullptr;
|
||||
_id = Guid::Empty;
|
||||
Changed();
|
||||
}
|
||||
|
||||
Asset::Asset(const SpawnParams& params, const AssetInfo* info)
|
||||
: ManagedScriptingObject(params)
|
||||
, _refCount(0)
|
||||
|
||||
234
Source/Engine/Content/SoftAssetReference.h
Normal file
234
Source/Engine/Content/SoftAssetReference.h
Normal file
@@ -0,0 +1,234 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Content/Asset.h"
|
||||
|
||||
/// <summary>
|
||||
/// The asset soft reference. Asset gets referenced (loaded) on actual use (ID reference is resolving it).
|
||||
/// </summary>
|
||||
class FLAXENGINE_API SoftAssetReferenceBase
|
||||
{
|
||||
protected:
|
||||
Asset* _asset = nullptr;
|
||||
Guid _id = Guid::Empty;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Action fired when field gets changed (link a new asset or change to the another value).
|
||||
/// </summary>
|
||||
Delegate<> Changed;
|
||||
|
||||
public:
|
||||
NON_COPYABLE(SoftAssetReferenceBase);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SoftAssetReferenceBase"/> class.
|
||||
/// </summary>
|
||||
SoftAssetReferenceBase() = default;
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="SoftAssetReferenceBase"/> class.
|
||||
/// </summary>
|
||||
~SoftAssetReferenceBase()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets the asset ID or Guid::Empty if not set.
|
||||
/// </summary>
|
||||
FORCE_INLINE Guid GetID() const
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the asset property value as string.
|
||||
/// </summary>
|
||||
String ToString() const;
|
||||
|
||||
protected:
|
||||
void OnSet(Asset* asset);
|
||||
void OnSet(const Guid& id);
|
||||
void OnResolve(const ScriptingTypeHandle& type);
|
||||
void OnUnloaded(Asset* asset);
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The asset soft reference. Asset gets referenced (loaded) on actual use (ID reference is resolving it).
|
||||
/// </summary>
|
||||
template<typename T>
|
||||
API_CLASS(InBuild) class SoftAssetReference : public SoftAssetReferenceBase
|
||||
{
|
||||
public:
|
||||
typedef T AssetType;
|
||||
typedef SoftAssetReference<T> Type;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SoftAssetReference"/> class.
|
||||
/// </summary>
|
||||
SoftAssetReference()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SoftAssetReference"/> class.
|
||||
/// </summary>
|
||||
/// <param name="asset">The asset to set.</param>
|
||||
SoftAssetReference(T* asset)
|
||||
{
|
||||
OnSet(asset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SoftAssetReference"/> class.
|
||||
/// </summary>
|
||||
/// <param name="other">The other.</param>
|
||||
SoftAssetReference(const SoftAssetReference& other)
|
||||
{
|
||||
OnSet(other.Get());
|
||||
}
|
||||
|
||||
SoftAssetReference(SoftAssetReference&& other)
|
||||
{
|
||||
OnSet(other.Get());
|
||||
other.OnSet(nullptr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="SoftAssetReference"/> class.
|
||||
/// </summary>
|
||||
~SoftAssetReference()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
FORCE_INLINE bool operator==(T* other)
|
||||
{
|
||||
return Get() == other;
|
||||
}
|
||||
FORCE_INLINE bool operator==(const SoftAssetReference& other)
|
||||
{
|
||||
return GetID() == other.GetID();
|
||||
}
|
||||
FORCE_INLINE bool operator!=(T* other)
|
||||
{
|
||||
return Get() != other;
|
||||
}
|
||||
FORCE_INLINE bool operator!=(const SoftAssetReference& other)
|
||||
{
|
||||
return GetID() != other.GetID();
|
||||
}
|
||||
SoftAssetReference& operator=(const SoftAssetReference& other)
|
||||
{
|
||||
if (this != &other)
|
||||
OnSet(other.GetID());
|
||||
return *this;
|
||||
}
|
||||
SoftAssetReference& operator=(SoftAssetReference&& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
OnSet(other.GetID());
|
||||
other.OnSet(nullptr);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
FORCE_INLINE SoftAssetReference& operator=(const T& other)
|
||||
{
|
||||
OnSet(&other);
|
||||
return *this;
|
||||
}
|
||||
FORCE_INLINE SoftAssetReference& operator=(T* other)
|
||||
{
|
||||
OnSet(other);
|
||||
return *this;
|
||||
}
|
||||
FORCE_INLINE SoftAssetReference& operator=(const Guid& id)
|
||||
{
|
||||
OnSet(id);
|
||||
return *this;
|
||||
}
|
||||
FORCE_INLINE operator T*() const
|
||||
{
|
||||
return (T*)Get();
|
||||
}
|
||||
FORCE_INLINE operator bool() const
|
||||
{
|
||||
return Get() != nullptr;
|
||||
}
|
||||
FORCE_INLINE T* operator->() const
|
||||
{
|
||||
return (T*)Get();
|
||||
}
|
||||
template<typename U>
|
||||
FORCE_INLINE U* As() const
|
||||
{
|
||||
return static_cast<U*>(Get());
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets the asset (or null if unassigned).
|
||||
/// </summary>
|
||||
T* Get() const
|
||||
{
|
||||
if (!_asset)
|
||||
const_cast<SoftAssetReference*>(this)->OnResolve(T::TypeInitializer);
|
||||
return (T*)_asset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets managed instance object (or null if no asset linked).
|
||||
/// </summary>
|
||||
MObject* GetManagedInstance() const
|
||||
{
|
||||
auto asset = Get();
|
||||
return asset ? asset->GetOrCreateManagedInstance() : nullptr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether asset is assigned and managed instance of the asset is alive.
|
||||
/// </summary>
|
||||
bool HasManagedInstance() const
|
||||
{
|
||||
auto asset = Get();
|
||||
return asset && asset->HasManagedInstance();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the managed instance object or creates it if missing or null if not assigned.
|
||||
/// </summary>
|
||||
MObject* GetOrCreateManagedInstance() const
|
||||
{
|
||||
auto asset = Get();
|
||||
return asset ? asset->GetOrCreateManagedInstance() : nullptr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the asset.
|
||||
/// </summary>
|
||||
/// <param name="id">The object ID. Uses Scripting to find the registered asset of the given ID.</param>
|
||||
FORCE_INLINE void Set(const Guid& id)
|
||||
{
|
||||
OnSet(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the asset.
|
||||
/// </summary>
|
||||
/// <param name="asset">The asset.</param>
|
||||
FORCE_INLINE void Set(T* asset)
|
||||
{
|
||||
OnSet(asset);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
uint32 GetHash(const SoftAssetReference<T>& key)
|
||||
{
|
||||
return GetHash(key.GetID());
|
||||
}
|
||||
@@ -75,8 +75,8 @@ ExportAssetResult AssetExporters::ExportModel(ExportAssetContext& context)
|
||||
|
||||
for (uint32 i = 0; i < vertices; i++)
|
||||
{
|
||||
auto v = vb1[i].TexCoord;
|
||||
output->WriteText(StringAnsi::Format("vt {0} {1}\n", Float16Compressor::Decompress(v.X), Float16Compressor::Decompress(v.Y)));
|
||||
auto v = vb1[i].TexCoord.ToVector2();
|
||||
output->WriteText(StringAnsi::Format("vt {0} {1}\n", v.X, v.Y));
|
||||
}
|
||||
|
||||
output->WriteChar('\n');
|
||||
@@ -180,8 +180,8 @@ ExportAssetResult AssetExporters::ExportSkinnedModel(ExportAssetContext& context
|
||||
|
||||
for (uint32 i = 0; i < vertices; i++)
|
||||
{
|
||||
auto v = vb0[i].TexCoord;
|
||||
output->WriteText(StringAnsi::Format("vt {0} {1}\n", Float16Compressor::Decompress(v.X), Float16Compressor::Decompress(v.Y)));
|
||||
auto v = vb0[i].TexCoord.ToVector2();
|
||||
output->WriteText(StringAnsi::Format("vt {0} {1}\n", v.X, v.Y));
|
||||
}
|
||||
|
||||
output->WriteChar('\n');
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
|
||||
#if COMPILE_WITH_ASSETS_IMPORTER
|
||||
|
||||
#if COMPILE_WITH_PHYSICS_COOKING
|
||||
#include "Engine/Physics/CollisionCooking.h"
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Creating collision data asset utility
|
||||
@@ -23,7 +25,6 @@ public:
|
||||
static CreateAssetResult Create(CreateAssetContext& context);
|
||||
|
||||
#if COMPILE_WITH_PHYSICS_COOKING
|
||||
|
||||
/// <summary>
|
||||
/// Cooks the mesh collision data and saves it to the asset using <see cref="CollisionData"/> format.
|
||||
/// </summary>
|
||||
@@ -31,7 +32,6 @@ public:
|
||||
/// <param name="arg">The input argument data.</param>
|
||||
/// <returns>True if failed, otherwise false. See log file to track errors better.</returns>
|
||||
static bool CookMeshCollision(const String& outputPath, CollisionCooking::Argument& arg);
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -639,7 +639,7 @@ public:
|
||||
{
|
||||
Vector3 output = input;
|
||||
const float length = input.Length();
|
||||
if (!Math::IsZero(length))
|
||||
if (Math::Abs(length) >= ZeroTolerance)
|
||||
{
|
||||
const float inv = 1.0f / length;
|
||||
output.X *= inv;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "Engine/Content/Assets/Shader.h"
|
||||
#include "Engine/Content/Assets/Material.h"
|
||||
#include "Engine/Content/Content.h"
|
||||
#include "Engine/Content/SoftAssetReference.h"
|
||||
#include "Engine/Platform/Windows/WindowsWindow.h"
|
||||
#include "Engine/Render2D/Render2D.h"
|
||||
#include "Engine/Engine/CommandLine.h"
|
||||
@@ -19,7 +20,6 @@
|
||||
#include "Engine/Profiler/Profiler.h"
|
||||
#include "Engine/Renderer/RenderList.h"
|
||||
#include "Engine/Core/Utilities.h"
|
||||
#include "Engine/Scripting/SoftObjectReference.h"
|
||||
|
||||
GPUPipelineState* GPUPipelineState::Spawn(const SpawnParams& params)
|
||||
{
|
||||
@@ -253,7 +253,7 @@ struct GPUDevice::PrivateData
|
||||
GPUPipelineState* PS_Clear = nullptr;
|
||||
GPUBuffer* FullscreenTriangleVB = nullptr;
|
||||
AssetReference<Material> DefaultMaterial;
|
||||
SoftObjectReference<Material> DefaultDeformableMaterial;
|
||||
SoftAssetReference<Material> DefaultDeformableMaterial;
|
||||
AssetReference<Texture> DefaultNormalMap;
|
||||
AssetReference<Texture> DefaultWhiteTexture;
|
||||
AssetReference<Texture> DefaultBlackTexture;
|
||||
|
||||
@@ -9,7 +9,7 @@ BlendShapesInstance::MeshInstance::MeshInstance()
|
||||
: IsUsed(false)
|
||||
, IsDirty(false)
|
||||
, DirtyMinVertexIndex(0)
|
||||
, DirtyMaxVertexIndex(MAX_uint32)
|
||||
, DirtyMaxVertexIndex(MAX_uint32 - 1)
|
||||
, VertexBuffer(0, sizeof(VB0SkinnedElementType), TEXT("Skinned Mesh Blend Shape"))
|
||||
{
|
||||
}
|
||||
@@ -112,7 +112,7 @@ void BlendShapesInstance::Update(SkinnedModel* skinnedModel)
|
||||
// Initialize the dynamic vertex buffer data (use the dirty range from the previous update to be cleared with initial data)
|
||||
instance.VertexBuffer.Data.Resize(vertexBuffer.Length());
|
||||
const uint32 dirtyVertexDataStart = instance.DirtyMinVertexIndex * sizeof(VB0SkinnedElementType);
|
||||
const uint32 dirtyVertexDataLength = Math::Min<uint32>(instance.DirtyMaxVertexIndex - instance.DirtyMinVertexIndex, vertexCount) * sizeof(VB0SkinnedElementType);
|
||||
const uint32 dirtyVertexDataLength = Math::Min<uint32>(instance.DirtyMaxVertexIndex - instance.DirtyMinVertexIndex + 1, vertexCount) * sizeof(VB0SkinnedElementType);
|
||||
Platform::MemoryCopy(instance.VertexBuffer.Data.Get() + dirtyVertexDataStart, vertexBuffer.Get() + dirtyVertexDataStart, dirtyVertexDataLength);
|
||||
|
||||
// Blend all blend shapes
|
||||
|
||||
@@ -589,6 +589,17 @@ void MeshData::Merge(MeshData& other)
|
||||
}
|
||||
}
|
||||
|
||||
bool MaterialSlotEntry::UsesProperties() const
|
||||
{
|
||||
return Diffuse.Color != Color::White ||
|
||||
Diffuse.TextureIndex != -1 ||
|
||||
Emissive.Color != Color::Transparent ||
|
||||
Emissive.TextureIndex != -1 ||
|
||||
!Math::IsOne(Opacity.Value) ||
|
||||
Opacity.TextureIndex != -1 ||
|
||||
Normals.TextureIndex != -1;
|
||||
}
|
||||
|
||||
void ModelData::CalculateLODsScreenSizes()
|
||||
{
|
||||
const float autoComputeLodPowerBase = 0.5f;
|
||||
|
||||
@@ -373,16 +373,7 @@ struct FLAXENGINE_API MaterialSlotEntry
|
||||
|
||||
bool TwoSided = false;
|
||||
|
||||
bool UsesProperties() const
|
||||
{
|
||||
return Diffuse.Color != Color::White ||
|
||||
Diffuse.TextureIndex != -1 ||
|
||||
Emissive.Color != Color::Transparent ||
|
||||
Emissive.TextureIndex != -1 ||
|
||||
!Math::IsOne(Opacity.Value) ||
|
||||
Opacity.TextureIndex != -1 ||
|
||||
Normals.TextureIndex != -1;
|
||||
}
|
||||
bool UsesProperties() const;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "PixelFormatExtensions.h"
|
||||
#include "Engine/Core/Collections/Dictionary.h"
|
||||
#include "Engine/Core/Math/Math.h"
|
||||
|
||||
// ReSharper disable CppClangTidyClangDiagnosticSwitchEnum
|
||||
|
||||
@@ -1047,7 +1047,7 @@ void GPUContextVulkan::BindIB(GPUBuffer* indexBuffer)
|
||||
void GPUContextVulkan::BindSampler(int32 slot, GPUSampler* sampler)
|
||||
{
|
||||
ASSERT(slot >= GPU_STATIC_SAMPLERS_COUNT && slot < GPU_MAX_SAMPLER_BINDED);
|
||||
const auto handle = sampler ? ((GPUSamplerVulkan*)sampler)->Sampler : nullptr;
|
||||
const auto handle = sampler ? ((GPUSamplerVulkan*)sampler)->Sampler : VK_NULL_HANDLE;
|
||||
_samplerHandles[slot] = handle;
|
||||
}
|
||||
|
||||
|
||||
@@ -366,7 +366,7 @@ void GPUDeviceVulkan::GetInstanceLayersAndExtensions(Array<const char*>& outInst
|
||||
}
|
||||
|
||||
#if VK_EXT_debug_utils
|
||||
if (!vkTrace && outDebugUtils && FindLayerExtension(globalLayerExtensions, VK_EXT_DEBUG_UTILS_EXTENSION_NAME))
|
||||
if (!vkTrace && FindLayerExtension(globalLayerExtensions, VK_EXT_DEBUG_UTILS_EXTENSION_NAME))
|
||||
{
|
||||
outInstanceExtensions.Add(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
@@ -185,6 +185,8 @@ bool GPUSwapChainVulkan::CreateSwapChain(int32 width, int32 height)
|
||||
// Flush removed resources
|
||||
_device->DeferredDeletionQueue.ReleaseResources(true);
|
||||
}
|
||||
ASSERT(_surface == VK_NULL_HANDLE);
|
||||
ASSERT_LOW_LAYER(_backBuffers.Count() == 0);
|
||||
|
||||
// Create platform-dependent surface
|
||||
VulkanPlatform::CreateSurface(windowHandle, GPUDeviceVulkan::Instance, &_surface);
|
||||
@@ -205,7 +207,7 @@ bool GPUSwapChainVulkan::CreateSwapChain(int32 width, int32 height)
|
||||
VALIDATE_VULKAN_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, _surface, &surfaceFormatsCount, nullptr));
|
||||
ASSERT(surfaceFormatsCount > 0);
|
||||
|
||||
Array<VkSurfaceFormatKHR> surfaceFormats;
|
||||
Array<VkSurfaceFormatKHR, InlinedAllocation<16>> surfaceFormats;
|
||||
surfaceFormats.AddZeroed(surfaceFormatsCount);
|
||||
VALIDATE_VULKAN_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, _surface, &surfaceFormatsCount, surfaceFormats.Get()));
|
||||
|
||||
@@ -414,8 +416,8 @@ bool GPUSwapChainVulkan::CreateSwapChain(int32 width, int32 height)
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate memory usage
|
||||
_memoryUsage = RenderTools::CalculateTextureMemoryUsage(_format, _width, _height, 1) * _backBuffers.Count();
|
||||
// Estimate memory usage
|
||||
_memoryUsage = 1024 + RenderTools::CalculateTextureMemoryUsage(_format, _width, _height, 1) * _backBuffers.Count();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -270,6 +270,11 @@ bool GPUTextureVulkan::OnInit()
|
||||
imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
if (useUAV)
|
||||
imageInfo.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
|
||||
#if PLATFORM_MAC
|
||||
// MoltenVK: VK_ERROR_FEATURE_NOT_PRESENT: vkCreateImageView(): 2D views on 3D images can only be used as color attachments.
|
||||
if (IsVolume() && _desc.HasPerSliceViews())
|
||||
imageInfo.usage &= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
#endif
|
||||
imageInfo.tiling = optimalTiling ? VK_IMAGE_TILING_OPTIMAL : VK_IMAGE_TILING_LINEAR;
|
||||
imageInfo.samples = (VkSampleCountFlagBits)MultiSampleLevel();
|
||||
// TODO: set initialLayout to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL for IsRegularTexture() ???
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
void MacVulkanPlatform::GetInstanceExtensions(Array<const char*>& extensions, Array<const char*>& layers)
|
||||
{
|
||||
extensions.Add(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
extensions.Add(VK_MVK_MACOS_SURFACE_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
|
||||
@@ -1024,10 +1024,12 @@ void UpdateGPU(RenderTask* task, GPUContext* context)
|
||||
const auto& track = particleSystem->Tracks[j];
|
||||
if (track.Type != ParticleSystem::Track::Types::Emitter || track.Disabled)
|
||||
continue;
|
||||
const uint32 emitterIndex = track.AsEmitter.Index;
|
||||
auto emitter = particleSystem->Emitters[emitterIndex].Get();
|
||||
auto& data = instance.Emitters[emitterIndex];
|
||||
if (!emitter || !emitter->IsLoaded() || !data.Buffer || emitter->SimulationMode != ParticlesSimulationMode::GPU)
|
||||
const int32 emitterIndex = track.AsEmitter.Index;
|
||||
ParticleEmitter* emitter = particleSystem->Emitters[emitterIndex].Get();
|
||||
if (!emitter || !emitter->IsLoaded() || emitter->SimulationMode != ParticlesSimulationMode::GPU || instance.Emitters.Count() <= emitterIndex)
|
||||
continue;
|
||||
ParticleEmitterInstance& data = instance.Emitters[emitterIndex];
|
||||
if (!data.Buffer)
|
||||
continue;
|
||||
ASSERT(emitter->Capacity != 0 && emitter->Graph.Layout.Size != 0);
|
||||
|
||||
|
||||
@@ -242,7 +242,7 @@ void CharacterController::CreateShape()
|
||||
|
||||
void CharacterController::UpdateBounds()
|
||||
{
|
||||
void* actor = PhysicsBackend::GetShapeActor(_shape);
|
||||
void* actor = _shape ? PhysicsBackend::GetShapeActor(_shape) : nullptr;
|
||||
if (actor)
|
||||
PhysicsBackend::GetActorBounds(actor, _box);
|
||||
else
|
||||
|
||||
@@ -837,8 +837,8 @@ DragDropEffect MacWindow::DoDragDrop(const StringView& data)
|
||||
void MacWindow::SetCursor(CursorType type)
|
||||
{
|
||||
WindowBase::SetCursor(type);
|
||||
if (!_isMouseOver)
|
||||
return;
|
||||
//if (!_isMouseOver)
|
||||
// return;
|
||||
NSCursor* cursor = nullptr;
|
||||
switch (type)
|
||||
{
|
||||
@@ -875,6 +875,7 @@ void MacWindow::SetCursor(CursorType type)
|
||||
if (cursor)
|
||||
{
|
||||
[cursor set];
|
||||
[NSCursor unhide];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,11 @@ public:
|
||||
static void MemoryBarrier();
|
||||
static int64 InterlockedExchange(int64 volatile* dst, int64 exchange)
|
||||
{
|
||||
#if WIN64
|
||||
return _InterlockedExchange64(dst, exchange);
|
||||
#else
|
||||
return _interlockedexchange64(dst, exchange);
|
||||
#endif
|
||||
}
|
||||
static int32 InterlockedCompareExchange(int32 volatile* dst, int32 exchange, int32 comperand)
|
||||
{
|
||||
@@ -37,15 +41,27 @@ public:
|
||||
}
|
||||
static int64 InterlockedIncrement(int64 volatile* dst)
|
||||
{
|
||||
#if WIN64
|
||||
return _InterlockedExchangeAdd64(dst, 1) + 1;
|
||||
#else
|
||||
return _interlockedexchange64(dst, 1) + 1;
|
||||
#endif
|
||||
}
|
||||
static int64 InterlockedDecrement(int64 volatile* dst)
|
||||
{
|
||||
#if WIN64
|
||||
return _InterlockedExchangeAdd64(dst, -1) - 1;
|
||||
#else
|
||||
return _interlockedexchangeadd64(dst, -1) - 1;
|
||||
#endif
|
||||
}
|
||||
static int64 InterlockedAdd(int64 volatile* dst, int64 value)
|
||||
{
|
||||
#if WIN64
|
||||
return _InterlockedExchangeAdd64(dst, value);
|
||||
#else
|
||||
return _interlockedexchangeadd64(dst, value);
|
||||
#endif
|
||||
}
|
||||
static int32 AtomicRead(int32 volatile* dst)
|
||||
{
|
||||
@@ -61,7 +77,11 @@ public:
|
||||
}
|
||||
static void AtomicStore(int64 volatile* dst, int64 value)
|
||||
{
|
||||
#if WIN64
|
||||
_InterlockedExchange64(dst, value);
|
||||
#else
|
||||
_interlockedexchange64(dst, value);
|
||||
#endif
|
||||
}
|
||||
static void Prefetch(void const* ptr);
|
||||
static void* Allocate(uint64 size, uint64 alignment);
|
||||
|
||||
@@ -18,7 +18,7 @@ class FLAXENGINE_API ScriptingEvents
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Global table for registered even binder methods (key is pair of type and event name, value is method that takes instance with event, object to bind and flag to bind or unbind).
|
||||
/// Global table for registered event binder methods (key is pair of type and event name, value is method that takes instance with event, object to bind and flag to bind or unbind).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Key: pair of event type, event name.
|
||||
|
||||
@@ -24,6 +24,7 @@ public:
|
||||
Delegate<> Changed;
|
||||
|
||||
public:
|
||||
NON_COPYABLE(SoftObjectReferenceBase);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SoftObjectReferenceBase"/> class.
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "Engine/Core/Math/Matrix.h"
|
||||
#include "Engine/Scripting/ManagedSerialization.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MUtils.h"
|
||||
#include "Engine/Scripting/ScriptingObjectReference.h"
|
||||
#include "Engine/Content/Asset.h"
|
||||
#include "Engine/Utilities/Encryption.h"
|
||||
#if USE_MONO
|
||||
#include <ThirdParty/mono-2.0/mono/metadata/object.h>
|
||||
|
||||
@@ -5,14 +5,21 @@
|
||||
#include "SerializationFwd.h"
|
||||
#include "Engine/Core/Collections/Array.h"
|
||||
#include "Engine/Core/Collections/Dictionary.h"
|
||||
#include "Engine/Scripting/ScriptingObjectReference.h"
|
||||
#include "Engine/Scripting/SoftObjectReference.h"
|
||||
#include "Engine/Content/AssetReference.h"
|
||||
#include "Engine/Content/WeakAssetReference.h"
|
||||
#include "Engine/Scripting/ScriptingObject.h"
|
||||
#include "Engine/Utilities/Encryption.h"
|
||||
|
||||
struct Version;
|
||||
struct VariantType;
|
||||
template<typename T>
|
||||
class ScriptingObjectReference;
|
||||
template<typename T>
|
||||
class SoftObjectReference;
|
||||
template<typename T>
|
||||
class AssetReference;
|
||||
template<typename T>
|
||||
class WeakAssetReference;
|
||||
template<typename T>
|
||||
class SoftAssetReference;
|
||||
|
||||
// @formatter:off
|
||||
|
||||
@@ -513,6 +520,26 @@ namespace Serialization
|
||||
v = id;
|
||||
}
|
||||
|
||||
// Soft Asset Reference
|
||||
|
||||
template<typename T>
|
||||
inline bool ShouldSerialize(const SoftAssetReference<T>& v, const void* otherObj)
|
||||
{
|
||||
return !otherObj || v.Get() != ((SoftAssetReference<T>*)otherObj)->Get();
|
||||
}
|
||||
template<typename T>
|
||||
inline void Serialize(ISerializable::SerializeStream& stream, const SoftAssetReference<T>& v, const void* otherObj)
|
||||
{
|
||||
stream.Guid(v.GetID());
|
||||
}
|
||||
template<typename T>
|
||||
inline void Deserialize(ISerializable::DeserializeStream& stream, SoftAssetReference<T>& v, ISerializeModifier* modifier)
|
||||
{
|
||||
Guid id;
|
||||
Deserialize(stream, id, modifier);
|
||||
v = id;
|
||||
}
|
||||
|
||||
// Array
|
||||
|
||||
template<typename T, typename AllocationType = HeapAllocation>
|
||||
|
||||
@@ -519,14 +519,12 @@ void ReadStream::ReadJson(ISerializable* obj)
|
||||
|
||||
void WriteStream::WriteText(const StringView& text)
|
||||
{
|
||||
for (int32 i = 0; i < text.Length(); i++)
|
||||
WriteChar(text[i]);
|
||||
WriteBytes(text.Get(), sizeof(Char) * text.Length());
|
||||
}
|
||||
|
||||
void WriteStream::WriteText(const StringAnsiView& text)
|
||||
{
|
||||
for (int32 i = 0; i < text.Length(); i++)
|
||||
WriteChar(text[i]);
|
||||
WriteBytes(text.Get(), sizeof(char) * text.Length());
|
||||
}
|
||||
|
||||
void WriteStream::WriteString(const StringView& data)
|
||||
|
||||
@@ -423,7 +423,7 @@ void ShadowsOfMordor::Builder::onJobRender(GPUContext* context)
|
||||
#endif
|
||||
|
||||
// Report progress
|
||||
float hemispheresProgress = static_cast<float>(_workerStagePosition1) / lightmapEntry.Hemispheres.Count();
|
||||
float hemispheresProgress = static_cast<float>(_workerStagePosition1) / Math::Max(lightmapEntry.Hemispheres.Count(), 1);
|
||||
float lightmapsProgress = static_cast<float>(_workerStagePosition0 + hemispheresProgress) / scene->Lightmaps.Count();
|
||||
float bouncesProgress = static_cast<float>(_giBounceRunningIndex) / _bounceCount;
|
||||
reportProgress(BuildProgressStep::RenderHemispheres, lightmapsProgress / _bounceCount + bouncesProgress);
|
||||
|
||||
@@ -42,6 +42,7 @@ void ModelTool::Options::Serialize(SerializeStream& stream, const void* otherObj
|
||||
SERIALIZE(ImportVertexColors);
|
||||
SERIALIZE(ImportBlendShapes);
|
||||
SERIALIZE(LightmapUVsSource);
|
||||
SERIALIZE(CollisionMeshesPrefix);
|
||||
SERIALIZE(Scale);
|
||||
SERIALIZE(Rotation);
|
||||
SERIALIZE(Translation);
|
||||
@@ -79,6 +80,7 @@ void ModelTool::Options::Deserialize(DeserializeStream& stream, ISerializeModifi
|
||||
DESERIALIZE(ImportVertexColors);
|
||||
DESERIALIZE(ImportBlendShapes);
|
||||
DESERIALIZE(LightmapUVsSource);
|
||||
DESERIALIZE(CollisionMeshesPrefix);
|
||||
DESERIALIZE(Scale);
|
||||
DESERIALIZE(Rotation);
|
||||
DESERIALIZE(Translation);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "Engine/Tools/TextureTool/TextureTool.h"
|
||||
#include "Engine/ContentImporters/AssetsImportingManager.h"
|
||||
#include "Engine/ContentImporters/CreateMaterial.h"
|
||||
#include "Engine/ContentImporters/CreateCollisionData.h"
|
||||
#include "Editor/Utilities/EditorUtilities.h"
|
||||
#include <ThirdParty/meshoptimizer/meshoptimizer.h>
|
||||
|
||||
@@ -562,7 +563,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
|
||||
materialOptions.Opacity.Texture = data.Textures[material.Opacity.TextureIndex].AssetID;
|
||||
if (material.Normals.TextureIndex != -1)
|
||||
materialOptions.Normals.Texture = data.Textures[material.Normals.TextureIndex].AssetID;
|
||||
if (material.TwoSided | material.Diffuse.HasAlphaMask)
|
||||
if (material.TwoSided || material.Diffuse.HasAlphaMask)
|
||||
materialOptions.Info.CullMode = CullMode::TwoSided;
|
||||
if (!Math::IsOne(material.Opacity.Value) || material.Opacity.TextureIndex != -1)
|
||||
materialOptions.Info.BlendMode = MaterialBlendMode::Transparent;
|
||||
@@ -624,6 +625,41 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
|
||||
}
|
||||
}
|
||||
|
||||
// Collision mesh output
|
||||
if (options.CollisionMeshesPrefix.HasChars())
|
||||
{
|
||||
// Extract collision meshes
|
||||
ModelData collisionModel;
|
||||
for (auto& lod : data.LODs)
|
||||
{
|
||||
for (int32 i = lod.Meshes.Count() - 1; i >= 0; i--)
|
||||
{
|
||||
auto mesh = lod.Meshes[i];
|
||||
if (mesh->Name.StartsWith(options.CollisionMeshesPrefix, StringSearchCase::IgnoreCase))
|
||||
{
|
||||
if (collisionModel.LODs.Count() == 0)
|
||||
collisionModel.LODs.AddOne();
|
||||
collisionModel.LODs[0].Meshes.Add(mesh);
|
||||
lod.Meshes.RemoveAtKeepOrder(i);
|
||||
if (lod.Meshes.IsEmpty())
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (collisionModel.LODs.HasItems())
|
||||
{
|
||||
// Create collision
|
||||
CollisionCooking::Argument arg;
|
||||
arg.Type = CollisionDataType::TriangleMesh;
|
||||
arg.OverrideModelData = &collisionModel;
|
||||
auto assetPath = autoImportOutput / StringUtils::GetFileNameWithoutExtension(path) + TEXT("Collision") ASSET_FILES_EXTENSION_WITH_DOT;
|
||||
if (CreateCollisionData::CookMeshCollision(assetPath, arg))
|
||||
{
|
||||
LOG(Error, "Failed to create collision mesh.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For generated lightmap UVs coordinates needs to be moved so all meshes are in unique locations in [0-1]x[0-1] coordinates space
|
||||
if (options.LightmapUVsSource == ModelLightmapUVsSource::Generate && data.LODs.HasItems() && data.LODs[0].Meshes.Count() > 1)
|
||||
{
|
||||
|
||||
@@ -177,6 +177,7 @@ public:
|
||||
bool ImportVertexColors = true;
|
||||
bool ImportBlendShapes = false;
|
||||
ModelLightmapUVsSource LightmapUVsSource = ModelLightmapUVsSource::Disable;
|
||||
String CollisionMeshesPrefix;
|
||||
|
||||
// Transform
|
||||
float Scale = 1.0f;
|
||||
|
||||
Reference in New Issue
Block a user