diff --git a/Download_SDK_Desktop.bat b/Download_SDK_Desktop.bat
index ab37a65..adf00d5 100644
--- a/Download_SDK_Desktop.bat
+++ b/Download_SDK_Desktop.bat
@@ -6,7 +6,7 @@ setlocal
bitsadmin /reset
bitsadmin /create third_party_download_desktop
-bitsadmin /addfile third_party_download_desktop https://downloads.popcornfx.com/Plugins/UE4/UnrealEngine_PopcornFXPlugin_2.18.6_Win64_Linux64_Mac64.7z "%~dp0\_PopcornFX_Runtime_SDK_Desktop.7z"
+bitsadmin /addfile third_party_download_desktop https://downloads.popcornfx.com/Plugins/UE4/UnrealEngine_PopcornFXPlugin_2.19.0_Win64_Linux64_Mac64.7z "%~dp0\_PopcornFX_Runtime_SDK_Desktop.7z"
bitsadmin /setpriority third_party_download_desktop "FOREGROUND"
bitsadmin /resume third_party_download_desktop
diff --git a/Download_SDK_Mobile.bat b/Download_SDK_Mobile.bat
index 7b9d51d..c3ec39a 100644
--- a/Download_SDK_Mobile.bat
+++ b/Download_SDK_Mobile.bat
@@ -6,7 +6,7 @@ setlocal
bitsadmin /reset
bitsadmin /create third_party_download_mobile
-bitsadmin /addfile third_party_download_mobile https://downloads.popcornfx.com/Plugins/UE4/UnrealEngine_PopcornFXPlugin_2.18.6_iOS_Android.7z "%~dp0\_PopcornFX_Runtime_SDK_Mobile.7z"
+bitsadmin /addfile third_party_download_mobile https://downloads.popcornfx.com/Plugins/UE4/UnrealEngine_PopcornFXPlugin_2.19.0_iOS_Android.7z "%~dp0\_PopcornFX_Runtime_SDK_Mobile.7z"
bitsadmin /setpriority third_party_download_mobile "FOREGROUND"
bitsadmin /resume third_party_download_mobile
diff --git a/PopcornFX.uplugin b/PopcornFX.uplugin
index 46a6f6f..22edee4 100644
--- a/PopcornFX.uplugin
+++ b/PopcornFX.uplugin
@@ -1,7 +1,7 @@
{
"FileVersion": 3,
- "Version": 21806,
- "VersionName": "2.18.6",
+ "Version": 21900,
+ "VersionName": "2.19.0",
"FriendlyName": "PopcornFX",
"Description": "PopcornFX Realtime Particle Solution integration into Unreal Engine",
"Category": "PopcornFX",
diff --git a/README.md b/README.md
index 7df2cb1..c94898c 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
# Unreal Engine PopcornFX Plugin
-Integrates the **PopcornFX Runtime SDK** into **Unreal Engine 4** and **Unreal Engine 5** as a Plugin.
-* **Version:** `v2.18.6`
-* **Unreal Engine:** `4.27`, `5.1`, `5.2` and `5.3`
+Integrates the **PopcornFX Runtime SDK** into **Unreal Engine 5** as a Plugin.
+* **Version:** `v2.19.0`
+* **Unreal Engine:** `5.1`, `5.2` and `5.3`
* **Supported platforms:** `Windows`, `MacOS`, `Linux`, `iOS`, `Android`, `PS4`, `PS5`, `XboxOne`, `Xbox Series`, `Switch`
[Contact-us](http://www.popcornfx.com/contact-us/) to request access to the plugin for consoles.
diff --git a/Shaders/Private/PopcornFXGPUBillboard.ush b/Shaders/Private/PopcornFXGPUBillboard.ush
index 6cd7c6c..34da918 100644
--- a/Shaders/Private/PopcornFXGPUBillboard.ush
+++ b/Shaders/Private/PopcornFXGPUBillboard.ush
@@ -33,6 +33,7 @@ struct FVertexFactoryIntermediates
{
float3 ParticleWorldPosition; // UE units
float3 VertexWorldPosition; // UE units
+ float3 VertexPrevWorldPosition; // UE units
float4 VertexTexCoords;
//float ParticleLifeRatio; TODO
@@ -167,6 +168,9 @@ void PopcornFXGPUBillboard(uint instanceID, float2 texCoords, out FVertexFactory
else
radius = PKSimData_Load2f(particleID, PopcornFXGPUBillboardVSUniforms.InSize2sOffset);
+ if (PopcornFXGPUBillboardVSUniforms.InEnabledOffset != -1)
+ radius *= PKSimData_Loadi(particleID, PopcornFXGPUBillboardVSUniforms.InEnabledOffset) != 0 ? 1.0f : 0.0f;
+
float rotation = 0.0f;
float3 xAxis = float3(0.0f, 0.0f, 0.0f);
@@ -293,6 +297,17 @@ void PopcornFXGPUBillboard(uint instanceID, float2 texCoords, out FVertexFactory
intermediates.VertexWorldPosition += ResolvedView.PreViewTranslation;
#endif // (ENGINE_MAJOR_VERSION == 5)
+ BRANCH
+ if (PopcornFXGPUBillboardVSUniforms.InPreviousPositionOffset != -1)
+ intermediates.VertexPrevWorldPosition = (PKSimData_Load3f(particleID, PopcornFXGPUBillboardVSUniforms.InPreviousPositionOffset) + bbCorner) * GLOBAL_SCALE;
+ else
+ intermediates.VertexPrevWorldPosition = (worldPos + bbCorner) * GLOBAL_SCALE; // no velocity
+#if (ENGINE_MAJOR_VERSION == 5)
+ intermediates.VertexPrevWorldPosition += LWCToFloat(ResolvedView.PrevPreViewTranslation);
+#else
+ intermediates.VertexPrevWorldPosition += ResolvedView.PrevPreViewTranslation;
+#endif // (ENGINE_MAJOR_VERSION == 5)
+
#if USE_PARTICLE_POSITION
const float particleRadius = min(radius.x, radius.y) * GLOBAL_SCALE;
# if (ENGINE_MAJOR_VERSION == 5)
diff --git a/Shaders/Private/PopcornFXGPUVertexFactory.ush b/Shaders/Private/PopcornFXGPUVertexFactory.ush
index 63a68df..9420647 100644
--- a/Shaders/Private/PopcornFXGPUVertexFactory.ush
+++ b/Shaders/Private/PopcornFXGPUVertexFactory.ush
@@ -184,9 +184,9 @@ FMaterialVertexParameters GetMaterialVertexParameters(FVertexFactoryInput Input,
VertexParameters.PreSkinnedPosition = Intermediates.ParticleWorldPosition.xyz;
VertexParameters.PreSkinnedNormal = TangentToLocal[2].xyz;
#if (ENGINE_MAJOR_VERSION == 5)
- VertexParameters.PrevFrameLocalToWorld = GetPrimitiveDataFromUniformBuffer().LocalToWorld; // No velocity
+ VertexParameters.PrevFrameLocalToWorld = GetPrimitiveDataFromUniformBuffer().PreviousLocalToWorld;
#else
- VertexParameters.PrevFrameLocalToWorld = Primitive.LocalToWorld; // No velocity
+ VertexParameters.PrevFrameLocalToWorld = Primitive.PreviousLocalToWorld;
#endif // (ENGINE_MAJOR_VERSION == 5)
#if (DYNAMIC_PARAMETERS_MASK != 0)
@@ -431,7 +431,7 @@ float3x3 VertexFactoryGetTangentToLocal(FVertexFactoryInput Input, FVertexFactor
float4 VertexFactoryGetPreviousWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
{
- return VertexFactoryGetWorldPosition(Input, Intermediates); // TODO
+ return float4(Intermediates.VertexPrevWorldPosition, 1.f);
}
float4 VertexFactoryGetTranslatedPrimitiveVolumeBounds(FVertexFactoryInterpolantsVSToPS Interpolants)
diff --git a/Shaders/Private/PopcornFXMeshVertexFactory.ush b/Shaders/Private/PopcornFXMeshVertexFactory.ush
index 8ba9a14..d999f77 100644
--- a/Shaders/Private/PopcornFXMeshVertexFactory.ush
+++ b/Shaders/Private/PopcornFXMeshVertexFactory.ush
@@ -149,6 +149,8 @@ struct FVertexFactoryIntermediates
float4x4 ParticleToWorld;
float4x4 WorldToParticle;
+ float4 PreviousPosition;
+
#if (ENGINE_MAJOR_VERSION == 5)
/** Cached primitive and instance data */
FSceneDataIntermediates SceneData;
@@ -233,7 +235,7 @@ FMaterialPixelParameters GetMaterialPixelParameters(FVertexFactoryInterpolantsVS
# if USE_PARTICLE_WORLD_TO_LOCAL
Result.Particle.WorldToParticle = LWCPromoteInverse(transpose(float4x4(Interpolants.WorldToParticle[0], Interpolants.WorldToParticle[1], Interpolants.WorldToParticle[2], float4(0.0f, 0.0f, 0.0f, 1.0f))));
# if NEEDS_INSTANCE_WORLD_TO_LOCAL_PS
- Result.InstanceWorldtoLocal = Result.Particle.WorldToParticle;
+ Result.InstanceWorldToLocal = Result.Particle.WorldToParticle;
# endif // NEEDS_INSTANCE_WORLD_TO_LOCAL_PS
# endif // USE_PARTICLE_WORLD_TO_LOCAL
#else
@@ -395,6 +397,19 @@ float4 CalcWorldPosition(FVertexFactoryInput Input)
return float4(WorldPosition, Input.Position.w);
}
+float4 CalcPreviousWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
+{
+ // FIXME only offsets the particle position, properly store the previous rotation transforms as well.
+ float4x4 Transform = float4x4(Input.Transform1, Input.Transform2, Input.Transform3, Intermediates.PreviousPosition);
+
+#if (ENGINE_MAJOR_VERSION == 5)
+ float3 WorldPosition = mul(Input.Position, Transform).xyz + LWCHackToFloat(ResolvedView.PrevPreViewTranslation);
+#else
+ float3 WorldPosition = mul(Input.Position, Transform).xyz + ResolvedView.PrevPreViewTranslation;
+#endif // (ENGINE_MAJOR_VERSION == 5)
+ return float4(WorldPosition, Input.Position.w);
+}
+
FVertexFactoryIntermediates GetVertexFactoryIntermediates(FVertexFactoryInput Input)
{
FVertexFactoryIntermediates Intermediates = (FVertexFactoryIntermediates)0;
@@ -429,6 +444,12 @@ FVertexFactoryIntermediates GetVertexFactoryIntermediates(FVertexFactoryInput In
if (PopcornFXMeshVSUniforms.InEmissiveColorsOffset != -1)
Intermediates.EmissiveColor = PKSimData_Load4f(particleID, PopcornFXMeshVSUniforms.InEmissiveColorsOffset);
+ BRANCH
+ if (PopcornFXMeshVSUniforms.InPreviousPositionOffset != -1)
+ Intermediates.PreviousPosition = float4(PKSimData_Load3f(particleID, PopcornFXMeshVSUniforms.InPreviousPositionOffset), Input.Transform4.w);
+ else
+ Intermediates.PreviousPosition = Input.Transform4;
+
// Cursor sent through RelativeTime (either one)
BRANCH
if (PopcornFXMeshVSUniforms.InVATCursorsOffset != -1)
@@ -632,8 +653,7 @@ FVertexFactoryInterpolantsVSToPS VertexFactoryGetInterpolantsVSToPS(FVertexFacto
// @return previous translated world position
float4 VertexFactoryGetPreviousWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
{
- // The previous local to world instance transform isn't available.
- return CalcWorldPosition(Input);
+ return CalcPreviousWorldPosition(Input, Intermediates);
}
#if USING_TESSELLATION
diff --git a/Shaders/Private/PopcornFXSkeletalMeshVertexFactory.ush b/Shaders/Private/PopcornFXSkeletalMeshVertexFactory.ush
index 29cb666..d692876 100644
--- a/Shaders/Private/PopcornFXSkeletalMeshVertexFactory.ush
+++ b/Shaders/Private/PopcornFXSkeletalMeshVertexFactory.ush
@@ -250,7 +250,7 @@ FMaterialPixelParameters GetMaterialPixelParameters(FVertexFactoryInterpolantsVS
# if USE_PARTICLE_WORLD_TO_LOCAL
Result.Particle.WorldToParticle = LWCPromoteInverse(transpose(float4x4(Interpolants.WorldToParticle[0], Interpolants.WorldToParticle[1], Interpolants.WorldToParticle[2], float4(0.0f, 0.0f, 0.0f, 1.0f))));
# if NEEDS_INSTANCE_WORLD_TO_LOCAL_PS
- Result.InstanceWorldtoLocal = Result.Particle.WorldToParticle;
+ Result.InstanceWorldToLocal = Result.Particle.WorldToParticle;
# endif // NEEDS_INSTANCE_WORLD_TO_LOCAL_PS
# endif // USE_PARTICLE_WORLD_TO_LOCAL
#else
diff --git a/Shaders/Private/PopcornFXVertexFactory.ush b/Shaders/Private/PopcornFXVertexFactory.ush
index eeb1c1e..d05c9c6 100644
--- a/Shaders/Private/PopcornFXVertexFactory.ush
+++ b/Shaders/Private/PopcornFXVertexFactory.ush
@@ -54,6 +54,7 @@ struct FVertexFactoryInput
struct FVertexFactoryIntermediates
{
float3 Position;
+ float3 PrevPosition;
float4 ParticleColor;
float3 ParticleEmissiveColor;
@@ -229,6 +230,12 @@ FMaterialVertexParameters GetMaterialVertexParameters(FVertexFactoryInput Input,
VertexParameters.PreSkinnedPosition = Input.Position.xyz;
VertexParameters.PreSkinnedNormal = TangentToLocal[2].xyz;
+#if (ENGINE_MAJOR_VERSION == 5)
+ VertexParameters.PrevFrameLocalToWorld = GetPrimitiveDataFromUniformBuffer().PreviousLocalToWorld;
+#else
+ VertexParameters.PrevFrameLocalToWorld = Primitive.PreviousLocalToWorld;
+#endif // (ENGINE_MAJOR_VERSION == 5)
+
#if NEEDS_PARTICLE_COLOR
VertexParameters.Particle.Color = Intermediates.ParticleColor;
#endif
@@ -316,6 +323,22 @@ FVertexFactoryIntermediates GetVertexFactoryIntermediates(FVertexFactoryInput In
Intermediates.Position = worldVertexPosition;
+ float3 prevVertexPosition = vertexPosition;
+
+ BRANCH
+ if (PopcornFXBillboardVSUniforms.InPreviousPositionOffset != -1)
+ prevVertexPosition = PKSimData_Load3f(particleID, PopcornFXBillboardVSUniforms.InPreviousPositionOffset);
+
+#if (ENGINE_MAJOR_VERSION == 5)
+ float3 prevWorldVertexPosition = mul(float4(prevVertexPosition,1), LWCToFloat(GetPrimitiveDataFromUniformBuffer().PreviousLocalToWorld)).xyz;
+ prevWorldVertexPosition += LWCToFloat(ResolvedView.PrevPreViewTranslation);
+#else
+ float3 prevWorldVertexPosition = mul(float4(prevVertexPosition,1), Primitive.PreviousLocalToWorld).xyz;
+ prevWorldVertexPosition += ResolvedView.PrevPreViewTranslation;
+#endif // (ENGINE_MAJOR_VERSION == 5)
+
+ Intermediates.PrevPosition = prevWorldVertexPosition;
+
BRANCH
if (PopcornFXBillboardVSUniforms.InColorsOffset != -1)
Intermediates.ParticleColor = PKSimData_Load4f(particleID, PopcornFXBillboardVSUniforms.InColorsOffset);
@@ -427,7 +450,7 @@ float3x3 VertexFactoryGetTangentToLocal(FVertexFactoryInput Input, FVertexFactor
float4 VertexFactoryGetPreviousWorldPosition(FVertexFactoryInput Input, FVertexFactoryIntermediates Intermediates)
{
- return VertexFactoryGetWorldPosition(Input, Intermediates);
+ return float4(Intermediates.PrevPosition, 1);
}
float4 VertexFactoryGetTranslatedPrimitiveVolumeBounds(FVertexFactoryInterpolantsVSToPS Interpolants)
diff --git a/Source/PopcornFX/PopcornFX.Build.cs b/Source/PopcornFX/PopcornFX.Build.cs
index 059309b..11ed87a 100644
--- a/Source/PopcornFX/PopcornFX.Build.cs
+++ b/Source/PopcornFX/PopcornFX.Build.cs
@@ -229,7 +229,7 @@ private bool SetupPopcornFX(TargetInfo Target)
#if !UE_5_0_OR_LATER // Support dropped with UE5
if (Target.Platform == UnrealTargetPlatform.Win32)
{
- libPrefix = clientLibDir + "vs2017_Win32/";
+ libPrefix = clientLibDir + "vs2019_Win32/";
libExt = ".lib";
}
else
@@ -237,7 +237,7 @@ private bool SetupPopcornFX(TargetInfo Target)
if (Target.Platform == UnrealTargetPlatform.Win64 ||
isWinUNKNOWN) // Win32 UNKNOWN (WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP), just link with the same libs as Win64
{
- libPrefix = clientLibDir + "vs2017_x64/";
+ libPrefix = clientLibDir + "vs2019_x64/";
libExt = ".lib";
}
else if (Target.Platform == UnrealTargetPlatform.Mac)
@@ -248,31 +248,31 @@ private bool SetupPopcornFX(TargetInfo Target)
#if !UE_5_0_OR_LATER // Support dropped with UE5
else if (Target.Platform == UnrealTargetPlatform.XboxOne)
{
- libPrefix = clientLibDir + "vs2017_Durango/";
+ libPrefix = clientLibDir + "vs2019_Durango/";
libExt = ".lib";
}
#endif // !UE_5_0_OR_LATER
else if (isXboxOneUNKNOWN)
{
- libPrefix = clientLibDir + "vs2017_UNKNOWN.x64/";
+ libPrefix = clientLibDir + "vs2019_UNKNOWN.x64/";
libExt = ".lib";
}
else if (isUNKNOWN)
{
- libPrefix = clientLibDir + "vs2017_UNKNOWN.x64/";
+ libPrefix = clientLibDir + "vs2019_UNKNOWN.x64/";
libExt = ".lib";
}
#if !UE_5_0_OR_LATER // Support dropped with UE5
else if (Target.Platform == UnrealTargetPlatform.PS4)
{
- libPrefix = clientLibDir + "vs2017_ORBIS/";
+ libPrefix = clientLibDir + "vs2019_ORBIS/";
// "vs" + WindowsPlatform.GetVisualStudioCompilerVersionName(); // error (exception) on >= 4.16
libExt = ".a";
}
#endif // !UE_5_0_OR_LATER
else if (isUNKNOWN2)
{
- libPrefix = clientLibDir + "vs2017_UNKNOWN2/";
+ libPrefix = clientLibDir + "vs2019_UNKNOWN2/";
libExt = ".a";
}
else if (Target.Platform == UnrealTargetPlatform.IOS)
@@ -294,7 +294,7 @@ private bool SetupPopcornFX(TargetInfo Target)
#if !UE_5_0_OR_LATER // Support dropped with UE5
else if (Target.Platform == UnrealTargetPlatform.Switch)
{
- libPrefix = clientLibDir + "vs2017_NX64/";
+ libPrefix = clientLibDir + "vs2019_NX64/";
libExt = ".a";
}
#endif // !UE_5_0_OR_LATER
diff --git a/Source/PopcornFX/PopcornFX.natvis b/Source/PopcornFX/PopcornFX.natvis
new file mode 100644
index 0000000..ecb5cee
--- /dev/null
+++ b/Source/PopcornFX/PopcornFX.natvis
@@ -0,0 +1,410 @@
+
+
+
+
+
+
+
+
+
+
+
+ null
+ {*((char**)((unsigned long long)m_Container.m_Ptr + (((sizeof(PopcornFX::CStringContainer) + 4) + (sizeof(void*) - 1)) & ~((unsigned long long)(sizeof(void*) - 1))))),s} [Len={m_Container.m_Ptr->m_Length & 0x7FFFFFFF}]
+ {(char*)((unsigned long long)m_Container.m_Ptr + sizeof(PopcornFX::CStringContainer) + (0xF - ((sizeof(PopcornFX::CStringContainer) + 0xF) & ((unsigned long long)0xF)))),s} [Len={m_Container.m_Ptr->m_Length & 0x7FFFFFFF}]
+ null
+ *((char**)((unsigned long long)m_Container.m_Ptr + (((sizeof(PopcornFX::CStringContainer) + 4) + (sizeof(void*) - 1)) & ~((unsigned long long)(sizeof(void*) - 1))))),s
+ (char*)((unsigned long long)m_Container.m_Ptr + sizeof(PopcornFX::CStringContainer) + (0xF - ((sizeof(PopcornFX::CStringContainer) + 0xF) & ((unsigned long long)0xF)))),s
+
+
+
+ null
+ {*((wchar_t**)((unsigned long long)m_Container.m_Ptr + sizeof(PopcornFX::CStringUnicodeContainer) + 4)),su} [Len={m_Container.m_Ptr->m_Length & 0x7FFFFFFF}]
+ {(wchar_t*)(((unsigned long long)m_Container.m_Ptr + sizeof(PopcornFX::CStringUnicodeContainer) + 0xF) & ~((unsigned long long)0xF)),su} [Len={m_Container.m_Ptr->m_Length & 0x7FFFFFFF}]
+ null
+ *((wchar_t**)((unsigned long long)m_Container.m_Ptr + sizeof(PopcornFX::CStringUnicodeContainer) + 4)),su
+ (wchar_t*)(((unsigned long long)m_Container.m_Ptr + sizeof(PopcornFX::CStringUnicodeContainer) + 0xF) & ~((unsigned long long)0xF)),su
+
+
+
+ Id=0 null
+ Id={m_Id} {PopcornFX::CStringInternals::m_StringIdDictionnary->m_StringIdPool.m_Chunks[m_Id / PopcornFX::CStringIdDictionary::kPoolChunkSize][m_Id % PopcornFX::CStringIdDictionary::kPoolChunkSize]}
+
+ - PopcornFX::CStringInternals::m_StringIdDictionnary->m_StringIdPool.m_Chunks[m_Id / PopcornFX::CStringIdDictionary::kPoolChunkSize][m_Id % PopcornFX::CStringIdDictionary::kPoolChunkSize]
+
+
+
+
+ null
+ {m_Data,[m_Length]s} [Len={m_Length}]
+
+
+
+ null
+ {m_DataFeed.m_Ptr}
+
+ m_DataFeed.m_Ptr
+
+
+
+
+ {{RefPtr={(void*)m_Ptr}}}
+
+ m_Ptr
+
+
+
+ {{WeakPtr={(void*)m_Ptr}}}
+
+ m_Ptr
+
+
+
+ {{ScopedPtr={(void*)m_Ptr}}}
+
+ m_Ptr
+
+
+
+
+ {{A Count={m_Count}}}
+
+
+ m_Count
+ ($T1*)m_Data
+
+
+
+
+
+ {{A Count={m_Count}}}
+
+
+ m_Count
+ ($T1*)m_Data
+
+
+
+
+
+ {{SDA Count={m_Count & 0x7FFFFFFF} Data={(void*)m_Allocated.m_Data}}
+ {{SDA Count={m_Count & 0x7FFFFFFF} Data={(void*)(((unsigned long long)m_StaticData + kAlignment - 1) & - kAlignment)}}
+
+
+ m_Count & 0x7FFFFFFF
+ ($T1*)m_Allocated.m_Data
+
+
+ m_Count
+ ($T1*)(((unsigned long long)m_StaticData + kAlignment - 1) & - kAlignment)
+
+
+
+
+
+ {{SFA Count={m_Count}, Data={(void*)m_Data}, Cap={m_Capacity}}}
+
+
+ m_Count
+ ($T1*)m_Data
+
+
+
+
+
+ {{SA _Count={$T2}, Data={(void*)(((unsigned long long)_m_Data + kAlignment - 1) & - kAlignment)}
+
+
+ $T2
+ ($T1*)(((unsigned long long)_m_Data + kAlignment - 1) & - kAlignment)
+
+
+
+
+
+ {{SCA Count={m_Count}, Data={(void*)(((unsigned long long)_m_Data + kAlignment - 1) & - kAlignment)}}}
+
+
+ m_Count
+ ($T1*)(((unsigned long long)_m_Data + kAlignment - 1) & - kAlignment)
+
+
+
+
+
+ {{CA Count={$T2 * m_ChunksCount}({$T2}*{m_ChunksCount}), ChuncksCap={m_ChunksCapacity}}}
+
+
+ $T2 * m_ChunksCount
+ m_Chunks[$i / $T2][$i % $T2]
+
+
+
+
+
+ {{SlotA UsedCount={m_UsedSlots} _Count={$T2}}}
+
+
+ $T2
+ ($T1*)m_Data
+
+
+
+
+
+ {{SlotA UsedCount={m_UsedSlots} Count={m_DataSizeInBytes / sizeof($T1)}}}
+
+
+ m_DataSizeInBytes / sizeof($T1)
+ ($T1*)m_Data
+
+
+
+
+
+ {{MV Count={m_Count}, Data={(void*)m_Data}, sizeof={sizeof($T1)}}}
+
+
+ m_Count
+ ($T1*)m_Data
+
+
+
+
+
+ {{SMV Count={m_Storage.m_Count}, Data={(void*)m_Storage.m_RawDataPtr}, Stride={m_Storage.m_Stride}, sizeof={sizeof($T1)}}}
+
+
+ m_Storage.m_Count
+ *(($T1*)(m_Storage.m_RawDataPtr + $i * m_Storage.m_Stride))
+
+
+
+
+
+ {{SMVF Count={m_Storage.m_Count}, Data={(void*)m_Storage.m_RawDataPtr}, Stride={m_Storage.m_Stride}, Footp={m_ElementFootprintInBytes}, sizeof={sizeof($T1)}}
+
+
+ m_Storage.m_Count
+ *(($T1*)(m_Storage.m_RawDataPtr + $i * m_Storage.m_Stride))
+
+
+
+
+
+ {{First={m_First}, Second={m_Second}}}
+
+ - m_First
+ - m_Second
+
+
+
+
+ {{FHM Count={m_Count}, Data={(void*)m_Slots}, Size={m_Size}}}
+
+
+ m_Size
+ m_Slots
+
+
+
+
+
+
+
+ empty
+
+ void (error)
+
+
+ const class cr{m_RawBits & 0xFFFF,d}
+ variable class vr{m_RawBits & 0xFFFF,d}
+ instance class ir{m_RawBits & 0xFFFF,d}
+ stream class sr{m_RawBits & 0xFFFF,d}
+
+
+ const bool1 cr{m_RawBits & 0xFFFF,d}
+ variable bool1 vr{m_RawBits & 0xFFFF,d}
+ instance bool1 ir{m_RawBits & 0xFFFF,d}
+ stream bool1 sr{m_RawBits & 0xFFFF,d}
+
+ const bool2 cr{m_RawBits & 0xFFFF,d}
+ variable bool2 vr{m_RawBits & 0xFFFF,d}
+ instance bool2 ir{m_RawBits & 0xFFFF,d}
+ stream bool2 sr{m_RawBits & 0xFFFF,d}
+
+ const bool3 cr{m_RawBits & 0xFFFF,d}
+ variable bool3 vr{m_RawBits & 0xFFFF,d}
+ instance bool3 ir{m_RawBits & 0xFFFF,d}
+ stream bool3 sr{m_RawBits & 0xFFFF,d}
+
+ const bool4 cr{m_RawBits & 0xFFFF,d}
+ variable bool4 vr{m_RawBits & 0xFFFF,d}
+ instance bool4 ir{m_RawBits & 0xFFFF,d}
+ stream bool4 sr{m_RawBits & 0xFFFF,d}
+
+
+ const int1 cr{m_RawBits & 0xFFFF,d}
+ variable int1 vr{m_RawBits & 0xFFFF,d}
+ instance int1 ir{m_RawBits & 0xFFFF,d}
+ stream int1 sr{m_RawBits & 0xFFFF,d}
+
+ const int2 cr{m_RawBits & 0xFFFF,d}
+ variable int2 vr{m_RawBits & 0xFFFF,d}
+ instance int2 ir{m_RawBits & 0xFFFF,d}
+ stream int2 sr{m_RawBits & 0xFFFF,d}
+
+ const int3 cr{m_RawBits & 0xFFFF,d}
+ variable int3 vr{m_RawBits & 0xFFFF,d}
+ instance int3 ir{m_RawBits & 0xFFFF,d}
+ stream int3 sr{m_RawBits & 0xFFFF,d}
+
+ const int4 cr{m_RawBits & 0xFFFF,d}
+ variable int4 vr{m_RawBits & 0xFFFF,d}
+ instance int4 ir{m_RawBits & 0xFFFF,d}
+ stream int4 sr{m_RawBits & 0xFFFF,d}
+
+
+ const float1 cr{m_RawBits & 0xFFFF,d}
+ variable float1 vr{m_RawBits & 0xFFFF,d}
+ instance float1 ir{m_RawBits & 0xFFFF,d}
+ stream float1 sr{m_RawBits & 0xFFFF,d}
+
+ const float2 cr{m_RawBits & 0xFFFF,d}
+ variable float2 vr{m_RawBits & 0xFFFF,d}
+ instance float2 ir{m_RawBits & 0xFFFF,d}
+ stream float2 sr{m_RawBits & 0xFFFF,d}
+
+ const float3 cr{m_RawBits & 0xFFFF,d}
+ variable float3 vr{m_RawBits & 0xFFFF,d}
+ instance float3 ir{m_RawBits & 0xFFFF,d}
+ stream float3 sr{m_RawBits & 0xFFFF,d}
+
+ const float4 cr{m_RawBits & 0xFFFF,d}
+ variable float4 vr{m_RawBits & 0xFFFF,d}
+ instance float4 ir{m_RawBits & 0xFFFF,d}
+ stream float4 sr{m_RawBits & 0xFFFF,d}
+
+
+ const orientation cr{m_RawBits & 0xFFFF,d}
+ variable orientation vr{m_RawBits & 0xFFFF,d}
+ instance orientation ir{m_RawBits & 0xFFFF,d}
+ stream orientation sr{m_RawBits & 0xFFFF,d}
+
+
+
+
+
+ Range = ]{m_BoundMin.m_Value.m_Data32u,X}, {m_BoundMax.m_Value.m_Data32u,X}[ - ]{m_BoundMin.m_Value.m_Data32f}, {m_BoundMax.m_Value.m_Data32f}[ - ]{m_BoundMin.m_Value.m_Data32s}, {m_BoundMax.m_Value.m_Data32s}[
+ Range = ]{m_BoundMin.m_Value.m_Data32u,X}, {m_BoundMax.m_Value.m_Data32u,X}] - ]{m_BoundMin.m_Value.m_Data32f}, {m_BoundMax.m_Value.m_Data32f}] - ]{m_BoundMin.m_Value.m_Data32s}, {m_BoundMax.m_Value.m_Data32s}]
+ Range = [{m_BoundMin.m_Value.m_Data32u,X}, {m_BoundMax.m_Value.m_Data32u,X}[ - [{m_BoundMin.m_Value.m_Data32f}, {m_BoundMax.m_Value.m_Data32f}[ - [{m_BoundMin.m_Value.m_Data32s}, {m_BoundMax.m_Value.m_Data32s}[
+ Range = [{m_BoundMin.m_Value.m_Data32u,X}, {m_BoundMax.m_Value.m_Data32u,X}] - [{m_BoundMin.m_Value.m_Data32f}, {m_BoundMax.m_Value.m_Data32f}] - [{m_BoundMin.m_Value.m_Data32s}, {m_BoundMax.m_Value.m_Data32s}]
+
+
+
+ X
+ O
+
+
+
+ {*(PopcornFX::Range::Internal::_SConstantRange_Natvis*)(m_BoundMin.m_Value.m_Data32u + 0)}
+
+
+ 4
+ (PopcornFX::Range::Internal::_SConstantRange_Natvis*)(m_BoundMin.m_Value.m_Data32u + $i)
+
+
+
+
+
+ {*(PopcornFX::Range::Internal::_SConstantEdge_Natvis*)(m_Edge.m_Data+0)}{*(PopcornFX::Range::Internal::_SConstantEdge_Natvis*)(m_Edge.m_Data+1)}{*(PopcornFX::Range::Internal::_SConstantEdge_Natvis*)(m_Edge.m_Data+2)}{*(PopcornFX::Range::Internal::_SConstantEdge_Natvis*)(m_Edge.m_Data+3)}: |{m_Value.m_Data32u[0],X}, {m_Value.m_Data32u[1],X}, {m_Value.m_Data32u[2],X}, {m_Value.m_Data32u[3],X}| - |{m_Value.m_Data32f[0]}, {m_Value.m_Data32f[1]}, {m_Value.m_Data32f[2]}, {m_Value.m_Data32f[3]}| - |{m_Value.m_Data32s[0]}, {m_Value.m_Data32s[1]}, {m_Value.m_Data32s[2]}, {m_Value.m_Data32s[3]}|
+
+
+
+ INVALID
+ void
+ auto
+ byte
+ float
+ float2
+ float3
+ float4
+ int
+ int2
+ int3
+ int4
+ bool
+ bool2
+ bool3
+ bool4
+ orientation
+
+ - m_Index
+
+
+
+
+ {(PopcornFX::CVStreamSemanticDictionnary::EDefaultOrdinals)(m_Code >> 8)}
+ (m_Code >> 8)
+
+ - (PopcornFX::CVStreamSemanticDictionnary::EDefaultOrdinals)(m_Code >> 8)
+ - (m_Code >> 8)
+ - (PopcornFX::SVStreamCode::EElementType)(m_Code & 0x1F)
+ - (m_Code & 0x80) != 0
+ - (m_Code & 0x40) != 0
+ - m_Code
+
+
+
+
+ v{(m_Key >> 29) & 0x7,d}.{(m_Key >> 24) & 0x1F,d}.{(m_Key >> 18) & 0x3F,d}.{m_Key & 0x3FFFF,d}
+
+ - m_Key
+
+
+
+
+ {m_Data}
+
+
+ $T2
+ m_Data
+
+
+
+
+
+ {m_Axes}
+
+
+ $T2
+ m_Axes
+
+
+
+
+
+ {{{m_Imag[0]}, {m_Imag[1]}, {m_Imag[2]}, {m_Real}}}
+
+
+ 4
+ m_Imag
+
+
+
+
+
diff --git a/Source/PopcornFX/Private/Assets/PopcornFXAssetDep.cpp b/Source/PopcornFX/Private/Assets/PopcornFXAssetDep.cpp
index 2ea2d04..462d751 100644
--- a/Source/PopcornFX/Private/Assets/PopcornFXAssetDep.cpp
+++ b/Source/PopcornFX/Private/Assets/PopcornFXAssetDep.cpp
@@ -195,7 +195,7 @@ bool UPopcornFXAssetDep::SetAsset(UPopcornFXFile *file, UObject *asset)
FString UPopcornFXAssetDep::GetDefaultAssetPath() const
{
- return FPopcornFXPlugin::Get().BuildPathFromPkPath(TCHAR_TO_ANSI(*ImportPath), true);
+ return FPopcornFXPlugin::Get().BuildPathFromPkPath(ToPk(ImportPath), true);
}
//----------------------------------------------------------------------------
@@ -237,16 +237,16 @@ bool UPopcornFXAssetDep::ReimportAndResetDefaultAsset(UPopcornFXFile *file, bool
FString importSourcePath;
if (bImportFromCache)
{
- importSourcePath = FPopcornFXPlugin::Get().SettingsEditor()->SourcePackCacheDir / GetSourcePath();
+ importSourcePath = FPopcornFXPlugin::Get().SettingsEditor()->AbsSourcePackCacheDir / GetSourcePath();
if (!FPaths::FileExists(importSourcePath))
{
- UE_LOG(LogPopcornFXAssetDep, Error, TEXT("Source File '%s' not found. Please make sure to right click and 'Build Assets' on the source file."), *(FPopcornFXPlugin::Get().SettingsEditor()->SourcePackRootDir / GetSourcePath()));
+ UE_LOG(LogPopcornFXAssetDep, Error, TEXT("Source File '%s' not found. Please make sure to right click and 'Build Assets' on the source file."), *(FPopcornFXPlugin::Get().SettingsEditor()->AbsSourcePackRootDir / GetSourcePath()));
return false;
}
}
else
{
- importSourcePath = FPopcornFXPlugin::Get().SettingsEditor()->SourcePackRootDir / GetSourcePath();
+ importSourcePath = FPopcornFXPlugin::Get().SettingsEditor()->AbsSourcePackRootDir / GetSourcePath();
if (!FPaths::FileExists(importSourcePath))
{
UE_LOG(LogPopcornFXAssetDep, Error, TEXT("Source File '%s' not found to Import"), *importSourcePath);
@@ -299,17 +299,17 @@ void UPopcornFXAssetDep::GetAssetPath(FString &outputPath) const
}
PopcornFX::PFilePack pack;
- const PopcornFX::CString assetPath = TCHAR_TO_ANSI(*Asset->GetPathName());
+ const PopcornFX::CString assetPath = ToPk(Asset->GetPathName());
PK_ASSERT(PopcornFX::File::DefaultFileSystem() != null);
const PopcornFX::CString virtPath = PopcornFX::File::DefaultFileSystem()->PhysicalToVirtual(assetPath, &pack);
if (!virtPath.Empty())
{
PK_VERIFY(pack == FPopcornFXPlugin::Get().FilePack());
- outputPath = ANSI_TO_TCHAR(virtPath.Data());
+ outputPath = ToUE(virtPath);
return; // OK
}
- UE_LOG(LogPopcornFXAssetDep, Warning, TEXT("Asset '%s' is outside the mounted PopcornFX Pack"), ANSI_TO_TCHAR(assetPath.Data()));
+ UE_LOG(LogPopcornFXAssetDep, Warning, TEXT("Asset '%s' is outside the mounted PopcornFX Pack"), *ToUE(assetPath));
outputPath = ImportPath;
}
@@ -339,7 +339,7 @@ bool UPopcornFXAssetDep::Setup(UPopcornFXFile *file, const FString &sourcePathOr
ext == "pkan")
bImportFromCache = true;
- UObject *asset = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(TCHAR_TO_ANSI(*ImportPath), false);
+ UObject *asset = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(ToPk(ImportPath), false);
if (asset != null)
{
if (PK_VERIFY(IsCompatibleClass(asset->GetClass())))
@@ -397,7 +397,7 @@ void UPopcornFXAssetDep::PatchFields(UPopcornFXFile *file) const
FString newAssetPath;
GetAssetPath(newAssetPath);
- PopcornFX::CString newAssetPathPk = TCHAR_TO_ANSI(*newAssetPath); // Conv to UE, can't have PK types in public header.
+ PopcornFX::CString newAssetPathPk = ToPk(newAssetPath); // Conv to UE, can't have PK types in public header.
if (!PK_VERIFY(!newAssetPathPk.Empty()))
return;
@@ -427,7 +427,7 @@ void UPopcornFXAssetDep::PatchFields(UPopcornFXFile *file) const
if (bo != null)
{
- const PopcornFX::CString fieldName = TCHAR_TO_ANSI(*(patch.FieldName));
+ const PopcornFX::CString fieldName = ToPk(patch.FieldName);
PopcornFX::CGuid fieldId = bo->GetFieldIndex(PopcornFX::CStringView(fieldName));
if (PK_VERIFY(fieldId.Valid()))
{
@@ -468,7 +468,7 @@ UPopcornFXFile *UPopcornFXAssetDep::ParentPopcornFXFile() const
bool UPopcornFXAssetDep::Conflicts(const FString &importPath, EPopcornFXAssetDepType::Type type, const TArray &otherAssetDeps)
{
- const FString gamePath = FPopcornFXPlugin::Get().BuildPathFromPkPath(TCHAR_TO_ANSI(*importPath), true);
+ const FString gamePath = FPopcornFXPlugin::Get().BuildPathFromPkPath(ToPk(importPath), true);
if (!PK_VERIFY(!gamePath.IsEmpty()))
return false;
diff --git a/Source/PopcornFX/Private/Assets/PopcornFXEffect.cpp b/Source/PopcornFX/Private/Assets/PopcornFXEffect.cpp
index d5b3af6..2b4ff50 100644
--- a/Source/PopcornFX/Private/Assets/PopcornFXEffect.cpp
+++ b/Source/PopcornFX/Private/Assets/PopcornFXEffect.cpp
@@ -188,7 +188,7 @@ void UPopcornFXEffect::BeginCacheForCookedPlatformData(const ITargetPlatform *ta
}
FString bakedFilePath;
- if (_BakeFile(path, bakedFilePath, false, TCHAR_TO_ANSI(*targetPlatform->PlatformName())))
+ if (_BakeFile(path, bakedFilePath, false, targetPlatform->PlatformName()))
{
// For debugging purposes only, helps inspect content of baked effects
if (FPopcornFXPlugin::Get().SettingsEditor()->bDebugBakedEffects)
@@ -235,7 +235,7 @@ const PopcornFX::CStringView kQualityLevelNames[] = { "low", "medium", "high", "
//----------------------------------------------------------------------------
-bool UPopcornFXEffect::LoadEffect()
+bool UPopcornFXEffect::LoadEffect(bool forceImport)
{
ClearEffect();
@@ -272,7 +272,7 @@ bool UPopcornFXEffect::LoadEffect()
m_Loaded = true;
- DefaultAttributeList->SetupDefault(this);
+ DefaultAttributeList->SetupDefault(this, forceImport);
return m_Loaded;
}
@@ -577,7 +577,7 @@ namespace
if (filePath.Empty())
return;
- FString cleanFilePath = filePath.Data();
+ FString cleanFilePath = ToUE(filePath);
const PopcornFX::HBO::CFieldDefinition &fieldDef = hbo.GetFieldDefinition(fieldIndex);
const PopcornFX::HBO::CFieldAttributesBase &fieldAttribs = fieldDef.GetBaseAttributes();
@@ -716,7 +716,6 @@ namespace
bool UPopcornFXEffect::_ImportFile(const FString &filePath)
{
- DefaultAttributeList->Clean();
ClearEffect();
if (!Super::_ImportFile(filePath))
@@ -749,7 +748,7 @@ bool UPopcornFXEffect::_BakeFile(const FString &srcFilePath, FString &outBakedFi
for (s32 i = 0; i < qualityLevelCount; ++i)
PK_VERIFY(targetBuildVersions.PushBack(PopcornFX::CString::Format("%s:%s%s", kQualityLevelNames[i].Data(), backendAndBuildTags.m_BuildTags.Data(), kQualityLevelNames[i].Data())).Valid());
- const TCHAR *targetPlatformNameForLog = forEditor ? ANSI_TO_TCHAR("UnrealEditor") : *targetPlatformName;
+ const TCHAR *targetPlatformNameForLog = forEditor ? UTF8_TO_TCHAR("UnrealEditor") : *targetPlatformName;
UE_LOG(LogPopcornFXEffect, Display, TEXT("Begin effect baking '%s' for '%s'..."), *GetPathName(), targetPlatformNameForLog);
@@ -777,7 +776,7 @@ bool UPopcornFXEffect::_BakeFile(const FString &srcFilePath, FString &outBakedFi
}
PopcornFX::CCookery cookery;
- const PopcornFX::SBakeTarget defaultTarget("UE_Generic", TCHAR_TO_ANSI(*bakeDirPath));
+ const PopcornFX::SBakeTarget defaultTarget("UE_Generic", ToPk(bakeDirPath));
if (FPopcornFXPlugin::Get().Settings() == null) // Will trigger a load of settings if necessary
return false;
@@ -846,7 +845,7 @@ bool UPopcornFXEffect::_BakeFile(const FString &srcFilePath, FString &outBakedFi
#if (PK_COMPILE_GPU != 0)
if (backendAndBuildTags.m_BackendTargets > 0)
{
- if (!_SetupBakeBackendCompilers(bakeConfig, backendAndBuildTags, TCHAR_TO_ANSI(*FileSourceVirtualPath)))
+ if (!_SetupBakeBackendCompilers(bakeConfig, backendAndBuildTags, ToPk(FileSourceVirtualPath)))
{
UE_LOG(LogPopcornFXEffect, Warning, TEXT("Couldn't bake effect '%s': failed setting up GPU backend compilers"), *GetPathName());
return false;
@@ -859,7 +858,7 @@ bool UPopcornFXEffect::_BakeFile(const FString &srcFilePath, FString &outBakedFi
bakeConfig->SetExtensionsRemap(extensionsRemap);
PopcornFX::CMessageStream bakerErrors;
- if (!cookery.BakeAsset(TCHAR_TO_ANSI(*resolvedSrcFilePath), configFile, bakerErrors))
+ if (!cookery.BakeAsset(ToPk(resolvedSrcFilePath), configFile, bakerErrors))
{
UE_LOG(LogPopcornFXEffect, Warning, TEXT("Failed baking effect '%s' for '%s'%s"), *GetPathName(), targetPlatformNameForLog, !bakerErrors.Messages().Empty() ? ":" : ".");
for (const auto &message : bakerErrors.Messages())
@@ -867,7 +866,7 @@ bool UPopcornFXEffect::_BakeFile(const FString &srcFilePath, FString &outBakedFi
if (message.m_Level >= PopcornFX::CMessageStream::Warning)
{
const PopcornFX::CString messageText = message.ToString();
- UE_LOG(LogPopcornFXEffect, Warning, TEXT(" - %s"), ANSI_TO_TCHAR(messageText.Data()));
+ UE_LOG(LogPopcornFXEffect, Warning, TEXT(" - %s"), *ToUE(messageText));
}
}
return false;
@@ -879,7 +878,7 @@ bool UPopcornFXEffect::_BakeFile(const FString &srcFilePath, FString &outBakedFi
if (message.m_Level >= PopcornFX::CMessageStream::Warning)
{
const PopcornFX::CString messageText = message.ToString();
- UE_LOG(LogPopcornFXEffect, Warning, TEXT(" - %s"), ANSI_TO_TCHAR(messageText.Data()));
+ UE_LOG(LogPopcornFXEffect, Warning, TEXT(" - %s"), *ToUE(messageText));
}
}
}
@@ -892,7 +891,7 @@ bool UPopcornFXEffect::_BakeFile(const FString &srcFilePath, FString &outBakedFi
bool UPopcornFXEffect::FinishImport()
{
- if (!LoadEffect())
+ if (!LoadEffect(true))
return false;
TArray oldAssetDeps = AssetDependencies;
diff --git a/Source/PopcornFX/Private/Assets/PopcornFXFile.cpp b/Source/PopcornFX/Private/Assets/PopcornFXFile.cpp
index b608621..3e5b0a2 100644
--- a/Source/PopcornFX/Private/Assets/PopcornFXFile.cpp
+++ b/Source/PopcornFX/Private/Assets/PopcornFXFile.cpp
@@ -40,21 +40,21 @@ namespace
{
PK_ASSERT(!file.IsUnreachable());
- PopcornFX::CString rawFilePath = TCHAR_TO_ANSI(*file.GetPathName());
+ PopcornFX::CString rawFilePath = ToPk(file.GetPathName());
PopcornFX::PFilePack pack = FPopcornFXPlugin::Get().FilePack();
if (pack == null)
{
- UE_LOG(LogPopcornFile, Warning/*Error*/, TEXT("PopcornFX pack not loaded, cannot find '%s'"), ANSI_TO_TCHAR(rawFilePath.Data()));
+ UE_LOG(LogPopcornFile, Warning/*Error*/, TEXT("PopcornFX pack not loaded, cannot find '%s'"), *ToUE(rawFilePath));
return null;
}
const PopcornFX::CString &packPath = pack->Path();
- if (!rawFilePath.StartsWith(packPath.Data()))
+ if (!rawFilePath.StartsWith(packPath))
{
#if WITH_EDITOR
if (!IsRunningCommandlet()) // We don't want this error to fail the packaging
{
FText title = LOCTEXT("import_outside_mountpoint_title", "PopcornFX: Invalid file location");
- FText finalText = FText::FromString(FString::Printf(TEXT("The PopcornFX file '%s' is outside the mount point of the PopcornFX pack '%s'"), ANSI_TO_TCHAR(rawFilePath.Data()), ANSI_TO_TCHAR(packPath.Data())));
+ FText finalText = FText::FromString(FString::Printf(TEXT("The PopcornFX file '%s' is outside the mount point of the PopcornFX pack '%s'"), *ToUE(rawFilePath), *ToUE(packPath)));
OpenMessageBox(EAppMsgType::Ok, finalText, title);
}
@@ -71,7 +71,7 @@ namespace
rawFilePath = PopcornFX::CFilePath::StripExtension(rawFilePath);
rawFilePath += ".";
- rawFilePath += TCHAR_TO_ANSI(*file.PkExtension());
+ rawFilePath += ToPk(file.PkExtension());
return rawFilePath;
}
}
@@ -229,13 +229,13 @@ bool UPopcornFXFile::ImportThumbnail()
{
UE_LOG(LogPopcornFile, Warning, TEXT("Imported file is outside Source PopcornFX Project, we cannot import its thumbnail !"));
}
- else if (!PK_VERIFY(settings != null) || settings->SourcePackThumbnailsDir.IsEmpty())
+ else if (!PK_VERIFY(settings != null) || settings->AbsSourcePackThumbnailsDir.IsEmpty())
{
UE_LOG(LogPopcornFile, Warning, TEXT("Source PopcornFX Project is invalid, we cannot import its thumbnail !"));
}
else // ok
{
- const FString srcPath = settings->SourcePackThumbnailsDir / FileSourceVirtualPath + TEXT(".png");
+ const FString srcPath = settings->AbsSourcePackThumbnailsDir / FileSourceVirtualPath + TEXT(".png");
bool bImportWasCancelled;
if (ThumbnailImage == null ||
!FReimportManager::Instance()->Reimport(ThumbnailImage, false, false))
@@ -272,7 +272,7 @@ FString UPopcornFXFile::FileSourcePath() const
{
PK_ASSERT(!FileSourceVirtualPath.IsEmpty());
if (FileSourceVirtualPathIsNotVirtual == 0)
- return FPopcornFXPlugin::Get().SettingsEditor()->SourcePackRootDir / FileSourceVirtualPath;
+ return FPopcornFXPlugin::Get().SettingsEditor()->AbsSourcePackRootDir / FileSourceVirtualPath;
return FileSourceVirtualPath;
}
@@ -286,7 +286,7 @@ void UPopcornFXFile::SetFileSourcePath(const FString &fileSourcePath)
m_IsBaseObject = false;
bool absoluteImport = true;
- const FString packDir = FPopcornFXPlugin::Get().SettingsEditor()->SourcePackRootDir / "";
+ const FString packDir = FPopcornFXPlugin::Get().SettingsEditor()->AbsSourcePackRootDir / "";
if (packDir.Len() > 0)
{
@@ -340,8 +340,8 @@ void UPopcornFXFile::AskImportAssetDependenciesIFN()
bool foundSome = false;
- const FString sourcePack = FPopcornFXPlugin::Get().SettingsEditor()->SourcePackRootDir;
- const FString sourcePackCacheDir = FPopcornFXPlugin::Get().SettingsEditor()->SourcePackCacheDir;
+ const FString sourcePack = FPopcornFXPlugin::Get().SettingsEditor()->AbsSourcePackRootDir;
+ const FString sourcePackCacheDir = FPopcornFXPlugin::Get().SettingsEditor()->AbsSourcePackCacheDir;
for (int32 asseti = 0; asseti < AssetDependencies.Num(); ++asseti)
{
const UPopcornFXAssetDep *assetDep = AssetDependencies[asseti];
diff --git a/Source/PopcornFX/Private/Assets/PopcornFXMesh.cpp b/Source/PopcornFX/Private/Assets/PopcornFXMesh.cpp
index 4f0ab09..41fe6f6 100644
--- a/Source/PopcornFX/Private/Assets/PopcornFXMesh.cpp
+++ b/Source/PopcornFX/Private/Assets/PopcornFXMesh.cpp
@@ -228,7 +228,7 @@ PopcornFX::PResourceMesh UPopcornFXMesh::LoadResourceMeshIFN(bool editorBuildIFN
m_ResourceMesh = PopcornFX::CResourceMesh::Load(PopcornFX::File::DefaultFileSystem(), PopcornFX::CFilePackPath(FPopcornFXPlugin::Get().FilePack(), PkPath()), outReport);
if (m_ResourceMesh == null)
{
- UE_LOG(LogPopcornMesh, Warning, TEXT("Couldn't load PopcornFX mesh '%s'"), ANSI_TO_TCHAR(PkPath()));
+ UE_LOG(LogPopcornMesh, Warning, TEXT("Couldn't load PopcornFX mesh '%s'"), *ToUE(PkPath()));
m_ResourceMesh = null;
}
}
@@ -394,6 +394,13 @@ namespace
const u32 numVertices = section.GetNumVertices();
const u32 sectionInfluenceCount = section.MaxBoneInfluences;
+#if (ENGINE_MAJOR_VERSION == 4)
+ const float boneWeightNormalizer = 1.0f / 255.0f;
+#else
+ // 'GetBoneWeight()' will always return 16-bit bone weights, even if 'Use16BitBoneWeight()' is false, or if 'GetBoneWeightByteSize()' returns 1
+ const float boneWeightNormalizer = 1.0f / 65535.0f;
+#endif
+
for (u32 iVertex = 0; iVertex < numVertices; ++iVertex)
{
const u32 vertexIndex = sectionOffset + iVertex;
@@ -419,7 +426,7 @@ namespace
for (u32 iInfluence = 0; iInfluence < sectionInfluenceCount; ++iInfluence)
{
const float localBoneWeight = LODRenderData.SkinWeightVertexBuffer.GetBoneWeight(vertexIndex, iInfluence);
- const float boneWeight = localBoneWeight / 255.0f;
+ const float boneWeight = localBoneWeight * boneWeightNormalizer;
PK_ONLY_IF_ASSERTS(weightsSum += boneWeight);
_boneWeights[offsetInfluences + iInfluence] = boneWeight;
diff --git a/Source/PopcornFX/Private/Assets/PopcornFXRendererMaterial.cpp b/Source/PopcornFX/Private/Assets/PopcornFXRendererMaterial.cpp
index 9e801ce..55ad466 100644
--- a/Source/PopcornFX/Private/Assets/PopcornFXRendererMaterial.cpp
+++ b/Source/PopcornFX/Private/Assets/PopcornFXRendererMaterial.cpp
@@ -1649,16 +1649,16 @@ UTexture2D *LoadTexturePk(const PopcornFX::CString &pkPath)
if (pkPath.Empty())
return null;
- UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(pkPath.Data(), false);
+ UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(pkPath, false);
UTexture2D *texture = Cast(obj);
if (obj != null && texture == null)
{
- UE_LOG(LogPopcornFXRendererMaterial, Warning, TEXT("Asset is not a texture: '%s'"), ANSI_TO_TCHAR(pkPath.Data()));
+ UE_LOG(LogPopcornFXRendererMaterial, Warning, TEXT("Asset is not a texture: '%s'"), *ToUE(pkPath));
return null;
}
if (texture == null)
{
- UE_LOG(LogPopcornFXRendererMaterial, Warning, TEXT("Could not load texture '%s'"), ANSI_TO_TCHAR(pkPath.Data()));
+ UE_LOG(LogPopcornFXRendererMaterial, Warning, TEXT("Could not load texture '%s'"), *ToUE(pkPath));
return null;
}
return texture;
@@ -1671,16 +1671,16 @@ UPopcornFXTextureAtlas *LoadAtlasPk(const PopcornFX::CString &pkPath)
if (pkPath.Empty())
return null;
- UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(pkPath.Data(), false);
+ UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(pkPath, false);
UPopcornFXTextureAtlas *atlas = Cast(obj);
if (obj != null && atlas == null)
{
- UE_LOG(LogPopcornFXRendererMaterial, Warning, TEXT("Asset is not an atlas: '%s'"), ANSI_TO_TCHAR(pkPath.Data()));
+ UE_LOG(LogPopcornFXRendererMaterial, Warning, TEXT("Asset is not an atlas: '%s'"), *ToUE(pkPath));
return null;
}
if (atlas == null)
{
- UE_LOG(LogPopcornFXRendererMaterial, Warning, TEXT("Could not load atlas '%s'"), ANSI_TO_TCHAR(pkPath.Data()));
+ UE_LOG(LogPopcornFXRendererMaterial, Warning, TEXT("Could not load atlas '%s'"), *ToUE(pkPath));
return null;
}
return atlas;
@@ -1693,16 +1693,16 @@ UStaticMesh *LoadMeshPk(const PopcornFX::CString &pkPath)
if (pkPath.Empty())
return null;
- UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(pkPath.Data(), false);
+ UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(pkPath, false);
UStaticMesh *mesh = Cast(obj);
if (obj != null && mesh == null)
{
- UE_LOG(LogPopcornFXRendererMaterial, Warning, TEXT("Asset is not a mesh: '%s'"), ANSI_TO_TCHAR(pkPath.Data()));
+ UE_LOG(LogPopcornFXRendererMaterial, Warning, TEXT("Asset is not a mesh: '%s'"), *ToUE(pkPath));
return null;
}
if (mesh == null)
{
- UE_LOG(LogPopcornFXRendererMaterial, Warning, TEXT("Could not load mesh '%s'"), ANSI_TO_TCHAR(pkPath.Data()));
+ UE_LOG(LogPopcornFXRendererMaterial, Warning, TEXT("Could not load mesh '%s'"), *ToUE(pkPath));
return null;
}
return mesh;
@@ -1715,16 +1715,16 @@ USkeletalMesh *LoadSkelMeshPk(const PopcornFX::CString &pkPath)
if (pkPath.Empty())
return null;
- UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(pkPath.Data(), false);
+ UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(pkPath, false);
USkeletalMesh *mesh = Cast(obj);
if (obj != null && mesh == null)
{
- UE_LOG(LogPopcornFXRendererMaterial, Warning, TEXT("Asset is not a skeletal mesh: '%s'"), ANSI_TO_TCHAR(pkPath.Data()));
+ UE_LOG(LogPopcornFXRendererMaterial, Warning, TEXT("Asset is not a skeletal mesh: '%s'"), *ToUE(pkPath));
return null;
}
if (mesh == null)
{
- UE_LOG(LogPopcornFXRendererMaterial, Warning, TEXT("Could not load skeletal mesh '%s'"), ANSI_TO_TCHAR(pkPath.Data()));
+ UE_LOG(LogPopcornFXRendererMaterial, Warning, TEXT("Could not load skeletal mesh '%s'"), *ToUE(pkPath));
return null;
}
return mesh;
@@ -1734,7 +1734,7 @@ USkeletalMesh *LoadSkelMeshPk(const PopcornFX::CString &pkPath)
void SetMaterialTextureParameter(UMaterialInstanceDynamic *mat, FName textureName, const PopcornFX::CString &pkTexturePath)
{
- mat->SetTextureParameterValue(textureName, LoadTexturePk(pkTexturePath.Data()));
+ mat->SetTextureParameterValue(textureName, LoadTexturePk(pkTexturePath));
}
//----------------------------------------------------------------------------
diff --git a/Source/PopcornFX/Private/Attributes/PopcornFXAttributeFunctions.cpp b/Source/PopcornFX/Private/Attributes/PopcornFXAttributeFunctions.cpp
index 9341ef4..8cd4f4f 100644
--- a/Source/PopcornFX/Private/Attributes/PopcornFXAttributeFunctions.cpp
+++ b/Source/PopcornFX/Private/Attributes/PopcornFXAttributeFunctions.cpp
@@ -112,11 +112,10 @@ namespace
const char *attrType = (dstAttrTraits.ScalarType == PopcornFX::BaseType_Bool ? "Bool" : (dstAttrTraits.IsFp ? "Float" : "Int"));
UE_LOG(LogPopcornFXAttributeFunctions, Warning,
TEXT("SetAttributeAs: the Attribute [%d] \"%s\" cannot be set as %s %d: the attribute is %s %d (%s)"),
- attri, ANSI_TO_TCHAR(decl->ExportedName().Data()),
- ANSI_TO_TCHAR(inType), _Dim,
- ANSI_TO_TCHAR(attrType), dstAttrTraits.VectorDimension,
- *(component->GetPathName())
- );
+ attri, *ToUE(decl->ExportedName()),
+ UTF8_TO_TCHAR(inType), _Dim,
+ UTF8_TO_TCHAR(attrType), dstAttrTraits.VectorDimension,
+ *(component->GetPathName()));
return false;
}
}
@@ -176,11 +175,10 @@ namespace
const char *attrType = (dstAttrTraits.ScalarType == PopcornFX::BaseType_Bool ? "Bool" : (dstAttrTraits.IsFp ? "Float" : "Int"));
UE_LOG(LogPopcornFXAttributeFunctions, Warning,
TEXT("GetAttributeAs: the Attribute [%d] \"%s\" cannot be get as %s %d: the attribute is %s %d (%s)"),
- attri, ANSI_TO_TCHAR(decl->ExportedName().Data()),
- ANSI_TO_TCHAR(inType), _Dim,
- ANSI_TO_TCHAR(attrType), dstAttrTraits.VectorDimension,
- *(component->GetPathName())
- );
+ attri, *ToUE(decl->ExportedName()),
+ UTF8_TO_TCHAR(inType), _Dim,
+ UTF8_TO_TCHAR(attrType), dstAttrTraits.VectorDimension,
+ *(component->GetPathName()));
return false;
}
}
diff --git a/Source/PopcornFX/Private/Attributes/PopcornFXAttributeList.cpp b/Source/PopcornFX/Private/Attributes/PopcornFXAttributeList.cpp
index 0624885..eaca5e6 100644
--- a/Source/PopcornFX/Private/Attributes/PopcornFXAttributeList.cpp
+++ b/Source/PopcornFX/Private/Attributes/PopcornFXAttributeList.cpp
@@ -86,6 +86,8 @@ EPopcornFXAttributeSamplerType::Type ResolveAttribSamplerType(const PopcornFX::C
return EPopcornFXAttributeSamplerType::Shape;
case PopcornFX::SParticleDeclaration::SSampler::Sampler_Image:
return EPopcornFXAttributeSamplerType::Image;
+ case PopcornFX::SParticleDeclaration::SSampler::Sampler_Grid:
+ return EPopcornFXAttributeSamplerType::Grid;
case PopcornFX::SParticleDeclaration::SSampler::Sampler_Text:
return EPopcornFXAttributeSamplerType::Text;
case PopcornFX::SParticleDeclaration::SSampler::Sampler_VectorField:
@@ -109,7 +111,7 @@ void ResetAttribute(FPopcornFXAttributeDesc &attrib, const PopcornFX::CParticleA
{
if (decl != null)
{
- attrib.m_AttributeFName = *FString(ANSI_TO_TCHAR(decl->ExportedName().Data()));
+ attrib.m_AttributeFName = *FString(ToUE(decl->ExportedName()));
attrib.m_AttributeType = decl->ExportedType();
#if WITH_EDITOR
@@ -126,7 +128,7 @@ void ResetAttribute(FPopcornFXAttributeDesc &attrib, const PopcornFX::CParticleA
attrib.m_EnumList.SetNum(decl->EnumList().Count());
for (u32 i = 0; i < decl->EnumList().Count(); ++i)
- attrib.m_EnumList[i] = ANSI_TO_TCHAR(decl->EnumList()[i].Data());
+ attrib.m_EnumList[i] = ToUE(decl->EnumList()[i]);
if ((PopcornFX::EBaseTypeID)attrib.m_AttributeType == PopcornFX::BaseType_Quaternion)
{
@@ -135,7 +137,7 @@ void ResetAttribute(FPopcornFXAttributeDesc &attrib, const PopcornFX::CParticleA
attrib.m_AttributeEulerAngles = FVector(rotator.Roll, rotator.Pitch, rotator.Yaw);
}
#endif // WITH_EDITOR
- attrib.m_AttributeCategoryName = *FString((const UTF16CHAR*)decl->CategoryName().MapDefault().Data());
+ attrib.m_AttributeCategoryName = *ToUE(decl->CategoryName().MapDefault());
if (!attrib.m_AttributeCategoryName.IsValid() || attrib.m_AttributeCategoryName.IsNone())
attrib.m_AttributeCategoryName = "General";
}
@@ -150,10 +152,10 @@ void ResetAttributeSampler(FPopcornFXSamplerDesc &attribSampler, const PopcornFX
{
if (decl != null)
{
- attribSampler.m_SamplerFName = *FString(ANSI_TO_TCHAR(decl->ExportedName().Data()));
+ attribSampler.m_SamplerFName = *FString(ToUE(decl->ExportedName()));
attribSampler.m_SamplerType = ResolveAttribSamplerType(decl);
- attribSampler.m_AttributeCategoryName = *FString((const UTF16CHAR*)decl->CategoryName().MapDefault().Data());
+ attribSampler.m_AttributeCategoryName = *ToUE(decl->CategoryName().MapDefault());
if (!attribSampler.m_AttributeCategoryName.IsValid() || attribSampler.m_AttributeCategoryName.IsNone())
attribSampler.m_AttributeCategoryName = "General";
}
@@ -506,6 +508,7 @@ void UPopcornFXAttributeList::SetupDefault(UPopcornFXEffect *effect, bool force)
{
DBG_HERE();
+
if (!force && IsUpToDate(effect))
{
#if WITH_EDITOR
@@ -519,6 +522,8 @@ void UPopcornFXAttributeList::SetupDefault(UPopcornFXEffect *effect, bool force)
return;
}
+ const uint32 oldAttributesCount = m_Attributes.Num();
+
#if WITH_EDITOR
Modify();
#endif
@@ -552,23 +557,27 @@ void UPopcornFXAttributeList::SetupDefault(UPopcornFXEffect *effect, bool force)
const int32 attrCount = attrs.Count();
const int32 samplerCount = samplers.Count();
-#if WITH_EDITOR
m_Attributes.SetNum(attrCount);
for (int32 attri = 0; attri < attrCount; ++attri)
{
ResetAttribute(m_Attributes[attri], attrs[attri]);
+#if WITH_EDITOR
if (m_Attributes[attri].m_AttributeCategoryName.IsValid() && !m_Attributes[attri].m_AttributeCategoryName.IsNone())
m_Categories.AddUnique(m_Attributes[attri].m_AttributeCategoryName);
+#endif // WITH_EDITOR
}
m_Samplers.SetNum(samplerCount);
for (int32 sampleri = 0; sampleri < samplerCount; ++sampleri)
{
ResetAttributeSampler(m_Samplers[sampleri], samplers[sampleri]);
+#if WITH_EDITOR
if (m_Samplers[sampleri].m_AttributeCategoryName.IsValid() && !m_Samplers[sampleri].m_AttributeCategoryName.IsNone())
m_Categories.AddUnique(m_Samplers[sampleri].m_AttributeCategoryName);
+#endif // WITH_EDITOR
}
+#if WITH_EDITOR
if (attrCount > 0 || samplerCount > 0)
{
// Make "General" the first category if not already
@@ -588,7 +597,8 @@ void UPopcornFXAttributeList::SetupDefault(UPopcornFXEffect *effect, bool force)
const uint32 attribBytes = defContainer->Attributes().CoveredBytes();
m_AttributesRawData.SetNumUninitialized(attribBytes);
- if (attribBytes > 0)
+
+ if (attribBytes > 0 && (oldAttributesCount != attrCount))
PopcornFX::Mem::Copy(m_AttributesRawData.GetData(), defContainer->Attributes().Data(), attribBytes);
PK_ASSERT(CheckDataIntegrity());
@@ -1298,6 +1308,46 @@ void UPopcornFXAttributeList::SetAttributeDim(uint32 attributeId, uint32 d
SetAttribute(attributeId, *reinterpret_cast(&newValue), fromUI); // Ugly cast, so PopcornFXAttributeList.h is a public header to satisfy UE4 nativization bugs. To refactor some day
}
+//----------------------------------------------------------------------------
+
+void UPopcornFXAttributeList::PulseBoolAttributeDim(uint32 attributeId, uint32 dim, bool fromUI/* = false*/)
+{
+ SetAttributeDim(attributeId, dim, true, fromUI);
+ m_HasPendingOneShotReset = true;
+}
+
+//----------------------------------------------------------------------------
+
+void UPopcornFXAttributeList::ResetPulsedBoolAttributesIFN()
+{
+ if (!m_HasPendingOneShotReset) // Early-out most of the time
+ return;
+ m_HasPendingOneShotReset = false;
+
+ if (!m_Owner.IsValid() /*&& m_Owner->IsEmitterStarted()*/) // don't check if the emitter is started, even if stopped as long as particles are still here we want this logic to run
+ return;
+ PopcornFX::CParticleEffectInstance *effectInstance = m_Owner->_GetEffectInstance();
+ if (effectInstance == null)
+ return;
+
+ for (int32 i = 0; i < m_Attributes.Num(); i++)
+ {
+ const PopcornFX::CParticleAttributeDeclaration *decl = effectInstance->GetAttributeDecl(i);
+ if (decl != null && decl->OneShotTrigger())
+ {
+ const PopcornFX::EBaseTypeID typeID = PopcornFX::EBaseTypeID(decl->ExportedType());
+ if (PK_VERIFY(PopcornFX::CBaseTypeTraits::Traits(typeID).ScalarType == PopcornFX::BaseType_Bool)) // OneShotTrigger but not a 'bool' type ?
+ {
+ // Do not call 'UPopcornFXAttributeList::SetAttribute()', we don't want the 'RestartEmitter' logic at all here !
+ FPopcornFXAttributeValue newValue = { 0, 0, 0, 0 };
+ const PopcornFX::SAttributesContainer_SAttrib &_value = *reinterpret_cast(&newValue); // FIXME: We don't actually care about FPopcornFXAttributeValue, add a way to ctor a new SAttrib in one line
+ PK_VERIFY(effectInstance->SetRawAttribute(i, typeID, &_value, true));
+ AttributeRawDataAttributes(this)[i] = _value;
+ }
+ }
+ }
+}
+
#endif // WITH_EDITOR
//----------------------------------------------------------------------------
@@ -1392,7 +1442,7 @@ void UPopcornFXAttributeList::_RefreshAttributeSamplers(UPopcornFXEmitterCompone
if (desc.SamplerType() == EPopcornFXAttributeSamplerType::None)
{
- effectInstance->SetAttributeSampler(TCHAR_TO_ANSI(*desc.SamplerName()), null);
+ effectInstance->SetAttributeSampler(TCHAR_TO_UTF8(*desc.SamplerName()), null);
continue;
}
@@ -1401,7 +1451,7 @@ void UPopcornFXAttributeList::_RefreshAttributeSamplers(UPopcornFXEmitterCompone
if (attribSampler == null ||
!PK_VERIFY(desc.SamplerType() == attribSampler->SamplerType()))
{
- effectInstance->SetAttributeSampler(TCHAR_TO_ANSI(*desc.SamplerName()), null);
+ effectInstance->SetAttributeSampler(TCHAR_TO_UTF8(*desc.SamplerName()), null);
continue;
}
@@ -1411,7 +1461,7 @@ void UPopcornFXAttributeList::_RefreshAttributeSamplers(UPopcornFXEmitterCompone
if (!IsRunningCommandlet() && attribSampler != null)
samplerDescriptor = attribSampler->_AttribSampler_SetupSamplerDescriptor(desc, defaultSampler.Get());
- effectInstance->SetAttributeSampler(TCHAR_TO_ANSI(*desc.SamplerName()), samplerDescriptor != null ? samplerDescriptor : null);
+ effectInstance->SetAttributeSampler(TCHAR_TO_UTF8(*desc.SamplerName()), samplerDescriptor != null ? samplerDescriptor : null);
}
}
diff --git a/Source/PopcornFX/Private/Attributes/PopcornFXAttributeSamplerSkinnedMesh.cpp b/Source/PopcornFX/Private/Attributes/PopcornFXAttributeSamplerSkinnedMesh.cpp
index 09728f2..1fb0c8f 100644
--- a/Source/PopcornFX/Private/Attributes/PopcornFXAttributeSamplerSkinnedMesh.cpp
+++ b/Source/PopcornFX/Private/Attributes/PopcornFXAttributeSamplerSkinnedMesh.cpp
@@ -211,7 +211,7 @@ void UPopcornFXAttributeSamplerSkinnedMesh::Clear()
m_Data->m_SkinContext.m_SrcPositions = TStridedMemoryView();
m_Data->m_SkinContext.m_SrcNormals = TStridedMemoryView();
- m_Data->m_SkinContext.m_SrcTangents = TStridedMemoryView();
+ m_Data->m_SkinContext.m_SrcTangents = TStridedMemoryView();
m_Data->m_SkinContext.m_DstPositions = TStridedMemoryView();
m_Data->m_SkinContext.m_DstNormals = TStridedMemoryView();
@@ -313,7 +313,8 @@ void UPopcornFXAttributeSamplerSkinnedMesh::Skin_Finish(const PopcornFX::SSkinCo
// Rebuild sampling structures if bone visibility array has changed
if (!m_Data->m_BoneVisibilityChanged)
return;
- if (!PK_VERIFY(bSkinPositions))
+
+ if (!bSkinPositions)
{
// @TODO : warn the user that distribution will be invalid if he only checked bSkinNormals or bSkinTangents
// and he either is sampling a destructible mesh or the target skinned mesh component got one of its bone hidden/unhidden
@@ -710,16 +711,16 @@ namespace
_IndexType * __restrict boneIndices = reinterpret_cast<_IndexType*>(data->m_BoneIndices.RawDataPointer());
- const bool skin = (buildDesc.m_BuildFlags & (Build_Positions | Build_Tangents | Build_Normals)) != 0;
+ const bool skin = (buildDesc.m_BuildFlags & (Build_Positions | Build_Normals | Build_Tangents)) != 0;
if (skin)
{
PK_NAMEDSCOPEDPROFILE_C("AttributeSamplerSkinnedMesh::Copy src positions/normals/tangents", POPCORNFX_UE_PROFILER_COLOR);
- PK_ASSERT(srcPositionsView.Stride() == data->m_DstPositions.Stride());
if (buildDesc.m_BuildFlags & Build_Positions)
{
if (!PK_VERIFY(srcPositionsView.Count() == data->m_DstPositions.Count()))
return false;
+ PK_ASSERT(srcPositionsView.Stride() == data->m_DstPositions.Stride());
data->m_SkinContext.m_SrcPositions = srcPositionsView;
PopcornFX::Mem::Copy(data->m_DstPositions.RawDataPointer(), srcPositionsView.Data(), sizeof(CFloat4) * srcPositionsView.Count());
}
@@ -734,7 +735,7 @@ namespace
}
if (buildDesc.m_BuildFlags & Build_Tangents)
{
- const TStridedMemoryView srcTangentsView = TStridedMemoryView::Reinterpret(vstream.Tangents());
+ const TStridedMemoryView srcTangentsView = vstream.Tangents();
if (!PK_VERIFY(srcTangentsView.Count() == data->m_DstTangents.Count()))
return false;
PK_ASSERT(srcTangentsView.Stride() == data->m_DstTangents.Stride());
diff --git a/Source/PopcornFX/Private/Attributes/PopcornFXAttributeSamplers.cpp b/Source/PopcornFX/Private/Attributes/PopcornFXAttributeSamplers.cpp
index 1e20f65..8a9fff3 100644
--- a/Source/PopcornFX/Private/Attributes/PopcornFXAttributeSamplers.cpp
+++ b/Source/PopcornFX/Private/Attributes/PopcornFXAttributeSamplers.cpp
@@ -13,6 +13,7 @@
#include "PopcornFXAttributeSamplerShape.h"
#include "PopcornFXAttributeSamplerSkinnedMesh.h"
#include "PopcornFXAttributeSamplerImage.h"
+#include "PopcornFXAttributeSamplerGrid.h"
#include "PopcornFXAttributeSamplerText.h"
#include "PopcornFXAttributeSamplerCurve.h"
#include "PopcornFXAttributeSamplerCurveDynamic.h"
@@ -22,6 +23,7 @@
#include "Assets/PopcornFXMesh.h"
#include "Assets/PopcornFXTextureAtlas.h"
#include "Internal/ResourceHandlerImage_UE.h"
+#include "Platforms/PopcornFXPlatform.h"
#include "Components/SplineComponent.h"
#include "Components/BillboardComponent.h"
@@ -33,6 +35,10 @@
#include "VectorField/VectorFieldStatic.h"
#include "Serialization/BulkData.h"
#include "Curves/RichCurve.h"
+#include "Engine/VolumeTexture.h"
+#include "Materials/MaterialInstanceDynamic.h"
+#include "Engine/TextureRenderTarget2D.h"
+#include "Engine/TextureRenderTargetVolume.h"
#include "Engine/Texture.h"
#include "Engine/Texture2D.h"
#include "UObject/Package.h"
@@ -62,6 +68,7 @@
#if (PK_GPU_D3D12 != 0)
# include
# include
+
# include "Windows/HideWindowsPlatformTypes.h"
# include "D3D12RHIPrivate.h"
# include "D3D12Util.h"
@@ -97,7 +104,6 @@ APopcornFXAttributeSamplerActor::APopcornFXAttributeSamplerActor(const FObjectIn
{}
};
static FConstructorStatics ConstructorStatics;
- // SpriteComponent->RelativeScale3D = FVector(0.5f, 0.5f, 0.5f);
SpriteComponent->SetRelativeScale3D(FVector(1.5f));
SpriteComponent->bHiddenInGame = true;
@@ -153,6 +159,12 @@ APopcornFXAttributeSamplerImageActor::APopcornFXAttributeSamplerImageActor(const
_CtorRootSamplerComponent(PCIP, EPopcornFXAttributeSamplerComponentType::Image);
}
+APopcornFXAttributeSamplerGridActor::APopcornFXAttributeSamplerGridActor(const FObjectInitializer &PCIP)
+: Super(PCIP)
+{
+ _CtorRootSamplerComponent(PCIP, EPopcornFXAttributeSamplerComponentType::Grid);
+}
+
APopcornFXAttributeSamplerCurveActor::APopcornFXAttributeSamplerCurveActor(const FObjectInitializer &PCIP)
: Super(PCIP)
{
@@ -204,6 +216,9 @@ void APopcornFXAttributeSamplerActor::ReloadSprite()
case EPopcornFXAttributeSamplerComponentType::Image:
spriteName = "AttributeSampler_Image";
break;
+ case EPopcornFXAttributeSamplerComponentType::Grid:
+ spriteName = "AttributeSampler_Image"; //"AttributeSampler_Grid"; // TODO: Grid icon
+ break;
case EPopcornFXAttributeSamplerComponentType::AnimTrack:
spriteName = "Attributesampler_AnimTrack";
break;
@@ -271,7 +286,7 @@ void APopcornFXAttributeSamplerActor::PostRegisterAllComponents()
//----------------------------------------------------------------------------
-void APopcornFXAttributeSamplerActor::PostLoad()
+void APopcornFXAttributeSamplerActor::PostLoad()
{
Super::PostLoad();
#if WITH_EDITOR
@@ -286,7 +301,7 @@ void APopcornFXAttributeSamplerActor::PostLoad()
//----------------------------------------------------------------------------
-void APopcornFXAttributeSamplerActor::PostActorCreated()
+void APopcornFXAttributeSamplerActor::PostActorCreated()
{
Super::PostActorCreated();
#if WITH_EDITOR
@@ -301,7 +316,7 @@ void APopcornFXAttributeSamplerActor::PostActorCreated()
//----------------------------------------------------------------------------
// static
-UClass *UPopcornFXAttributeSampler::SamplerComponentClass(EPopcornFXAttributeSamplerComponentType::Type type)
+UClass *UPopcornFXAttributeSampler::SamplerComponentClass(EPopcornFXAttributeSamplerComponentType::Type type)
{
switch (type)
{
@@ -311,6 +326,8 @@ UClass *UPopcornFXAttributeSampler::SamplerComponentClass(EPopcornFXAttributeSa
return UPopcornFXAttributeSamplerSkinnedMesh::StaticClass();
case EPopcornFXAttributeSamplerComponentType::Image:
return UPopcornFXAttributeSamplerImage::StaticClass();
+ case EPopcornFXAttributeSamplerComponentType::Grid:
+ return UPopcornFXAttributeSamplerGrid::StaticClass();
case EPopcornFXAttributeSamplerComponentType::Curve:
return UPopcornFXAttributeSamplerCurve::StaticClass();
case EPopcornFXAttributeSamplerComponentType::AnimTrack:
@@ -1976,7 +1993,7 @@ PopcornFX::CParticleSamplerDescriptor *UPopcornFXAttributeSamplerText::_AttribSa
// @TODO kerning
PopcornFX::CFontMetrics *fontMetrics = null;
bool useKerning = false;
- if (!PK_VERIFY(m_Data->m_Desc->_Setup(TCHAR_TO_ANSI(*Text), fontMetrics, useKerning)))
+ if (!PK_VERIFY(m_Data->m_Desc->_Setup(ToPk(Text), fontMetrics, useKerning)))
return null;
m_Data->m_NeedsReload = false;
}
@@ -2069,13 +2086,10 @@ void UPopcornFXAttributeSamplerImage::OnUnregister()
{
if (m_Data != null)
{
-#if (PK_GPU_D3D12 != 0)//(PK_HAS_GPU != 0)
// Unregister the component during OnUnregister instead of BeginDestroy.
// In editor mode, BeginDestroy is only called when saving a level:
// Components ReregisterComponent() do not have a matching BeginDestroy call in editor
- if (m_Data->m_Desc != null)
- m_Data->m_Desc = null;
-#endif // (PK_HAS_GPU != 0)
+ m_Data->m_Desc = null;
}
Super::OnUnregister();
}
@@ -2113,9 +2127,9 @@ void UPopcornFXAttributeSamplerImage::PostEditChangeProperty(FPropertyChangedEve
m_Data->m_ReloadTextureAtlas = true;
m_Data->m_RebuildPDF = true;
}
- else if (propertyName == GET_MEMBER_NAME_STRING_CHECKED(UPopcornFXAttributeSamplerImage, SamplingMode) ||
- propertyName == GET_MEMBER_NAME_STRING_CHECKED(UPopcornFXAttributeSamplerImage, DensitySource) ||
- propertyName == GET_MEMBER_NAME_STRING_CHECKED(UPopcornFXAttributeSamplerImage, DensityPower))
+ else if ( propertyName == GET_MEMBER_NAME_STRING_CHECKED(UPopcornFXAttributeSamplerImage, SamplingMode) ||
+ propertyName == GET_MEMBER_NAME_STRING_CHECKED(UPopcornFXAttributeSamplerImage, DensitySource) ||
+ propertyName == GET_MEMBER_NAME_STRING_CHECKED(UPopcornFXAttributeSamplerImage, DensityPower))
{
m_Data->m_RebuildPDF = true;
}
@@ -2172,7 +2186,7 @@ bool UPopcornFXAttributeSamplerImage::_RebuildImageSampler()
const bool rebuildImage = m_Data->m_ReloadTexture;
if (rebuildImage)
{
- const PopcornFX::CString fullPath = TCHAR_TO_ANSI(*Texture->GetPathName());
+ const PopcornFX::CString fullPath = ToPk(Texture->GetPathName());
bool success = false;
m_Data->m_TextureResource = PopcornFX::Resource::DefaultManager()->Load(fullPath, true);
success |= (m_Data->m_TextureResource != null && !m_Data->m_TextureResource->Empty());
@@ -2196,7 +2210,7 @@ bool UPopcornFXAttributeSamplerImage::_RebuildImageSampler()
if (!success) // Couldn't load any of the resources (CPU/GPU)
{
- UE_LOG(LogPopcornFXAttributeSampler, Warning, TEXT("AttrSamplerImage: couldn't load texture '%s' for CPU/GPU sim sampling"), fullPath.Data());
+ UE_LOG(LogPopcornFXAttributeSampler, Warning, TEXT("AttrSamplerImage: couldn't load texture '%s' for CPU/GPU sim sampling"), *ToUE(fullPath));
return false;
}
m_Data->m_ReloadTexture = false;
@@ -2207,7 +2221,7 @@ bool UPopcornFXAttributeSamplerImage::_RebuildImageSampler()
if (TextureAtlas != null)
{
bool success = false;
- const PopcornFX::CString fullPath = TCHAR_TO_ANSI(*TextureAtlas->GetPathName());
+ const PopcornFX::CString fullPath = ToPk(TextureAtlas->GetPathName());
m_Data->m_TextureAtlasResource = PopcornFX::Resource::DefaultManager()->Load(fullPath, true);
success |= (m_Data->m_TextureAtlasResource != null && !m_Data->m_TextureAtlasResource->Empty());
@@ -2223,7 +2237,7 @@ bool UPopcornFXAttributeSamplerImage::_RebuildImageSampler()
if (!success) // Couldn't load any of the resources (CPU/GPU)
{
- UE_LOG(LogPopcornFXAttributeSampler, Warning, TEXT("AttrSamplerImage: couldn't load texture atlas '%s' for CPU/GPU sim sampling"), fullPath.Data());
+ UE_LOG(LogPopcornFXAttributeSampler, Warning, TEXT("AttrSamplerImage: couldn't load texture atlas '%s' for CPU/GPU sim sampling"), *ToUE(fullPath));
return false;
}
}
@@ -2368,8 +2382,8 @@ bool UPopcornFXAttributeSamplerImage::_BuildRegularImage(PopcornFX::CImageSurfac
UE_LOG(LogPopcornFXAttributeSampler, Log,
TEXT("AttrSamplerImage: texture '%s' format %s not supported for sampling, converting to %s (because AllowTextureConvertionAtRuntime) in '%s'"),
*Texture->GetName(),
- ANSI_TO_TCHAR(PopcornFX::CImage::GetFormatName(m_Data->m_TextureResource->m_Format)),
- ANSI_TO_TCHAR(PopcornFX::CImage::GetFormatName(dstFormat)),
+ UTF8_TO_TCHAR(PopcornFX::CImage::GetFormatName(m_Data->m_TextureResource->m_Format)),
+ UTF8_TO_TCHAR(PopcornFX::CImage::GetFormatName(dstFormat)),
*GetPathName());
PopcornFX::CImageSurface newSurface;
@@ -2379,8 +2393,8 @@ bool UPopcornFXAttributeSamplerImage::_BuildRegularImage(PopcornFX::CImageSurfac
UE_LOG(LogPopcornFXAttributeSampler, Warning,
TEXT("AttrSamplerImage: could not convert texture '%s' from %s to %s in %s"),
*Texture->GetName(),
- ANSI_TO_TCHAR(PopcornFX::CImage::GetFormatName(m_Data->m_TextureResource->m_Format)),
- ANSI_TO_TCHAR(PopcornFX::CImage::GetFormatName(dstFormat)),
+ UTF8_TO_TCHAR(PopcornFX::CImage::GetFormatName(m_Data->m_TextureResource->m_Format)),
+ UTF8_TO_TCHAR(PopcornFX::CImage::GetFormatName(dstFormat)),
*GetPathName());
return false;
}
@@ -2394,7 +2408,7 @@ bool UPopcornFXAttributeSamplerImage::_BuildRegularImage(PopcornFX::CImageSurfac
UE_LOG(LogPopcornFXAttributeSampler, Warning,
TEXT("AttrSamplerImage: texture '%s' format %s not supported for sampling (and AllowTextureConvertionAtRuntime not enabled) in %s"),
*Texture->GetName(),
- ANSI_TO_TCHAR(PopcornFX::CImage::GetFormatName(m_Data->m_TextureResource->m_Format)),
+ UTF8_TO_TCHAR(PopcornFX::CImage::GetFormatName(m_Data->m_TextureResource->m_Format)),
*GetPathName());
return false;
}
@@ -2402,6 +2416,424 @@ bool UPopcornFXAttributeSamplerImage::_BuildRegularImage(PopcornFX::CImageSurfac
return true;
}
+//----------------------------------------------------------------------------
+//
+// UPopcornFXAttributeSamplerGrid
+//
+//----------------------------------------------------------------------------
+
+struct FAttributeSamplerGridData
+{
+ bool m_ReloadGrid = true;
+ PopcornFX::PParticleSamplerDescriptor_Grid_Default m_Desc;
+
+ void Clear()
+ {
+ m_Desc = null;
+ m_ReloadGrid = true;
+ }
+
+ FAttributeSamplerGridData() { }
+
+ ~FAttributeSamplerGridData()
+ {
+ }
+};
+
+//----------------------------------------------------------------------------
+
+void UPopcornFXAttributeSamplerGrid::SetRenderTarget(class UTextureRenderTarget *InRenderTarget)
+{
+ RenderTarget = InRenderTarget;
+}
+
+//----------------------------------------------------------------------------
+
+void UPopcornFXAttributeSamplerGrid::SetAsMaterialTextureParameter(UMaterialInstanceDynamic *Material, FName ParameterName)
+{
+ if (Material == null)
+ {
+ UE_LOG(LogPopcornFXAttributeSampler, Warning, TEXT("SetAsMaterialTextureParameter: couldn't set grid as material texture parameter: null material"));
+ return;
+ }
+ UTexture *texture = GridTexture();
+ if (texture == null)
+ {
+ UE_LOG(LogPopcornFXAttributeSampler, Warning, TEXT("SetAsMaterialTextureParameter: couldn't set grid as material texture parameter: empty grid texture"));
+ return;
+ }
+ Material->SetTextureParameterValue(ParameterName, texture);
+}
+
+//----------------------------------------------------------------------------
+
+UPopcornFXAttributeSamplerGrid::UPopcornFXAttributeSamplerGrid(const FObjectInitializer &PCIP)
+: Super(PCIP)
+{
+ bAutoActivate = true;
+
+ RenderTarget = null;
+ bAssetGrid = false;
+
+ bSRGB = false;
+
+ SizeX = 128;
+ SizeY = 128;
+ SizeZ = 1;
+
+ DataType = EPopcornFXGridDataType::RGBA;
+
+ // UPopcornFXAttributeSampler override:
+ m_SamplerType = EPopcornFXAttributeSamplerType::Grid;
+
+ m_Data = new FAttributeSamplerGridData();
+ check(m_Data != null);
+}
+
+//----------------------------------------------------------------------------
+
+void UPopcornFXAttributeSamplerGrid::OnUnregister()
+{
+ if (m_Data != null)
+ {
+ // Unregister the component during OnUnregister instead of BeginDestroy.
+ // In editor mode, BeginDestroy is only called when saving a level:
+ // Components ReregisterComponent() do not have a matching BeginDestroy call in editor
+ m_Data->m_Desc = null;
+ m_Data->m_ReloadGrid = true;
+ }
+ Super::OnUnregister();
+}
+
+//----------------------------------------------------------------------------
+
+void UPopcornFXAttributeSamplerGrid::BeginDestroy()
+{
+ if (m_Data != null)
+ {
+ delete m_Data;
+ m_Data = null;
+ }
+ Super::BeginDestroy();
+}
+
+//----------------------------------------------------------------------------
+
+UTexture *UPopcornFXAttributeSamplerGrid::GridTexture()
+{
+ return bAssetGrid != 0 ? RenderTarget : m_GridTexture;
+}
+
+//----------------------------------------------------------------------------
+
+#if WITH_EDITOR
+
+void UPopcornFXAttributeSamplerGrid::PostEditChangeProperty(FPropertyChangedEvent &propertyChangedEvent)
+{
+ if (propertyChangedEvent.Property != NULL)
+ {
+ const FString propertyName = propertyChangedEvent.Property->GetName();
+
+ if (propertyName == GET_MEMBER_NAME_STRING_CHECKED(UPopcornFXAttributeSamplerGrid, bAssetGrid) ||
+ propertyName == GET_MEMBER_NAME_STRING_CHECKED(UPopcornFXAttributeSamplerGrid, bSRGB) ||
+ propertyName == GET_MEMBER_NAME_STRING_CHECKED(UPopcornFXAttributeSamplerGrid, RenderTarget) ||
+ propertyName == GET_MEMBER_NAME_STRING_CHECKED(UPopcornFXAttributeSamplerGrid, SizeX) ||
+ propertyName == GET_MEMBER_NAME_STRING_CHECKED(UPopcornFXAttributeSamplerGrid, SizeY) ||
+ propertyName == GET_MEMBER_NAME_STRING_CHECKED(UPopcornFXAttributeSamplerGrid, SizeZ) ||
+ propertyName == GET_MEMBER_NAME_STRING_CHECKED(UPopcornFXAttributeSamplerGrid, DataType))
+ {
+ // Rebuild
+ m_Data->m_ReloadGrid = true;
+ }
+ }
+ Super::PostEditChangeProperty(propertyChangedEvent);
+}
+
+#endif // WITH_EDITOR
+
+//----------------------------------------------------------------------------
+
+PopcornFX::CParticleSamplerDescriptor *UPopcornFXAttributeSamplerGrid::_AttribSampler_SetupSamplerDescriptor(FPopcornFXSamplerDesc &desc, const PopcornFX::CResourceDescriptor *defaultSampler)
+{
+ LLM_SCOPE(ELLMTag::Particles);
+ const PopcornFX::CResourceDescriptor_Grid *defaultGridSampler = PopcornFX::HBO::Cast(defaultSampler);
+ if (!PK_VERIFY(defaultGridSampler != null))
+ return null;
+ if (m_Data->m_ReloadGrid)
+ {
+ if (!RebuildGridSampler())
+ return null;
+ m_Data->m_ReloadGrid = false;
+ }
+
+ // Make sure the sampler matches what the effect expects
+ const u32 gridOrder = Cast(GridTexture()) != null ? 2 : 3;
+ const PopcornFX::Nodegraph::SDataTypeTraits &srcTypeTraits = PopcornFX::Nodegraph::SDataTypeTraits::Traits((PopcornFX::Nodegraph::EDataType)defaultGridSampler->Type());
+ if (defaultGridSampler->Order() != gridOrder ||
+ srcTypeTraits.BaseType() != m_Data->m_Desc->m_DataType)
+ {
+ UE_LOG(LogPopcornFXAttributeSampler, Warning,
+ TEXT("AttrSamplerGrid: Failed to setup grid attribute sampler, does not match with sampler defined in source effect '%s':\n"
+ "\t- SrcOrder=%d, Built=%d.\n"
+ "\t- SrcType=%s, Built=%s.\n"),
+ *ToUE(defaultGridSampler->FilePath()),
+ defaultGridSampler->Order(), gridOrder,
+ UTF8_TO_TCHAR(srcTypeTraits.Name()),
+ UTF8_TO_TCHAR(PopcornFX::CBaseTypeTraits::Traits(m_Data->m_Desc->m_DataType).Name));
+ m_Data->Clear();
+ return null;
+ }
+
+ return m_Data->m_Desc.Get();
+}
+
+//----------------------------------------------------------------------------
+
+bool UPopcornFXAttributeSamplerGrid::RebuildGridSampler()
+{
+ if (!_RebuildGridSampler())
+ {
+ const FString imageName = RenderTarget != null ? RenderTarget->GetName() : FString(TEXT("null"));
+ UE_LOG(LogPopcornFXAttributeSampler, Warning,
+ TEXT("AttrSamplerGrid: Failed to setup grid attribute sampler (RenderTarget=%s, Dimensions=(%d,%d,%d), DataType=%d"),
+ *imageName,
+ SizeX, SizeY, SizeZ,
+ DataType);
+ m_Data->Clear();
+ return false;
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+
+bool UPopcornFXAttributeSamplerGrid::_RebuildGridSampler()
+{
+ PK_NAMEDSCOPEDPROFILE_C("UPopcornFXAttributeSamplerGrid::Build grid sampler", POPCORNFX_UE_PROFILER_COLOR);
+
+ PopcornFX::PParticleSamplerDescriptor_Grid_Default descriptor = PK_NEW(PopcornFX::CParticleSamplerDescriptor_Grid_Default);
+ if (!PK_VERIFY(descriptor != null))
+ return false;
+
+ bool needsGPUHandle = false;
+#if (PK_GPU_D3D12 != 0)
+ needsGPUHandle = g_PopcornFXRHIAPI == SUERenderContext::D3D12;
+#endif
+
+ EPixelFormat pixelFormat = PF_Unknown;
+ bool isVolumeTexture = false;
+
+ m_GridTexture = null;
+
+ UTexture *texture = null;
+ if (bAssetGrid)
+ {
+ if (RenderTarget == null)
+ {
+ UE_LOG(LogPopcornFXAttributeSampler, Warning, TEXT("UPopcornFXAttributeSamplerGrid: couldn't build grid sampler: null texture"));
+ return false;
+ }
+ texture = RenderTarget;
+
+ UTextureRenderTarget2D *RT2D = Cast(texture);
+ UTextureRenderTargetVolume *RTVolume = Cast(texture);
+ if (RT2D != null)
+ {
+ const EPixelFormat RTFormat = GetPixelFormatFromRenderTargetFormat(RT2D->RenderTargetFormat);
+ const bool hasSupportedFormat = RTFormat == PF_R32_FLOAT ||
+ RTFormat == PF_G32R32F ||
+ RTFormat == PF_A32B32G32R32F;
+ const bool hasCorrectGamma = bSRGB == RT2D->IsSRGB();
+
+ if (!hasSupportedFormat)
+ {
+ // Error, don't try to convert the texture, let the user specify the desired format.
+ UE_LOG(LogPopcornFXAttributeSampler, Warning, TEXT("UPopcornFXAttributeSamplerGrid: can only setup attribute sampler from UTextureRenderTarget2D with format set to RTF_R32f, RTF_RG32f or RTF_RGBA32f"));
+ return false;
+ }
+ if (!hasCorrectGamma)
+ {
+ UE_LOG(LogPopcornFXAttributeSampler, Log, TEXT("UPopcornFXAttributeSamplerGrid: converting UTextureRenderTarget2D format to sRGB=%d"), bSRGB);
+ }
+ if ((!RT2D->bCanCreateUAV || !hasCorrectGamma) && needsGPUHandle)
+ {
+ RT2D->bCanCreateUAV = true;
+ RT2D->SRGB = bSRGB;
+ RT2D->UpdateResource();
+ }
+
+ PopcornFX::EBaseTypeID dataType;
+ switch (RTFormat)
+ {
+ case PF_R32_FLOAT:
+ dataType = PopcornFX::BaseType_Float;
+ break;
+ case PF_G32R32F:
+ dataType = PopcornFX::BaseType_Float2;
+ break;
+ case PF_A32B32G32R32F:
+ default:
+ dataType = PopcornFX::BaseType_Float4;
+ break;
+ };
+ descriptor->m_DataType = dataType;
+ descriptor->m_GridDimensions = CUint4(RT2D->SizeX, RT2D->SizeY, 1, 1);
+ pixelFormat = RTFormat;
+ }
+ else if (RTVolume != null)
+ {
+ const EPixelFormat RTFormat = RTVolume->OverrideFormat;
+ const bool hasSupportedFormat = RTFormat == PF_A32B32G32R32F;
+ const bool hasCorrectGamma = bSRGB == RTVolume->SRGB;
+
+ if (!hasSupportedFormat)
+ {
+ UE_LOG(LogPopcornFXAttributeSampler, Log, TEXT("UPopcornFXAttributeSamplerGrid: converting UTextureRenderTargetVolume format to RTF_RGBA32f"));
+ }
+ if (!hasCorrectGamma)
+ {
+ UE_LOG(LogPopcornFXAttributeSampler, Log, TEXT("UPopcornFXAttributeSamplerGrid: converting UTextureRenderTargetVolume format to sRGB=%d"), bSRGB);
+ }
+ if ((!RTVolume->bCanCreateUAV || !hasSupportedFormat || !hasCorrectGamma) || needsGPUHandle)
+ {
+ RTVolume->bCanCreateUAV = true;
+ RTVolume->OverrideFormat = PF_A32B32G32R32F;
+ RTVolume->SRGB = bSRGB;
+ RTVolume->UpdateResource();
+ }
+ descriptor->m_DataType = PopcornFX::BaseType_Float4;
+ descriptor->m_GridDimensions = CUint4(RTVolume->SizeX, RTVolume->SizeY, RTVolume->SizeZ, 1);
+ isVolumeTexture = true;
+ pixelFormat = PF_A32B32G32R32F;
+ }
+ else
+ {
+ UE_LOG(LogPopcornFXAttributeSampler, Warning, TEXT("UPopcornFXAttributeSamplerGrid: can only setup attribute sampler from UTextureRenderTarget2D or UTextureRenderTargetVolume"));
+ return false;
+ }
+ }
+ else
+ {
+ if (SizeX < 0 || SizeY < 0 || SizeZ < 0)
+ {
+ UE_LOG(LogPopcornFXAttributeSampler, Warning, TEXT("UPopcornFXAttributeSamplerGrid: couldn't build grid sampler: Invalid dimensions (%d,%d,%d)"), SizeX, SizeY, SizeZ);
+ return false;
+ }
+ ETextureRenderTargetFormat RTFormat = ETextureRenderTargetFormat::RTF_RGBA32f;
+ PopcornFX::EBaseTypeID dataType = PopcornFX::BaseType_Void;
+
+ switch (DataType)
+ {
+ case EPopcornFXGridDataType::R:
+ RTFormat = RTF_R32f;
+ dataType = PopcornFX::BaseType_Float;
+ break;
+ case EPopcornFXGridDataType::RG:
+ RTFormat = RTF_RG32f;
+ dataType = PopcornFX::BaseType_Float2;
+ break;
+ case EPopcornFXGridDataType::RGBA:
+ RTFormat = RTF_RGBA32f;
+ dataType = PopcornFX::BaseType_Float4;
+ break;
+ default:
+ PK_ASSERT_NOT_REACHED();
+ return false;
+ };
+ pixelFormat = GetPixelFormatFromRenderTargetFormat(RTFormat);
+
+ if (needsGPUHandle)
+ {
+ if (SizeZ > 1)
+ {
+ UTextureRenderTargetVolume *newTexture = NewObject(GetTransientPackage(), TEXT("PopcornFX Grid Attribute Sampler Volume"), RF_Transient);
+ check(newTexture != null);
+ newTexture->bCanCreateUAV = true;
+ newTexture->SRGB = bSRGB;
+ newTexture->Init(SizeX, SizeY, SizeZ, pixelFormat);
+ newTexture->UpdateResourceImmediate(true);
+ texture = newTexture;
+ isVolumeTexture = true;
+ }
+ else
+ {
+ UTextureRenderTarget2D *newTexture = NewObject(GetTransientPackage(), TEXT("PopcornFX Grid Attribute Sampler 2D"), RF_Transient);
+ check(newTexture != null);
+ newTexture->RenderTargetFormat = RTFormat;
+ newTexture->bAutoGenerateMips = false;
+ newTexture->bCanCreateUAV = true;
+ newTexture->SRGB = bSRGB;
+ newTexture->InitAutoFormat(SizeX, SizeY);
+ newTexture->UpdateResourceImmediate(true);
+ texture = newTexture;
+ }
+ if (texture == null)
+ {
+ UE_LOG(LogPopcornFXAttributeSampler, Warning, TEXT("UPopcornFXAttributeSamplerGrid: couldn't build grid sampler: couldn't create transient texture"));
+ return false;
+ }
+ m_GridTexture = texture;
+ }
+ descriptor->m_DataType = dataType;
+ descriptor->m_GridDimensions = CUint4(SizeX, SizeY, SizeZ, 1);
+ }
+
+ if (needsGPUHandle)
+ {
+ check(texture != null);
+
+ // WIP: Flush render commands to make sure the RHI resource is available.
+ FlushRenderingCommands();
+ }
+
+#if (PK_GPU_D3D12 != 0)
+ // There is no way currently to know if the current sampler descriptor will be used by the CPU or GPU sim, so we'll have to load both, if possible
+ // GPU sim image load is trivial: it will just grab the ref to the native resource
+ if (g_PopcornFXRHIAPI == SUERenderContext::D3D12)
+ {
+ // Simplified CResourceHandlerImage_UE_D3D12::NewFromTexture()
+ FTextureReferenceRHIRef texRef = texture->TextureReference.TextureReferenceRHI;
+ if (!IsValidRef(texRef))
+ {
+ UE_LOG(LogPopcornFXAttributeSampler, Warning, TEXT("UPopcornFXAttributeSamplerGrid: UTexture TextureReference not available \"%s\""), *texture->GetPathName());
+ return false;
+ }
+ FRHITexture *texRHI = texRef->GetReferencedTexture();
+ if (texRHI == null)
+ {
+ UE_LOG(LogPopcornFXAttributeSampler, Warning, TEXT("UPopcornFXAttributeSamplerGrid: UTexture TextureReference FRHITexture not available \"%s\""), *texture->GetPathName());
+ return false;
+ }
+ ID3D12Resource *gpuTexture = static_cast(texRHI->GetNativeResource());
+ if (gpuTexture == null)
+ {
+ UE_LOG(LogPopcornFXAttributeSampler, Warning, TEXT("UPopcornFXAttributeSamplerGrid: UTexture TextureReference FRHITexture D3D12 not available \"%s\""), *texture->GetPathName());
+ return false;
+ }
+
+ descriptor->SetupD3D12Resources(gpuTexture,
+ (u32)GPixelFormats[pixelFormat].PlatformFormat,
+ (u32)(isVolumeTexture ? D3D12_UAV_DIMENSION_TEXTURE3D : D3D12_UAV_DIMENSION_TEXTURE2D));
+ }
+#endif // PK_GPU_D3D12 != 0
+
+ // Build a CPU sim visible memory buffer (we could expose RW access functions into it)
+ {
+ const PopcornFX::CImage::EFormat pkFormat = _UE2PKImageFormat(pixelFormat, false);
+ PK_ASSERT(pkFormat != PopcornFX::CImage::Format_Invalid);
+ const u32 expectedSizeInBytes = PopcornFX::CImage::GetFormatPixelBufferSizeInBytes(pkFormat, CUint3(SizeX, SizeY, SizeZ));
+
+ enum { kAlignment = 0x80 };
+ descriptor->m_RawDataRef = PopcornFX::CRefCountedMemoryBuffer::AllocAligned(expectedSizeInBytes + kAlignment, kAlignment);
+ if (!PK_VERIFY(descriptor->m_RawDataRef != null))
+ return false;
+ descriptor->m_RawDataPtr = descriptor->m_RawDataRef->Data();
+ descriptor->m_RawDataByteCount = descriptor->m_RawDataRef->DataSizeInBytes();
+ }
+
+ m_Data->m_Desc = descriptor;
+ return true;
+}
//----------------------------------------------------------------------------
//
diff --git a/Source/PopcornFX/Private/DependencyModules/PopcornFXDependencyModuleLevelEditor.cpp b/Source/PopcornFX/Private/DependencyModules/PopcornFXDependencyModuleLevelEditor.cpp
index 7c92961..76c2219 100644
--- a/Source/PopcornFX/Private/DependencyModules/PopcornFXDependencyModuleLevelEditor.cpp
+++ b/Source/PopcornFX/Private/DependencyModules/PopcornFXDependencyModuleLevelEditor.cpp
@@ -87,7 +87,7 @@ void FPopcornFXDependencyModuleLevelEditor::OpenSourcePack()
PK_ASSERT(m_Settings->bSourcePackFound);
// We can now directly rely on opening the pkproj directly
- FPlatformProcess::LaunchFileInDefaultExternalApplication(*m_Settings->SourcePackProjectFile);
+ FPlatformProcess::LaunchFileInDefaultExternalApplication(*m_Settings->AbsSourcePackProjectFile);
}
//----------------------------------------------------------------------------
diff --git a/Source/PopcornFX/Private/DependencyModules/PopcornFXDependencyModulePropertyEditor.cpp b/Source/PopcornFX/Private/DependencyModules/PopcornFXDependencyModulePropertyEditor.cpp
index 291c321..f7f9e17 100644
--- a/Source/PopcornFX/Private/DependencyModules/PopcornFXDependencyModulePropertyEditor.cpp
+++ b/Source/PopcornFX/Private/DependencyModules/PopcornFXDependencyModulePropertyEditor.cpp
@@ -12,6 +12,7 @@
#include "Editor/CustomizeDetails/PopcornFXDetailsAttributeSamplerShape.h"
#include "Editor/CustomizeDetails/PopcornFXDetailsAttributeSamplerCurve.h"
#include "Editor/CustomizeDetails/PopcornFXDetailsAttributeSamplerImage.h"
+#include "Editor/CustomizeDetails/PopcornFXDetailsAttributeSamplerGrid.h"
#include "Editor/CustomizeDetails/PopcornFXDetailsAttributeSamplerVectorField.h"
#include "Editor/CustomizeDetails/PopcornFXDetailsAttributeSamplerActor.h"
#include "Editor/CustomizeDetails/PopcornFXDetailsAttributeSamplerSkinnedMesh.h"
@@ -50,6 +51,7 @@ void FPopcornFXDependencyModulePropertyEditor::Load()
propertyModule.RegisterCustomClassLayout("PopcornFXAttributeSamplerShape", FOnGetDetailCustomizationInstance::CreateStatic(&FPopcornFXDetailsAttributeSamplerShape::MakeInstance));
propertyModule.RegisterCustomClassLayout("PopcornFXAttributeSamplerCurve", FOnGetDetailCustomizationInstance::CreateStatic(&FPopcornFXDetailsAttributeSamplerCurve::MakeInstance));
propertyModule.RegisterCustomClassLayout("PopcornFXAttributeSamplerImage", FOnGetDetailCustomizationInstance::CreateStatic(&FPopcornFXDetailsAttributeSamplerImage::MakeInstance));
+ propertyModule.RegisterCustomClassLayout("PopcornFXAttributeSamplerGrid", FOnGetDetailCustomizationInstance::CreateStatic(&FPopcornFXDetailsAttributeSamplerGrid::MakeInstance));
propertyModule.RegisterCustomClassLayout("PopcornFXAttributeSamplerVectorField", FOnGetDetailCustomizationInstance::CreateStatic(&FPopcornFXDetailsAttributeSamplerVectorField::MakeInstance));
propertyModule.RegisterCustomClassLayout("PopcornFXAttributeSamplerActor", FOnGetDetailCustomizationInstance::CreateStatic(&FPopcornFXDetailsAttributeSamplerActor::MakeInstance));
propertyModule.RegisterCustomClassLayout("PopcornFXAttributeSamplerSkinnedMesh", FOnGetDetailCustomizationInstance::CreateStatic(&FPopcornFXDetailsAttributeSamplerSkinnedMesh::MakeInstance));
@@ -81,6 +83,7 @@ void FPopcornFXDependencyModulePropertyEditor::Unload()
propertyModule.UnregisterCustomClassLayout("PopcornFXAttributeSamplerShape");
propertyModule.UnregisterCustomClassLayout("PopcornFXAttributeSamplerCurve");
propertyModule.UnregisterCustomClassLayout("PopcornFXAttributeSamplerImage");
+ propertyModule.UnregisterCustomClassLayout("PopcornFXAttributeSamplerGrid");
propertyModule.UnregisterCustomClassLayout("PopcornFXAttributeSamplerVectorField");
propertyModule.UnregisterCustomClassLayout("PopcornFXAttributeSamplerActor");
propertyModule.UnregisterCustomClassLayout("PopcornFXAttributeSamplerSkinnedMesh");
diff --git a/Source/PopcornFX/Private/Editor/CustomizeDetails/PopcornFXDetailsAttributeList.cpp b/Source/PopcornFX/Private/Editor/CustomizeDetails/PopcornFXDetailsAttributeList.cpp
index 84fe137..b23413d 100644
--- a/Source/PopcornFX/Private/Editor/CustomizeDetails/PopcornFXDetailsAttributeList.cpp
+++ b/Source/PopcornFX/Private/Editor/CustomizeDetails/PopcornFXDetailsAttributeList.cpp
@@ -89,6 +89,8 @@ namespace
return "AttributeSampler_Curve";
case EPopcornFXAttributeSamplerType::Image:
return "AttributeSampler_Image";
+ case EPopcornFXAttributeSamplerType::Grid:
+ return "AttributeSampler_Image"; //"AttributeSampler_Grid"; // TODO: Grid icon
case EPopcornFXAttributeSamplerType::AnimTrack:
return "Attributesampler_AnimTrack";
case EPopcornFXAttributeSamplerType::Text:
@@ -535,6 +537,7 @@ namespace
m_Traits = &(PopcornFX::CBaseTypeTraits::Traits(attributeBaseTypeID));
m_IsQuaternion = attributeBaseTypeID == PopcornFX::BaseType_Quaternion;
+ m_IsOneShotTrigger = decl->OneShotTrigger();
// force vector dimension to 3 for quaternion, allow to display 3 float and use euler angles in editor
m_VectorDimension = (!m_IsQuaternion) ? m_Traits->VectorDimension : 3;
@@ -549,11 +552,9 @@ namespace
m_Title = FText::FromString(name);
{
- FString description;
- FString shortDescription;
- description = (const UTF16CHAR*)decl->Description().MapDefault().Data();
- description = description.Replace(TEXT("\\n"), TEXT("\n"));
- int32 shortOffset;
+ FString description = ToUE(decl->Description().MapDefault()).Replace(TEXT("\\n"), TEXT("\n"));
+ FString shortDescription;
+ int32 shortOffset;
if (description.FindChar('\n', shortOffset))
shortDescription = description.Left(shortOffset - 1);
else
@@ -563,7 +564,7 @@ namespace
}
// TODO: add an icon for quaternion attributes, right now fallbacks to F3
- const FString typeName = (!m_IsQuaternion) ? GenerateTypeName(attributeBaseTypeID) : TEXT("F3");
+ const FString typeName = (!m_IsQuaternion) ? GenerateTypeName(attributeBaseTypeID) : TEXT("F3");
m_AttributeIcon = *(TEXT("PopcornFX.Attribute.") + typeName);
m_IsColor =
@@ -803,19 +804,36 @@ namespace
TSharedRef sharedThis = SharedThis(this);
check(dimi < m_Traits->VectorDimension);
- TSharedPtr< SCheckBox > axis;
- if (m_ReadOnly)
+ if (!m_IsOneShotTrigger)
{
- SAssignNew(axis, SCheckBox)
- .IsChecked(sharedThis, &TSelf::GetValueBool, dimi);
+ TSharedPtr axis;
+ if (m_ReadOnly)
+ {
+ SAssignNew(axis, SCheckBox)
+ .IsChecked(sharedThis, &TSelf::GetValueBool, dimi);
+ }
+ else
+ {
+ SAssignNew(axis, SCheckBox)
+ .OnCheckStateChanged(sharedThis, &TSelf::OnValueChangedBool, dimi)
+ .IsChecked(sharedThis, &TSelf::GetValueBool, dimi);
+ }
+ return axis.ToSharedRef();
}
else
{
- SAssignNew(axis, SCheckBox)
- .OnCheckStateChanged(sharedThis, &TSelf::OnValueChangedBool, dimi)
- .IsChecked(sharedThis, &TSelf::GetValueBool, dimi);
+ TSharedPtr axis;
+ SAssignNew(axis, SButton)
+ .Text(FText::FromString("Pulse"))
+ .VAlign(VAlign_Center)
+ .HAlign(HAlign_Center)
+ .ClickMethod(EButtonClickMethod::MouseDown)
+ .OnClicked(this, &TSelf::OnValuePulsedBool, dimi)
+ .ContentPadding(0.0f)
+ .ForegroundColor(FSlateColor::UseForeground())
+ .IsFocusable(false);
+ return axis.ToSharedRef();
}
- return axis.ToSharedRef();
}
template
@@ -965,6 +983,22 @@ namespace
attrList->PostEditChange();
}
+ FReply OnValuePulsedBool(uint32 dimi)
+ {
+ if (m_ReadOnly)
+ return FReply::Handled();
+ UPopcornFXAttributeList *attrList;
+ if (!_GetAttrib(attrList))
+ return FReply::Handled();
+
+ const FScopedTransaction Transaction(LOCTEXT("AttributeCommit", "Attribute Value Pulse"));
+ attrList->SetFlags(RF_Transactional);
+ attrList->Modify();
+ attrList->PulseBoolAttributeDim(m_Index, dimi, true);
+ attrList->PostEditChange();
+ return FReply::Handled();
+ }
+
FText GetValueEnumText() const
{
UPopcornFXAttributeList *attrList;
@@ -1138,17 +1172,18 @@ namespace
bool m_ReadOnly = false;
bool m_ExpandOnly = false;
- uint32 m_Index;
- u32 m_VectorDimension;
- const PopcornFX::CBaseTypeTraits *m_Traits;
+ uint32 m_Index = 0;
+ u32 m_VectorDimension = 0;
+ const PopcornFX::CBaseTypeTraits *m_Traits = null;
FText m_Title;
FText m_Description;
FText m_ShortDescription;
FName m_AttributeIcon;
- bool m_IsColor;
- bool m_IsQuaternion;
+ bool m_IsColor = false;
+ bool m_IsQuaternion = false;
+ bool m_IsOneShotTrigger = false;
EPopcornFXAttributeDropDownMode::Type m_DropDownMode;
TArray m_EnumList; // copy
TArray> m_EnumListIndices;
diff --git a/Source/PopcornFX/Private/Editor/CustomizeDetails/PopcornFXDetailsAttributeSamplerGrid.cpp b/Source/PopcornFX/Private/Editor/CustomizeDetails/PopcornFXDetailsAttributeSamplerGrid.cpp
new file mode 100644
index 0000000..005f223
--- /dev/null
+++ b/Source/PopcornFX/Private/Editor/CustomizeDetails/PopcornFXDetailsAttributeSamplerGrid.cpp
@@ -0,0 +1,70 @@
+//----------------------------------------------------------------------------
+// Copyright Persistant Studios, SARL. All Rights Reserved.
+// https://www.popcornfx.com/terms-and-conditions/
+//----------------------------------------------------------------------------
+
+#if WITH_EDITOR
+#include "PopcornFXDetailsAttributeSamplerGrid.h"
+#include "PopcornFXAttributeSamplerGrid.h"
+#include "PopcornFXSDK.h"
+
+#include "DetailLayoutBuilder.h"
+#include "DetailCategoryBuilder.h"
+#include "PropertyCustomizationHelpers.h"
+#include "PropertyHandle.h"
+
+//----------------------------------------------------------------------------
+
+FPopcornFXDetailsAttributeSamplerGrid::FPopcornFXDetailsAttributeSamplerGrid()
+: m_CachedDetailLayoutBuilder(null)
+{
+
+}
+
+//----------------------------------------------------------------------------
+
+TSharedRef FPopcornFXDetailsAttributeSamplerGrid::MakeInstance()
+{
+ return MakeShareable(new FPopcornFXDetailsAttributeSamplerGrid);
+}
+
+//----------------------------------------------------------------------------
+
+void FPopcornFXDetailsAttributeSamplerGrid::RebuildDetails()
+{
+ if (!PK_VERIFY(m_CachedDetailLayoutBuilder != null))
+ return;
+ m_CachedDetailLayoutBuilder->ForceRefreshDetails();
+}
+
+//----------------------------------------------------------------------------
+
+void FPopcornFXDetailsAttributeSamplerGrid::CustomizeDetails(IDetailLayoutBuilder &detailLayout)
+{
+ TSharedRef isAssetGrid = detailLayout.GetProperty("bAssetGrid");
+ IDetailCategoryBuilder &detailCategory = detailLayout.EditCategory("PopcornFX AttributeSampler");
+
+ m_CachedDetailLayoutBuilder = &detailLayout;
+ if (isAssetGrid->IsValidHandle())
+ {
+ bool _isAssetGrid = false;
+
+ isAssetGrid->GetValue(_isAssetGrid);
+ if (_isAssetGrid)
+ {
+ detailLayout.HideProperty("SizeX");
+ detailLayout.HideProperty("SizeY");
+ detailLayout.HideProperty("SizeZ");
+ detailLayout.HideProperty("DataType");
+ }
+ else
+ {
+ detailLayout.HideProperty("RenderTarget");
+ }
+ isAssetGrid->SetOnPropertyValueChanged(FSimpleDelegate::CreateSP(this, &FPopcornFXDetailsAttributeSamplerGrid::RebuildDetails));
+ }
+
+}
+
+//----------------------------------------------------------------------------
+#endif // WITH_EDITOR
diff --git a/Source/PopcornFX/Private/Editor/CustomizeDetails/PopcornFXDetailsAttributeSamplerGrid.h b/Source/PopcornFX/Private/Editor/CustomizeDetails/PopcornFXDetailsAttributeSamplerGrid.h
new file mode 100644
index 0000000..eba9eef
--- /dev/null
+++ b/Source/PopcornFX/Private/Editor/CustomizeDetails/PopcornFXDetailsAttributeSamplerGrid.h
@@ -0,0 +1,30 @@
+//----------------------------------------------------------------------------
+// Copyright Persistant Studios, SARL. All Rights Reserved.
+// https://www.popcornfx.com/terms-and-conditions/
+//----------------------------------------------------------------------------
+
+#pragma once
+
+#if WITH_EDITOR
+
+#include "PopcornFXMinimal.h"
+
+#include "PropertyEditorModule.h"
+#include "IDetailCustomization.h"
+
+class FPopcornFXDetailsAttributeSamplerGrid : public IDetailCustomization
+{
+public:
+ FPopcornFXDetailsAttributeSamplerGrid();
+
+ /** Makes a new instance of this detail layout class for a specific detail view requesting it */
+ static TSharedRef MakeInstance();
+
+ virtual void CustomizeDetails(IDetailLayoutBuilder &detailLayout) override;
+private:
+ void RebuildDetails();
+
+ IDetailLayoutBuilder *m_CachedDetailLayoutBuilder;
+};
+
+#endif // WITH_EDITOR
diff --git a/Source/PopcornFX/Private/Editor/PopcornFXEffectEditor.cpp b/Source/PopcornFX/Private/Editor/PopcornFXEffectEditor.cpp
index 334959f..8bdeb2c 100644
--- a/Source/PopcornFX/Private/Editor/PopcornFXEffectEditor.cpp
+++ b/Source/PopcornFX/Private/Editor/PopcornFXEffectEditor.cpp
@@ -364,6 +364,7 @@ void FPopcornFXEffectEditor::ReimportEffect()
PK_ASSERT(m_Effect != null);
FReimportManager::Instance()->Reimport(m_Effect, true);
+ PreviewViewport->ResetEmitterAttributes();
}
//----------------------------------------------------------------------------
diff --git a/Source/PopcornFX/Private/Editor/PopcornFXStyle.cpp b/Source/PopcornFX/Private/Editor/PopcornFXStyle.cpp
index c0ab734..c26a5df 100644
--- a/Source/PopcornFX/Private/Editor/PopcornFXStyle.cpp
+++ b/Source/PopcornFX/Private/Editor/PopcornFXStyle.cpp
@@ -95,6 +95,7 @@ void FPopcornFXStyle::Initialize()
ATTRIBSAMPLER_STYLE("PopcornFXAttributeSamplerShape", "AttributeSampler_Shape", "SlateBrushes/AttributeSampler_Shape");
ATTRIBSAMPLER_STYLE("PopcornFXAttributeSamplerSkinnedMesh", "AttributeSampler_SkeletalMesh", "SlateBrushes/AttributeSampler_SkeletalMesh");
ATTRIBSAMPLER_STYLE("PopcornFXAttributeSamplerImage", "AttributeSampler_Image", "SlateBrushes/AttributeSampler_Image");
+ ATTRIBSAMPLER_STYLE("PopcornFXAttributeSamplerGrid", "AttributeSampler_Image", "SlateBrushes/AttributeSampler_Image"); // TODO: Grid icon
ATTRIBSAMPLER_STYLE("PopcornFXAttributeSamplerAnimTrack", "Attributesampler_AnimTrack", "SlateBrushes/Attributesampler_AnimTrack");
ATTRIBSAMPLER_STYLE("PopcornFXAttributeSamplerCurve", "AttributeSampler_Curve", "SlateBrushes/AttributeSampler_Curve");
ATTRIBSAMPLER_STYLE("PopcornFXAttributeSamplerText", "AttributeSampler_Text", "SlateBrushes/AttributeSampler_Text");
diff --git a/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim.cpp b/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim.cpp
index 4631c4f..c67224f 100644
--- a/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim.cpp
+++ b/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim.cpp
@@ -48,12 +48,18 @@ void SetupPopcornFXRHIAPI(uint32 API)
bool _IsGpuSupportedOnPlatform(const EShaderPlatform &platform)
{
- const bool platformSupportsSM5OrEquivalent = IsFeatureLevelSupported(platform, ERHIFeatureLevel::SM5);
- const bool isStaticShaderPlatform = FStaticShaderPlatformNames::Get().IsStaticPlatform(platform);
+#if WITH_EDITOR
+ const EShaderPlatform &realPlatform = FGenericDataDrivenShaderPlatformInfo::GetIsPreviewPlatform(platform) ? FGenericDataDrivenShaderPlatformInfo::GetPreviewShaderPlatformParent(platform) : platform;
+#else
+ const EShaderPlatform &realPlatform = platform;
+#endif
+
+ const bool platformSupportsSM5OrEquivalent = IsFeatureLevelSupported(realPlatform, ERHIFeatureLevel::SM5);
+ const bool isStaticShaderPlatform = FStaticShaderPlatformNames::Get().IsStaticPlatform(realPlatform);
if (isStaticShaderPlatform)
{
- const FName platformName = FStaticShaderPlatformNames::Get().GetPlatformName(platform);
+ const FName platformName = FStaticShaderPlatformNames::Get().GetPlatformName(realPlatform);
// Special UE4
return (
@@ -69,16 +75,16 @@ bool _IsGpuSupportedOnPlatform(const EShaderPlatform &platform)
false) && platformSupportsSM5OrEquivalent;
}
#if (ENGINE_MAJOR_VERSION == 5)
- const bool platformSupportsSM6OrEquivalent = IsFeatureLevelSupported(platform, ERHIFeatureLevel::SM6);
- return (platform == SP_PCD3D_SM5 && platformSupportsSM5OrEquivalent) ||
- (platform == SP_PCD3D_SM6 && platformSupportsSM6OrEquivalent);
+ const bool platformSupportsSM6OrEquivalent = IsFeatureLevelSupported(realPlatform, ERHIFeatureLevel::SM6);
+ return (realPlatform == SP_PCD3D_SM5 && platformSupportsSM5OrEquivalent) ||
+ (realPlatform == SP_PCD3D_SM6 && platformSupportsSM6OrEquivalent);
#else
return (
# if 0
// GPU sim not supported on Xbox one for now
- platform == SP_XBOXONE_D3D12 ||
+ realPlatform == SP_XBOXONE_D3D12 ||
# endif
- platform == SP_PCD3D_SM5
+ realPlatform == SP_PCD3D_SM5
) &&
platformSupportsSM5OrEquivalent;
#endif // (ENGINE_MAJOR_VERSION == 5)
diff --git a/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSimInterfaces.cpp b/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSimInterfaces.cpp
index fdea54e..23a88d4 100644
--- a/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSimInterfaces.cpp
+++ b/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSimInterfaces.cpp
@@ -40,10 +40,10 @@ namespace PopcornFXGPU
FString simInterfaceSource;
if (!FFileHelper::LoadFileToString(simInterfaceSource, *simInterfacePath))
{
- PopcornFX::CLog::Log(PK_ERROR, "Couldn't load sim interface source ('%s')", TCHAR_TO_ANSI(*simInterfacePath));
+ PopcornFX::CLog::Log(PK_ERROR, "Couldn't load sim interface source ('%s')", TCHAR_TO_UTF8(*simInterfacePath));
return false;
}
- outKernelSource += TCHAR_TO_ANSI(*simInterfaceSource);
+ outKernelSource += ToPk(simInterfaceSource);
return true;
}
@@ -160,7 +160,7 @@ namespace PopcornFXGPU
#if (PK_GPU_D3D11 != 0)
const PopcornFX::SBindingContextD3D11 &d3d11Context = context.ToD3D11();
- PopcornFX::SParticleStreamBuffer_D3D11 &viewConstantBuffer = FPopcornFXPlugin::Get().ViewConstantBuffer_D3D11();
+ PopcornFX::SBuffer_D3D11 &viewConstantBuffer = FPopcornFXPlugin::Get().ViewConstantBuffer_D3D11();
if (viewConstantBuffer.Empty())
{
ID3D11Device *device = null;
diff --git a/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim_D3D11.cpp b/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim_D3D11.cpp
index 040035b..38978eb 100644
--- a/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim_D3D11.cpp
+++ b/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim_D3D11.cpp
@@ -63,7 +63,7 @@ void UpdateBufferStats(TRefCountPtr Buffer, bool bAllocating) { }
//
//----------------------------------------------------------------------------
-FShaderResourceViewRHIRef StreamBufferSRVToRHI(const PopcornFX::SParticleStreamBuffer_D3D11 *stream, u32 stride, u8 pixelFormat)
+FShaderResourceViewRHIRef StreamBufferSRVToRHI(const PopcornFX::SBuffer_D3D11 *stream, u32 stride, u8 pixelFormat)
{
#if (ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 3)
FRHICommandListBase &RHICmdList = FRHICommandListExecutor::GetImmediateCommandList();
@@ -89,9 +89,9 @@ FShaderResourceViewRHIRef StreamBufferSRVToRHI(const PopcornFX::SParticleStreamB
//----------------------------------------------------------------------------
#if (ENGINE_MAJOR_VERSION == 5)
-FRHIBuffer *StreamBufferResourceToRHI(const PopcornFX::SParticleStreamBuffer_D3D11 *stream, u32 stride)
+FRHIBuffer *StreamBufferResourceToRHI(const PopcornFX::SBuffer_D3D11 *stream, u32 stride)
#else
-FRHIVertexBuffer *StreamBufferResourceToRHI(const PopcornFX::SParticleStreamBuffer_D3D11 *stream, u32 stride)
+FRHIVertexBuffer *StreamBufferResourceToRHI(const PopcornFX::SBuffer_D3D11 *stream, u32 stride)
#endif // (ENGINE_MAJOR_VERSION == 5)
{
D3D11_BUFFER_DESC desc;
@@ -103,7 +103,7 @@ FRHIVertexBuffer *StreamBufferResourceToRHI(const PopcornFX::SParticleStreamB
PK_ASSERT((desc.Usage & D3D11_USAGE_DYNAMIC) == 0); // no BUF_AnyDynamic
PK_ASSERT((desc.CPUAccessFlags) == 0); // no BUF_AnyDynamic
- // TODO: Unify SParticleStreamBuffer_D3D11 with other APIs, just provide a m_ByteSize member..
+ // TODO: Unify SBuffer_D3D11 with other APIs, just provide a m_ByteSize member..
const u32 sizeInBytes = desc.ByteWidth;
// Fixed #12899: removed BUF_UnorderedAccess | BUF_ByteAddressBuffer from the buffer usage, as it leads to crashes on some AMD GPU hardware.
diff --git a/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim_D3D11.h b/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim_D3D11.h
index c8ad681..a9678da 100644
--- a/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim_D3D11.h
+++ b/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim_D3D11.h
@@ -13,15 +13,15 @@
class FD3D11VertexBuffer;
FWD_PK_API_BEGIN
-struct SParticleStreamBuffer_D3D11;
+struct SBuffer_D3D11;
class CParticleStreamToRender_D3D11;
FWD_PK_API_END
-FShaderResourceViewRHIRef StreamBufferSRVToRHI(const PopcornFX::SParticleStreamBuffer_D3D11 *stream, u32 stride, u8 pixelFormat = PF_R32_FLOAT);
+FShaderResourceViewRHIRef StreamBufferSRVToRHI(const PopcornFX::SBuffer_D3D11 *stream, u32 stride, u8 pixelFormat = PF_R32_FLOAT);
#if (ENGINE_MAJOR_VERSION == 5)
-FRHIBuffer *StreamBufferResourceToRHI(const PopcornFX::SParticleStreamBuffer_D3D11 *stream, u32 stride);
+FRHIBuffer *StreamBufferResourceToRHI(const PopcornFX::SBuffer_D3D11 *stream, u32 stride);
#else
-FRHIVertexBuffer *StreamBufferResourceToRHI(const PopcornFX::SParticleStreamBuffer_D3D11 *stream, u32 stride);
+FRHIVertexBuffer *StreamBufferResourceToRHI(const PopcornFX::SBuffer_D3D11 *stream, u32 stride);
#endif // (ENGINE_MAJOR_VERSION == 5)
//----------------------------------------------------------------------------
diff --git a/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim_D3D12.cpp b/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim_D3D12.cpp
index 6ce8622..18e4363 100644
--- a/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim_D3D12.cpp
+++ b/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim_D3D12.cpp
@@ -330,7 +330,7 @@ inline FD3D12UnorderedAccessView* CreateUAV(D3D12_UNORDERED_ACCESS_VIEW_DESC& De
//
//----------------------------------------------------------------------------
-FShaderResourceViewRHIRef StreamBufferSRVToRHI(const PopcornFX::SParticleStreamBuffer_D3D12 *stream, u32 stride, u8 pixelFormat)
+FShaderResourceViewRHIRef StreamBufferSRVToRHI(const PopcornFX::SBuffer_D3D12 *stream, u32 stride, u8 pixelFormat)
{
#if (ENGINE_MAJOR_VERSION == 5)
FRHIBuffer *buffer = StreamBufferResourceToRHI(stream, stride);
@@ -353,9 +353,9 @@ FShaderResourceViewRHIRef StreamBufferSRVToRHI(const PopcornFX::SParticleStreamB
//----------------------------------------------------------------------------
#if (ENGINE_MAJOR_VERSION == 5)
-FRHIBuffer *StreamBufferResourceToRHI(const PopcornFX::SParticleStreamBuffer_D3D12 *stream, u32 stride)
+FRHIBuffer *StreamBufferResourceToRHI(const PopcornFX::SBuffer_D3D12 *stream, u32 stride)
#else
-FRHIVertexBuffer *StreamBufferResourceToRHI(const PopcornFX::SParticleStreamBuffer_D3D12 *stream, u32 stride)
+FRHIVertexBuffer *StreamBufferResourceToRHI(const PopcornFX::SBuffer_D3D12 *stream, u32 stride)
#endif // (ENGINE_MAJOR_VERSION == 5)
{
D3D12_RESOURCE_DESC desc = stream->m_Resource->GetDesc();
@@ -368,7 +368,7 @@ FRHIVertexBuffer *StreamBufferResourceToRHI(const PopcornFX::SParticleStreamBuff
PK_ASSERT(desc.SampleDesc.Quality == 0);
PK_ASSERT(desc.Layout == D3D12_TEXTURE_LAYOUT_ROW_MAJOR);
PK_ASSERT(desc.Flags == D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS);
- PK_ASSERT(stream->m_State == (D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER)); // PK_BUFFER_GPU_D3D12_DEFAULT_STATE, currently not exposed
+ PK_ASSERT(stream->m_State == (D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER) || stream->m_State == (D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER | D3D12_RESOURCE_STATE_COPY_SOURCE)); // PK_BUFFER_GPU_D3D12_DEFAULT_STATE, currently not exposed
FD3D12DynamicRHI *dynamicRHI = static_cast(GDynamicRHI);
FD3D12Device *device = dynamicRHI->GetAdapter().GetDevice(0);
diff --git a/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim_D3D12.h b/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim_D3D12.h
index 2d98658..604e08e 100644
--- a/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim_D3D12.h
+++ b/Source/PopcornFX/Private/GPUSim/PopcornFXGPUSim_D3D12.h
@@ -13,15 +13,15 @@
class FD3D12VertexBuffer;
FWD_PK_API_BEGIN
-struct SParticleStreamBuffer_D3D12;
+struct SBuffer_D3D12;
class CParticleStreamToRender_D3D12;
FWD_PK_API_END
-FShaderResourceViewRHIRef StreamBufferSRVToRHI(const PopcornFX::SParticleStreamBuffer_D3D12 *stream, u32 stride, u8 pixelFormat = PF_R32_FLOAT);
+FShaderResourceViewRHIRef StreamBufferSRVToRHI(const PopcornFX::SBuffer_D3D12 *stream, u32 stride, u8 pixelFormat = PF_R32_FLOAT);
#if (ENGINE_MAJOR_VERSION == 5)
-FRHIBuffer *StreamBufferResourceToRHI(const PopcornFX::SParticleStreamBuffer_D3D12 *stream, u32 stride);
+FRHIBuffer *StreamBufferResourceToRHI(const PopcornFX::SBuffer_D3D12 *stream, u32 stride);
#else
-FRHIVertexBuffer *StreamBufferResourceToRHI(const PopcornFX::SParticleStreamBuffer_D3D12 *stream, u32 stride);
+FRHIVertexBuffer *StreamBufferResourceToRHI(const PopcornFX::SBuffer_D3D12 *stream, u32 stride);
#endif // (ENGINE_MAJOR_VERSION == 5)
#endif // (PK_GPU_D3D12 == 1)
diff --git a/Source/PopcornFX/Private/HUD/PopcornFXHUDProfiler.cpp b/Source/PopcornFX/Private/HUD/PopcornFXHUDProfiler.cpp
index cd37dec..f7341cd 100644
--- a/Source/PopcornFX/Private/HUD/PopcornFXHUDProfiler.cpp
+++ b/Source/PopcornFX/Private/HUD/PopcornFXHUDProfiler.cpp
@@ -265,13 +265,13 @@ void APopcornFXHUDProfiler::DrawDebugHUD(UCanvas* inCanvas, APlayerController* p
const PopcornFX::Units::SValueAndNamedUnit readableTotalTimeCPU = PopcornFX::Units::AutoscaleTime(wallUpdateTimeCPU, 0.5f);
//const PopcornFX::Units::SValueAndNamedUnit readableTotalTimeGPU = PopcornFX::Units::AutoscaleTime(totalUpdateTimeGPU, 0.5f);
DrawBar(timexPos, timeCPUxPos - 1, yPos, wallUpdateTimeCPU / TimeLimitTotalSeconds, lineHeight);
- Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTotalTime.m_Value, ANSI_TO_TCHAR(readableTotalTime.m_UnitName)), timexPos, yPos, 1.f, 1.f, friNoShadow);
+ Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTotalTime.m_Value, UTF8_TO_TCHAR(readableTotalTime.m_UnitName)), timexPos, yPos, 1.f, 1.f, friNoShadow);
if (hasGPU)
{
DrawBar(timeCPUxPos, timeGPUxPos - 1, yPos, wallUpdateTimeCPU / CPUTimeLimitTotalSeconds, lineHeight);
- Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTotalTimeCPU.m_Value, ANSI_TO_TCHAR(readableTotalTimeCPU.m_UnitName)), timeCPUxPos, yPos, 1.f, 1.f, friNoShadow);
+ Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTotalTimeCPU.m_Value, UTF8_TO_TCHAR(readableTotalTimeCPU.m_UnitName)), timeCPUxPos, yPos, 1.f, 1.f, friNoShadow);
//DrawBar(timeGPUxPos, pCountCPUxPos - 1, yPos, totalUpdateTimeGPU / GPUTimeLimitTotalSeconds, lineHeight);
- //Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTotalTimeGPU.m_Value, ANSI_TO_TCHAR(readableTotalTimeGPU.m_UnitName)), timeGPUxPos, yPos, 1.f, 1.f, friNoShadow);
+ //Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTotalTimeGPU.m_Value, UTF8_TO_TCHAR(readableTotalTimeGPU.m_UnitName)), timeGPUxPos, yPos, 1.f, 1.f, friNoShadow);
}
}
// Counts
@@ -360,13 +360,13 @@ void APopcornFXHUDProfiler::DrawDebugHUD(UCanvas* inCanvas, APlayerController* p
const PopcornFX::Units::SValueAndNamedUnit readableTimeGPU = PopcornFX::Units::AutoscaleTime(timeTotalGPU, 0.5f);
DrawBar(timexPos, timeCPUxPos - 1, yPos, timeTotal / TimeLimitPerEffectSeconds, lineHeight);
- Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTime.m_Value, ANSI_TO_TCHAR(readableTime.m_UnitName)), timexPos, yPos, 1.f, 1.f, friNoShadow);
+ Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTime.m_Value, UTF8_TO_TCHAR(readableTime.m_UnitName)), timexPos, yPos, 1.f, 1.f, friNoShadow);
if (hasGPU)
{
DrawBar(timeCPUxPos, timeGPUxPos - 1, yPos, timeTotalCPU / CPUTimeLimitPerEffectSeconds, lineHeight);
- Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTimeCPU.m_Value, ANSI_TO_TCHAR(readableTimeCPU.m_UnitName)), timeCPUxPos, yPos, 1.f, 1.f, friNoShadow);
+ Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTimeCPU.m_Value, UTF8_TO_TCHAR(readableTimeCPU.m_UnitName)), timeCPUxPos, yPos, 1.f, 1.f, friNoShadow);
DrawBar(timeGPUxPos, pCountCPUxPos - 1, yPos, timeTotalGPU / GPUTimeLimitPerEffectSeconds, lineHeight);
- Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTimeGPU.m_Value, ANSI_TO_TCHAR(readableTimeGPU.m_UnitName)), timeGPUxPos, yPos, 1.f, 1.f, friNoShadow);
+ Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTimeGPU.m_Value, UTF8_TO_TCHAR(readableTimeGPU.m_UnitName)), timeGPUxPos, yPos, 1.f, 1.f, friNoShadow);
}
}
@@ -384,7 +384,7 @@ void APopcornFXHUDProfiler::DrawDebugHUD(UCanvas* inCanvas, APlayerController* p
}
// Effect path
- Canvas->DrawText(font, FString::Printf(TEXT("%s"), ANSI_TO_TCHAR(allSceneTimings[iTiming].m_EffectPath.Data())), effectPathxPos, yPos, 1.f, 1.f, fri);
+ Canvas->DrawText(font, FString::Printf(TEXT("%s"), *ToUE(allSceneTimings[iTiming].m_EffectPath)), effectPathxPos, yPos, 1.f, 1.f, fri);
yPos += lineHeight;
if (yPos > maxDrawyPos)
@@ -419,13 +419,13 @@ void APopcornFXHUDProfiler::DrawDebugHUD(UCanvas* inCanvas, APlayerController* p
const PopcornFX::Units::SValueAndNamedUnit readableTotalDisplayedTimeCPU = PopcornFX::Units::AutoscaleTime(timeTotalCPU, 0.5f);
const PopcornFX::Units::SValueAndNamedUnit readableTotalDisplayedTimeGPU = PopcornFX::Units::AutoscaleTime(timeTotalGPU, 0.5f);
DrawBar(timexPos, timeCPUxPos - 1, yPos, timeTotal / TimeLimitTotalSeconds, lineHeight);
- Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTotalDisplayedTime.m_Value, ANSI_TO_TCHAR(readableTotalDisplayedTime.m_UnitName)), timexPos, yPos, 1.f, 1.f, friNoShadow);
+ Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTotalDisplayedTime.m_Value, UTF8_TO_TCHAR(readableTotalDisplayedTime.m_UnitName)), timexPos, yPos, 1.f, 1.f, friNoShadow);
if (hasGPU)
{
DrawBar(timeCPUxPos, timeGPUxPos - 1, yPos, timeTotalCPU / CPUTimeLimitTotalSeconds, lineHeight);
- Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTotalDisplayedTimeCPU.m_Value, ANSI_TO_TCHAR(readableTotalDisplayedTimeCPU.m_UnitName)), timeCPUxPos, yPos, 1.f, 1.f, friNoShadow);
+ Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTotalDisplayedTimeCPU.m_Value, UTF8_TO_TCHAR(readableTotalDisplayedTimeCPU.m_UnitName)), timeCPUxPos, yPos, 1.f, 1.f, friNoShadow);
DrawBar(timeGPUxPos, pCountCPUxPos - 1, yPos, timeTotalGPU / GPUTimeLimitTotalSeconds, lineHeight);
- Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTotalDisplayedTimeGPU.m_Value, ANSI_TO_TCHAR(readableTotalDisplayedTimeGPU.m_UnitName)), timeGPUxPos, yPos, 1.f, 1.f, friNoShadow);
+ Canvas->DrawText(font, FString::Printf(TEXT("%.1f %s"), readableTotalDisplayedTimeGPU.m_Value, UTF8_TO_TCHAR(readableTotalDisplayedTimeGPU.m_UnitName)), timeGPUxPos, yPos, 1.f, 1.f, friNoShadow);
}
}
diff --git a/Source/PopcornFX/Private/Internal/FileSystemController_UE.cpp b/Source/PopcornFX/Private/Internal/FileSystemController_UE.cpp
index aecf67b..11c2aeb 100644
--- a/Source/PopcornFX/Private/Internal/FileSystemController_UE.cpp
+++ b/Source/PopcornFX/Private/Internal/FileSystemController_UE.cpp
@@ -31,7 +31,7 @@ using PopcornFX::PKMax;
// static
UObject *CFileSystemController_UE::LoadUObject(const CString &path, bool pathNotVirtual)
{
- UObject *object = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(path.Data(), pathNotVirtual);
+ UObject *object = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(path, pathNotVirtual);
FS_DEBUG_LOG(PK_INFO, "FileSystem LoadUObject %s > %p", path.Data(), object);
return object;
}
@@ -65,16 +65,15 @@ UPopcornFXFile *CFileSystemController_UE::FindDirectPopcornFXFile(UObject *uobj
//
//----------------------------------------------------------------------------
-CFileStreamFS_UE::CFileStreamFS_UE(
- CFileSystemController_UE *controller,
- PopcornFX::PFilePack pack,
- const CString &path,
- IFileSystem::EAccessPolicy mode,
- UPopcornFXFile *file)
- : CFileStream(controller, pack, path, mode)
- , m_Mode(mode)
- , m_File(file)
- , m_Pos(0)
+CFileStreamFS_UE::CFileStreamFS_UE( CFileSystemController_UE *controller,
+ PopcornFX::PFilePack pack,
+ const CString &path,
+ IFileSystem::EAccessPolicy mode,
+ UPopcornFXFile *file)
+: CFileStream(controller, pack, path, mode)
+, m_Mode(mode)
+, m_File(file)
+, m_Pos(0)
{
FILE_ASSERT(m_File != null);
FS_DEBUG_LOG(PK_INFO, "ctor CFileStreamFS_UE %s filesize:%d", Path().Data(), CFileStreamFS_UE::SizeInBytes());
diff --git a/Source/PopcornFX/Private/Internal/ParticleScene.cpp b/Source/PopcornFX/Private/Internal/ParticleScene.cpp
index 53d74ef..a76fae0 100644
--- a/Source/PopcornFX/Private/Internal/ParticleScene.cpp
+++ b/Source/PopcornFX/Private/Internal/ParticleScene.cpp
@@ -1872,7 +1872,7 @@ PopcornFX::TMemoryView CParticleScene::GetAudioSpectrum(Pop
if (channelGroup.Empty() || m_FillAudioBuffers == null)
return PopcornFX::TMemoryView();
- const FName channelName(ANSI_TO_TCHAR(channelGroup.ToString().Data()));
+ const FName channelName(*ToUE(channelGroup.ToString()));
const float * const *rawSpectrumData = m_FillAudioBuffers->AsyncGetAudioSpectrum(channelName, outBaseCount);
if (rawSpectrumData == null || outBaseCount == 0)
return PopcornFX::TMemoryView();
@@ -1888,7 +1888,7 @@ PopcornFX::TMemoryView CParticleScene::GetAudioWaveform(Pop
if (channelGroup.Empty() || m_FillAudioBuffers == null)
return PopcornFX::TMemoryView();
- const FName channelName(ANSI_TO_TCHAR(channelGroup.ToString().Data()));
+ const FName channelName(*ToUE(channelGroup.ToString()));
const float * const *rawWaveformData = m_FillAudioBuffers->AsyncGetAudioWaveform(channelName, outBaseCount);
if (rawWaveformData == null || outBaseCount == 0)
return PopcornFX::TMemoryView();
@@ -2946,7 +2946,7 @@ bool CParticleScene::RegisterEventListener(UPopcornFXEffect* particleEffect, Pop
{
if (!particleEffect->Effect()->RegisterEventCallback(broadcastCallback, eventNameID))
{
- UE_LOG(LogPopcornFXScene, Warning, TEXT("Register Event Listener: Couldn't register callback to event '%s' on effect '%s'"), eventNameID.ToString().Data(), *particleEffect->GetName());
+ UE_LOG(LogPopcornFXScene, Warning, TEXT("Register Event Listener: Couldn't register callback to event '%s' on effect '%s'"), *ToUE(eventNameID.ToString()), *particleEffect->GetName());
return false;
}
// add event name ID : don't register a callback several times for the same event
@@ -3098,7 +3098,7 @@ bool CParticleScene::GetPayloadValue(const FName &payloadName, EPopcornFXPayload
return false;
}
- const PopcornFX::CStringId payloadNameID(TCHAR_TO_ANSI(*payloadName.ToString())); // Expensive
+ const PopcornFX::CStringId payloadNameID(ToPk(payloadName.ToString())); // Expensive
const PopcornFX::CGuid payloadIndex = m_CurrentPayloadView->m_Payloads.IndexOf(payloadNameID);
if (!payloadIndex.Valid())
diff --git a/Source/PopcornFX/Private/Internal/PopcornFXLogs.cpp b/Source/PopcornFX/Private/Internal/PopcornFXLogs.cpp
index 76e4c6b..9c1fb40 100644
--- a/Source/PopcornFX/Private/Internal/PopcornFXLogs.cpp
+++ b/Source/PopcornFX/Private/Internal/PopcornFXLogs.cpp
@@ -56,7 +56,7 @@ namespace
if (!LogPopcornFX.IsSuppressed(kLogVerbosityToUE[level]))
{
const ELogVerbosity::Type logLevel = kLogVerbosityToUE[level];
- FMsg::Logf(__FILE__, __LINE__, LogPopcornFX.GetCategoryName(), logLevel, TEXT("%s"), ANSI_TO_TCHAR(s.Data()));
+ FMsg::Logf(__FILE__, __LINE__, LogPopcornFX.GetCategoryName(), logLevel, TEXT("%s"), UTF8_TO_TCHAR(s.Data()));
}
#endif
}
diff --git a/Source/PopcornFX/Private/Internal/ResourceHandlerImage_UE.cpp b/Source/PopcornFX/Private/Internal/ResourceHandlerImage_UE.cpp
index 319dd0e..a7515ac 100644
--- a/Source/PopcornFX/Private/Internal/ResourceHandlerImage_UE.cpp
+++ b/Source/PopcornFX/Private/Internal/ResourceHandlerImage_UE.cpp
@@ -229,10 +229,10 @@ PopcornFX::CImage *CResourceHandlerImage_UE::NewFromPath(const PopcornFX::CStrin
{
PK_NAMEDSCOPEDPROFILE_C("CResourceHandlerImage_UE::NewFromPath", POPCORNFX_UE_PROFILER_COLOR);
- UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(path.Data(), pathNotVirtual);
+ UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(path, pathNotVirtual);
if (obj == null)
{
- UE_LOG(LogPopcornFXResourceHandlerImage, Warning, TEXT("UObject not found \"%s\" %d"), ANSI_TO_TCHAR(path.Data()), pathNotVirtual);
+ UE_LOG(LogPopcornFXResourceHandlerImage, Warning, TEXT("UObject not found \"%s\" %d"), *ToUE(path), pathNotVirtual);
return null;
}
UTexture *texture = Cast(obj);
@@ -285,9 +285,7 @@ CResourceHandlerImage_UE::~CResourceHandlerImage_UE()
for (CResourcesHashMap::ConstIterator it = m_Images.Begin(), itEnd = m_Images.End(); it != itEnd; ++it)
{
PK_ASSERT(it->m_ReferenceCount > 0);
- UE_LOG(LogPopcornFXResourceHandlerImage, Warning, TEXT("Texture leak: \"%s\" %s"),
- ANSI_TO_TCHAR(it.Key().Data()),
- it->m_Virtual ? TEXT("(Virtual Texture)") : TEXT(""));
+ UE_LOG(LogPopcornFXResourceHandlerImage, Warning, TEXT("Texture leak: \"%s\" %s"), *ToUE(it.Key()), it->m_Virtual ? TEXT("(Virtual Texture)") : TEXT(""));
}
}
@@ -308,9 +306,8 @@ void *CResourceHandlerImage_UE::Load(
PopcornFX::CString _fullPath = resourcePath;
if (!pathNotVirtual) // if virtual path
- {
- _fullPath = TCHAR_TO_ANSI(*FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath.Data(), true)); // prepend Pack Path
- }
+ _fullPath = ToPk(FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath, true)); // prepend Pack Path
+
PopcornFX::CFilePath::StripExtensionInPlace(_fullPath);
const PopcornFX::CString &fullPath = _fullPath;
if (!/*PK_VERIFY*/(!fullPath.Empty()))
@@ -508,9 +505,8 @@ bool CResourceHandlerImage_UE::IsUsed(const PopcornFX::CString &virtualPath, boo
{
PopcornFX::CString _fullPath = virtualPath;
if (!pathNotVirtual) // if virtual path
- {
- _fullPath = TCHAR_TO_ANSI(*FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath.Data(), true)); // prepend Pack Path
- }
+ _fullPath = ToPk(FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath, true)); // prepend Pack Path
+
PopcornFX::CFilePath::StripExtensionInPlace(_fullPath);
const PopcornFX::CString &fullPath = _fullPath;
if (!/*PK_VERIFY*/(!fullPath.Empty()))
@@ -538,9 +534,8 @@ bool CResourceHandlerImage_UE::RegisterVirtualTexture(const PopcornFX::CString &
PopcornFX::CString _fullPath = virtualPath;
if (!pathNotVirtual) // if virtual path
- {
- _fullPath = TCHAR_TO_ANSI(*FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath.Data(), true)); // prepend Pack Path
- }
+ _fullPath = ToPk(FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath, true)); // prepend Pack Path
+
PopcornFX::CFilePath::StripExtensionInPlace(_fullPath);
const PopcornFX::CString &fullPath = _fullPath;
if (!/*PK_VERIFY*/(!fullPath.Empty()))
@@ -552,7 +547,7 @@ bool CResourceHandlerImage_UE::RegisterVirtualTexture(const PopcornFX::CString &
const u32 totalImageBytes = PopcornFX::CImage::GetFormatPixelBufferSizeInBytes(format, size);
if (!PK_VERIFY(pixelsDataSizeInBytes >= totalImageBytes))
{
- UE_LOG(LogPopcornFXResourceHandlerImage, Error, TEXT("Invalid image byte size for virtual texture \"%s\""), ANSI_TO_TCHAR(virtualPath.Data()));
+ UE_LOG(LogPopcornFXResourceHandlerImage, Error, TEXT("Invalid image byte size for virtual texture \"%s\""), *ToUE(virtualPath));
return false;
}
@@ -647,7 +642,8 @@ bool CResourceHandlerImage_UE::UnregisterVirtualTexture(const PopcornFX::CString
PopcornFX::CString _fullPath = virtualPath;
if (!pathNotVirtual) // if virtual path
- _fullPath = TCHAR_TO_ANSI(*FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath.Data(), true)); // prepend Pack Path
+ _fullPath = ToPk(FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath, true)); // prepend Pack Path
+
PopcornFX::CFilePath::StripExtensionInPlace(_fullPath);
const PopcornFX::CString &fullPath = _fullPath;
if (!/*PK_VERIFY*/(!fullPath.Empty()))
@@ -660,12 +656,12 @@ bool CResourceHandlerImage_UE::UnregisterVirtualTexture(const PopcornFX::CString
SResourceEntry *foundResource = m_Images.Find(fullPath);
if (foundResource == null)
{
- UE_LOG(LogPopcornFXResourceHandlerImage, Error, TEXT("Virtual Texture not found to Unregister \"%s\""), ANSI_TO_TCHAR(virtualPath.Data()));
+ UE_LOG(LogPopcornFXResourceHandlerImage, Error, TEXT("Virtual Texture not found to Unregister \"%s\""), *ToUE(virtualPath));
return false;
}
if (!PK_VERIFY(foundResource->m_Virtual))
{
- UE_LOG(LogPopcornFXResourceHandlerImage, Error, TEXT("Texture is not a Virtual Texture to Unregister \"%s\""), ANSI_TO_TCHAR(virtualPath.Data()));
+ UE_LOG(LogPopcornFXResourceHandlerImage, Error, TEXT("Texture is not a Virtual Texture to Unregister \"%s\""), *ToUE(virtualPath));
return false;
}
PK_ASSERT(foundResource->m_Image != null);
@@ -701,7 +697,7 @@ bool CResourceHandlerImage_UE::UnregisterVirtualTexture(const PopcornFX::CString
if (resource == null)
{
- UE_LOG(LogPopcornFXResourceHandlerImage, Error, TEXT("Could not load true asset to replace Unregistered Virtual Texture, keeping old datas \"%s\""), ANSI_TO_TCHAR(virtualPath.Data()));
+ UE_LOG(LogPopcornFXResourceHandlerImage, Error, TEXT("Could not load true asset to replace Unregistered Virtual Texture, keeping old datas \"%s\""), *ToUE(virtualPath));
return false;
}
PK_ASSERT(foundResource->m_Image != null);
@@ -789,10 +785,10 @@ PopcornFX::CImageGPU_D3D11 *CResourceHandlerImage_UE_D3D11::NewFromPath(const P
{
PK_NAMEDSCOPEDPROFILE_C("CResourceHandlerImage_UE_D3D11::NewFromPath", POPCORNFX_UE_PROFILER_COLOR);
- UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(path.Data(), pathNotVirtual);
+ UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(path, pathNotVirtual);
if (obj == null)
{
- UE_LOG(LogPopcornFXResourceHandlerImageGPU, Warning, TEXT("UObject not found \"%s\" %d"), ANSI_TO_TCHAR(path.Data()), pathNotVirtual);
+ UE_LOG(LogPopcornFXResourceHandlerImageGPU, Warning, TEXT("UObject not found \"%s\" %d"), *ToUE(path), pathNotVirtual);
return null;
}
UTexture *texture = Cast(obj);
@@ -840,9 +836,8 @@ void *CResourceHandlerImage_UE_D3D11::Load(
PopcornFX::CString _fullPath = resourcePath;
if (!pathNotVirtual) // if virtual path
- {
- _fullPath = TCHAR_TO_ANSI(*FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath.Data(), true)); // prepend Pack Path
- }
+ _fullPath = ToPk(FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath, true)); // prepend Pack Path
+
PopcornFX::CFilePath::StripExtensionInPlace(_fullPath);
const PopcornFX::CString &fullPath = _fullPath;
if (!/*PK_VERIFY*/(!fullPath.Empty()))
@@ -1038,9 +1033,8 @@ bool CResourceHandlerImage_UE_D3D11::IsUsed(const PopcornFX::CString &virtualPat
{
PopcornFX::CString _fullPath = virtualPath;
if (!pathNotVirtual) // if virtual path
- {
- _fullPath = TCHAR_TO_ANSI(*FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath.Data(), true)); // prepend Pack Path
- }
+ _fullPath = ToPk(FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath, true)); // prepend Pack Path
+
PopcornFX::CFilePath::StripExtensionInPlace(_fullPath);
const PopcornFX::CString &fullPath = _fullPath;
if (!/*PK_VERIFY*/(!fullPath.Empty()))
@@ -1066,7 +1060,8 @@ bool CResourceHandlerImage_UE_D3D11::RegisterVirtualTexture(const PopcornFX::CSt
PopcornFX::CString _fullPath = virtualPath;
if (!pathNotVirtual) // if virtual path
- _fullPath = TCHAR_TO_ANSI(*FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath.Data(), true)); // prepend Pack Path
+ _fullPath = ToPk(FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath, true)); // prepend Pack Path
+
PopcornFX::CFilePath::StripExtensionInPlace(_fullPath);
const PopcornFX::CString &fullPath = _fullPath;
if (!/*PK_VERIFY*/(!fullPath.Empty()))
@@ -1116,7 +1111,8 @@ bool CResourceHandlerImage_UE_D3D11::UnregisterVirtualTexture(const PopcornFX::C
PopcornFX::CString _fullPath = virtualPath;
if (!pathNotVirtual) // if virtual path
- _fullPath = TCHAR_TO_ANSI(*FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath.Data(), true)); // prepend Pack Path
+ _fullPath = ToPk(FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath, true)); // prepend Pack Path
+
PopcornFX::CFilePath::StripExtensionInPlace(_fullPath);
const PopcornFX::CString &fullPath = _fullPath;
if (!/*PK_VERIFY*/(!fullPath.Empty()))
@@ -1128,12 +1124,12 @@ bool CResourceHandlerImage_UE_D3D11::UnregisterVirtualTexture(const PopcornFX::C
SResourceEntry *foundResource = m_Images.Find(fullPath);
if (foundResource == null)
{
- UE_LOG(LogPopcornFXResourceHandlerImageGPU, Error, TEXT("Virtual Texture GPU not found to Unregister \"%s\""), ANSI_TO_TCHAR(virtualPath.Data()));
+ UE_LOG(LogPopcornFXResourceHandlerImageGPU, Error, TEXT("Virtual Texture GPU not found to Unregister \"%s\""), *ToUE(virtualPath));
return false;
}
if (!PK_VERIFY(foundResource->m_Virtual))
{
- UE_LOG(LogPopcornFXResourceHandlerImageGPU, Error, TEXT("Texture GPU is not a Virtual Texture to Unregister \"%s\""), ANSI_TO_TCHAR(virtualPath.Data()));
+ UE_LOG(LogPopcornFXResourceHandlerImageGPU, Error, TEXT("Texture GPU is not a Virtual Texture to Unregister \"%s\""), *ToUE(virtualPath));
return false;
}
PK_ASSERT(foundResource->m_Image != null);
@@ -1170,7 +1166,7 @@ bool CResourceHandlerImage_UE_D3D11::UnregisterVirtualTexture(const PopcornFX::C
if (resource == null)
{
- UE_LOG(LogPopcornFXResourceHandlerImage, Error, TEXT("Could not load true asset to replace Unregistered Virtual Texture, keeping old datas \"%s\""), ANSI_TO_TCHAR(virtualPath.Data()));
+ UE_LOG(LogPopcornFXResourceHandlerImage, Error, TEXT("Could not load true asset to replace Unregistered Virtual Texture, keeping old datas \"%s\""), *ToUE(virtualPath));
return false;
}
PK_ASSERT(foundResource->m_Image != null);
@@ -1267,10 +1263,10 @@ PopcornFX::CImageGPU_D3D12 *CResourceHandlerImage_UE_D3D12::NewFromPath(const Po
{
PK_NAMEDSCOPEDPROFILE_C("CResourceHandlerImage_UE_D3D12::NewFromPath", POPCORNFX_UE_PROFILER_COLOR);
- UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(path.Data(), pathNotVirtual);
+ UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(path, pathNotVirtual);
if (obj == null)
{
- UE_LOG(LogPopcornFXResourceHandlerImageGPU, Warning, TEXT("UObject not found \"%s\" %d"), ANSI_TO_TCHAR(path.Data()), pathNotVirtual);
+ UE_LOG(LogPopcornFXResourceHandlerImageGPU, Warning, TEXT("UObject not found \"%s\" %d"), *ToUE(path), pathNotVirtual);
return null;
}
UTexture *texture = Cast(obj);
@@ -1318,9 +1314,8 @@ void *CResourceHandlerImage_UE_D3D12::Load(
PopcornFX::CString _fullPath = resourcePath;
if (!pathNotVirtual) // if virtual path
- {
- _fullPath = TCHAR_TO_ANSI(*FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath.Data(), true)); // prepend Pack Path
- }
+ _fullPath = ToPk(FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath, true)); // prepend Pack Path
+
PopcornFX::CFilePath::StripExtensionInPlace(_fullPath);
const PopcornFX::CString &fullPath = _fullPath;
if (!/*PK_VERIFY*/(!fullPath.Empty()))
diff --git a/Source/PopcornFX/Private/Internal/ResourceHandlerMesh_UE.cpp b/Source/PopcornFX/Private/Internal/ResourceHandlerMesh_UE.cpp
index 4328f65..5b410be 100644
--- a/Source/PopcornFX/Private/Internal/ResourceHandlerMesh_UE.cpp
+++ b/Source/PopcornFX/Private/Internal/ResourceHandlerMesh_UE.cpp
@@ -79,10 +79,10 @@ void *CResourceHandlerMesh_UE::Load(
PK_ASSERT(resourceTypeID == PopcornFX::TResourceRouter::ResourceTypeID());
- UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(resourcePath.Data(), pathNotVirtual);
+ UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(resourcePath, pathNotVirtual);
if (obj == null)
{
- UE_LOG(LogPopcornFXResourceHandlerMesh, Warning, TEXT("UObject not found \"%s\""), ANSI_TO_TCHAR(resourcePath.Data()));
+ UE_LOG(LogPopcornFXResourceHandlerMesh, Warning, TEXT("UObject not found \"%s\""), *ToUE(resourcePath));
return null;
}
diff --git a/Source/PopcornFX/Private/Internal/ResourceHandlerVectorField_UE.cpp b/Source/PopcornFX/Private/Internal/ResourceHandlerVectorField_UE.cpp
index d8f4232..e76ed64 100644
--- a/Source/PopcornFX/Private/Internal/ResourceHandlerVectorField_UE.cpp
+++ b/Source/PopcornFX/Private/Internal/ResourceHandlerVectorField_UE.cpp
@@ -119,10 +119,10 @@ PopcornFX::CVectorField *CResourceHandlerVectorField_UE::NewFromPath(const Popco
{
PK_NAMEDSCOPEDPROFILE_C("CResourceHandlerVectorField_UE::NewFromPath", POPCORNFX_UE_PROFILER_COLOR);
- UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(path.Data(), pathNotVirtual);
+ UObject *obj = FPopcornFXPlugin::Get().LoadUObjectFromPkPath(path, pathNotVirtual);
if (obj == null)
{
- UE_LOG(LogPopcornFXResourceHandlerVectorField, Warning, TEXT("UObject not found \"%s\" %d"), ANSI_TO_TCHAR(path.Data()), pathNotVirtual);
+ UE_LOG(LogPopcornFXResourceHandlerVectorField, Warning, TEXT("UObject not found \"%s\" %d"), *ToUE(path), pathNotVirtual);
return null;
}
UVectorFieldStatic *vectorFieldStatic = Cast(obj);
@@ -157,9 +157,8 @@ void *CResourceHandlerVectorField_UE::Load(
PopcornFX::CString _fullPath = resourcePath;
if (!pathNotVirtual) // if virtual path
- {
- _fullPath = TCHAR_TO_ANSI(*FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath.Data(), true)); // prepend Pack Path
- }
+ _fullPath = ToPk(FPopcornFXPlugin::Get().BuildPathFromPkPath(_fullPath, true)); // prepend Pack Path
+
PopcornFX::CFilePath::StripExtensionInPlace(_fullPath);
const PopcornFX::CString &fullPath = _fullPath;
if (!/*PK_VERIFY*/(!fullPath.Empty()))
diff --git a/Source/PopcornFX/Private/Internal/Startup.cpp b/Source/PopcornFX/Private/Internal/Startup.cpp
index fce4298..80ece0f 100644
--- a/Source/PopcornFX/Private/Internal/Startup.cpp
+++ b/Source/PopcornFX/Private/Internal/Startup.cpp
@@ -30,6 +30,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -40,6 +41,7 @@
#include
#include
+#include
#include
#include
@@ -103,16 +105,34 @@ void AddDefaultGlobalListenersOverride(void *userHandle);
#if (KR_PROFILER_ENABLED != 0)
+bool g_RecordEffectNames = false;
+thread_local u32 g_ProfileDepth = 0;
+thread_local s32 g_RecordEffectName_Depth = -1;
struct SUEStatIdKey
{
- const char *m_StatName = null;
+ PopcornFX::COwnedStringView m_StatName;
- SUEStatIdKey() {}
- SUEStatIdKey(const char *statName) : m_StatName(statName) {}
+ SUEStatIdKey() : m_StatName(PopcornFX::CString::EmptyString) { }
+ SUEStatIdKey(const PopcornFX::COwnedStringView &statName)
+ : m_StatName(statName)
+ {
+#if (PK_CALL_SCOPE_ENABLED != 0)
+ if (g_RecordEffectNames &&
+ (g_RecordEffectName_Depth == -1 || g_RecordEffectName_Depth == g_ProfileDepth))
+ {
+ PopcornFX::TMemoryView stack = PopcornFX::CCallContext::ReadStack();
+ if (!stack.Empty() && stack.Last() != null)
+ {
+ g_RecordEffectName_Depth = g_ProfileDepth;
+ m_StatName = PopcornFX::CString::Format("(%s) %s", stack.Last()->Message().Data(), statName.Data());
+ }
+ }
+#endif // (PK_CALL_SCOPE_ENABLED != 0)
+ }
- bool Empty() const { return m_StatName == null; }
+ bool Empty() const { return m_StatName.Empty(); }
- bool operator == (const SUEStatIdKey &other) const { return m_StatName == other.m_StatName; }
+ bool operator == (const SUEStatIdKey &other) const { return m_StatName.View() == other.m_StatName.View(); }
bool operator != (const SUEStatIdKey &other) const { return !(*this == other); }
};
@@ -121,7 +141,7 @@ struct SUEStatIdEntry
SUEStatIdKey m_Key;
TStatId m_StatId;
- SUEStatIdEntry() {}
+ SUEStatIdEntry() { }
SUEStatIdEntry(const SUEStatIdKey &key, TStatId value) : m_Key(key), m_StatId(value) {}
bool operator == (const SUEStatIdKey &other) const { return m_Key == other; }
@@ -137,7 +157,7 @@ class PopcornFX::TTypeHasher
public:
PK_INLINE static u32 Hash(const SUEStatIdKey &value)
{
- return _RawHasher::Hash(value.m_StatName, strlen(value.m_StatName));//sizeof(char*)); // hash pointer
+ return _RawHasher::Hash(value.m_StatName.Data(), value.m_StatName.Length());
}
PK_INLINE static u32 Hash(const SUEStatIdEntry &value)
{
@@ -163,7 +183,7 @@ class PopcornFX::TFastHashMapTraits
template
SUEStatIdEntry const PopcornFX::TFastHashMapTraits::Invalid = SUEStatIdEntry();
template
-SUEStatIdEntry const PopcornFX::TFastHashMapTraits::Probe = SUEStatIdEntry(SUEStatIdKey((const char*)1), TStatId());
+SUEStatIdEntry const PopcornFX::TFastHashMapTraits::Probe = SUEStatIdEntry(SUEStatIdKey("SUEStatIdKey"), TStatId());
struct SPopcornFXThreadProfileContext
{
@@ -269,8 +289,8 @@ namespace
char _buffer[2048];
PrettyFormatAssert_Unsafe(_buffer, sizeof(_buffer), PK_ASSERT_CATCHER_ARGUMENTS);
- const char *perttyMessage = _buffer;
- UE_LOG(LogPopcornFXStartup, Warning, TEXT("%s"), ANSI_TO_TCHAR(perttyMessage));
+ const char *prettyMessage = _buffer;
+ UE_LOG(LogPopcornFXStartup, Warning, TEXT("%s"), UTF8_TO_TCHAR(prettyMessage));
if (!IsClassLoaded() ||
!GetMutableDefault()->EnableAsserts)
@@ -290,7 +310,7 @@ namespace
// UE handles all WinProc messages then wait updates tasks before execute them >>> DEAD LOCK
// GPumpingMessagesOutsideOfMainLoop = true should enqueue messages
TGuardValue pumpMessageGuard(GPumpingMessagesOutsideOfMainLoop, true);
- msgBoxRes = FPlatformMisc::MessageBoxExt(EAppMsgType::CancelRetryContinue, ANSI_TO_TCHAR(perttyMessage), TEXT("PopcornFX Assertion failed"));
+ msgBoxRes = FPlatformMisc::MessageBoxExt(EAppMsgType::CancelRetryContinue, UTF8_TO_TCHAR(prettyMessage), TEXT("PopcornFX Assertion failed"));
}
switch (msgBoxRes)
{
@@ -644,14 +664,14 @@ namespace
if (success)
{
PK_ASSERT(nodeDescriptor != null);
- const SUEStatIdKey key = SUEStatIdKey(nodeDescriptor->m_Name);
+ const SUEStatIdKey key = SUEStatIdKey(PopcornFX::COwnedStringView(PopcornFX::CStringView::FromNullTerminatedString(nodeDescriptor->m_Name)));
PopcornFX::CGuid statId = ctx->m_StatsMap.IndexOf(key);
if (!statId.Valid())
{
- const FString statName = ANSI_TO_TCHAR(nodeDescriptor->m_Name);
+ const FString statName = *ToUE(key.m_StatName.View());
const TStatId newStatId = FDynamicStats::CreateStatId(statName);
- statId = ctx->m_StatsMap.Insert(SUEStatIdEntry(SUEStatIdKey(nodeDescriptor->m_Name), newStatId));
+ statId = ctx->m_StatsMap.Insert(SUEStatIdEntry(key, newStatId));
}
success = statId.Valid();
@@ -675,6 +695,9 @@ namespace
const FMinimalName statMinimalName = dynamicStatId.GetMinimalName(EMemoryOrder::Relaxed);
const FName statName = MinimalNameToName(statMinimalName);
FThreadStats::AddMessage(statName, EStatOperation::CycleScopeStart);
+#if (PK_CALL_SCOPE_ENABLED != 0)
+ ++g_ProfileDepth;
+#endif // (PK_CALL_SCOPE_ENABLED != 0)
}
}
@@ -691,22 +714,24 @@ namespace
POPCORNFX_PROFILERECORD_REENTRY_GUARD(return);
+ --g_ProfileDepth;
+
CWorkerThreadPool_UE *threadPool = static_cast(PopcornFX::Scheduler::ThreadPool().Get());
PK_ASSERT(threadPool != null);
SPopcornFXThreadProfileContext *ctx = threadPool->GetCurrentThreadProfileContext();
if (ctx != null) // Can record
{
PK_ASSERT(nodeDescriptor != null);
- const SUEStatIdKey key = SUEStatIdKey(nodeDescriptor->m_Name);
+ const SUEStatIdKey key = SUEStatIdKey(PopcornFX::COwnedStringView(PopcornFX::CStringView::FromNullTerminatedString(nodeDescriptor->m_Name)));
const PopcornFX::CGuid statId = ctx->m_StatsMap.IndexOf(key);
if (statId.Valid())
{
if (GCycleStatsShouldEmitNamedEvents > 0)
{
-# if PK_HAS_CPUPROFILERTRACE
+#if PK_HAS_CPUPROFILERTRACE
if (UE_TRACE_CHANNELEXPR_IS_ENABLED(CpuChannel))
FCpuProfilerTrace::OutputEndEvent();
-# endif // PK_HAS_CPUPROFILERTRACE
+#endif // PK_HAS_CPUPROFILERTRACE
FPlatformMisc::EndNamedEvent();
}
@@ -714,6 +739,10 @@ namespace
const FMinimalName statMinimalName = dynamicStatId.GetMinimalName(EMemoryOrder::Relaxed);
const FName statName = MinimalNameToName(statMinimalName);
FThreadStats::AddMessage(statName, EStatOperation::CycleScopeEnd);
+#if (PK_CALL_SCOPE_ENABLED != 0)
+ if (g_ProfileDepth == g_RecordEffectName_Depth)
+ g_RecordEffectName_Depth = -1;
+#endif // (PK_CALL_SCOPE_ENABLED != 0)
}
}
}
@@ -763,11 +792,19 @@ bool PopcornFXStartup()
#if (KR_PROFILER_ENABLED != 0)
bool usePopcornFXTP = false;
bool recordProfileMarkers = false;
+ bool recordEffectNames = false;
+
GConfig->GetBool(TEXT("PopcornFX"), TEXT("bUsePopcornFXWTP"), usePopcornFXTP, GEngineIni);
GConfig->GetBool(TEXT("PopcornFX"), TEXT("bRecordProfileMarkers"), recordProfileMarkers, GEngineIni);
+#if (PK_CALL_SCOPE_ENABLED != 0)
+ GConfig->GetBool(TEXT("PopcornFX"), TEXT("bRecordEffectNames"), recordEffectNames, GEngineIni);
+#endif //(PK_CALL_SCOPE_ENABLED != 0)
if (usePopcornFXTP)
+ {
recordProfileMarkers = false;
+ recordEffectNames = false;
+ }
if (recordProfileMarkers)
{
kernelConfiguration.m_ProfilerRecordArg = null;
@@ -776,6 +813,7 @@ bool PopcornFXStartup()
kernelConfiguration.m_ProfilerRecordMemoryTransaction = &PopcornFX_ProfileRecordMemoryTransaction;
kernelConfiguration.m_ProfilerRecordThreadDependency = &PopcornFX_ProfileRecordThreadDependency;
}
+ g_RecordEffectNames = recordEffectNames;
#endif // (KR_PROFILER_ENABLED != 0)
success = true;
@@ -830,7 +868,6 @@ bool PopcornFXStartup()
CCoordinateFrame::SetGlobalFrame(ECoordinateFrame::Frame_LeftHand_Z_Up);
-
// Register load tags
success &= PopcornFX::CParticleManager::AddGlobalConstant(PopcornFX::CParticleManager::SElement("build.tags.low", 20));
success &= PopcornFX::CParticleManager::AddGlobalConstant(PopcornFX::CParticleManager::SElement("build.tags.medium", 21));
diff --git a/Source/PopcornFX/Private/Platforms/PopcornFXPlatformCommon.cpp b/Source/PopcornFX/Private/Platforms/PopcornFXPlatformCommon.cpp
index 04bed7b..31ba019 100644
--- a/Source/PopcornFX/Private/Platforms/PopcornFXPlatformCommon.cpp
+++ b/Source/PopcornFX/Private/Platforms/PopcornFXPlatformCommon.cpp
@@ -237,7 +237,7 @@ bool CompileComputeShaderForAPI( const PopcornFX::CString &source,
if (!modules.Num())
{
- UE_LOG(LogPopcornFXPlatformCommon, Verbose, TEXT("Failed compiling bytecodes for %s: No target shader formats found"), ANSI_TO_TCHAR(apiName.Data()));
+ UE_LOG(LogPopcornFXPlatformCommon, Verbose, TEXT("Failed compiling bytecodes for %s: No target shader formats found"), *ToUE(apiName));
return false;
}
@@ -290,17 +290,17 @@ bool CompileComputeShaderForAPI( const PopcornFX::CString &source,
"// Layer: %s\n"
"// Shader built for API: %s\n"
"// Build tags: %s\n"
- "// Shader kernel stage: %s\n"
- , buildInfos.m_SourceEffect.Empty() ? "" : buildInfos.m_SourceEffect.ToString().Data()
- , buildInfos.m_SourceLayerName.Empty() ? "" : buildInfos.m_SourceLayerName.ToString().Data()
- , apiName.Data()
- , allBuildTags.Data()
- , kKernelStageNames[buildInfos.m_KernelStage]));
+ "// Shader kernel stage: %s\n",
+ buildInfos.m_SourceEffect.Empty() ? "" : buildInfos.m_SourceEffect.ToString().Data(),
+ buildInfos.m_SourceLayerName.Empty() ? "" : buildInfos.m_SourceLayerName.ToString().Data(),
+ apiName.Data(),
+ allBuildTags.Data(),
+ kKernelStageNames[buildInfos.m_KernelStage]));
}
- if (!FFileHelper::SaveStringToFile(ANSI_TO_TCHAR(finalSource.Data()), *srcFilePath))
+ if (!FFileHelper::SaveStringToFile(ToUE(finalSource), *srcFilePath))
{
- UE_LOG(LogPopcornFXPlatformCommon, Verbose, TEXT("Failed compiling bytecodes for %s: couldn't create temp source file"), ANSI_TO_TCHAR(apiName.Data()));
+ UE_LOG(LogPopcornFXPlatformCommon, Verbose, TEXT("Failed compiling bytecodes for %s: couldn't create temp source file"), *ToUE(apiName));
return false;
}
@@ -329,7 +329,7 @@ bool CompileComputeShaderForAPI( const PopcornFX::CString &source,
FShaderCompilerEnvironment mergedEnvironment;
if (!shaderFormat->PreprocessShader(input, mergedEnvironment, preprocessorOutput))
{
- UE_LOG(LogPopcornFXPlatformCommon, Verbose, TEXT("Failed preprocessing shader for %s"), ANSI_TO_TCHAR(apiName.Data()));
+ UE_LOG(LogPopcornFXPlatformCommon, Verbose, TEXT("Failed preprocessing shader for %s"), *ToUE(apiName));
return false;
}
shaderFormat->CompilePreprocessedShader(input, preprocessorOutput, output, workingDirectory);
@@ -350,14 +350,14 @@ bool CompileComputeShaderForAPI( const PopcornFX::CString &source,
if (shaderCodeStart >= fullShaderCodeEnd ||
(fullShaderCodeEnd - shaderCodeStart) < bytecodeMagic.Length())
{
- UE_LOG(LogPopcornFXPlatformCommon, Verbose, TEXT("Failed compiling bytecodes for %s: couldn't find %s header"), ANSI_TO_TCHAR(apiName.Data()), ANSI_TO_TCHAR(bytecodeMagic.Data()));
+ UE_LOG(LogPopcornFXPlatformCommon, Verbose, TEXT("Failed compiling bytecodes for %s: couldn't find %s header"), *ToUE(apiName), *ToUE(bytecodeMagic));
return false;
}
for (u32 i = 0; i < bytecodeMagic.Length(); ++i)
{
if (shaderCodeStart[i] != bytecodeMagic[i])
{
- UE_LOG(LogPopcornFXPlatformCommon, Verbose, TEXT("Failed compiling bytecodes for %s: couldn't find %s header"), ANSI_TO_TCHAR(apiName.Data()), ANSI_TO_TCHAR(bytecodeMagic.Data()));
+ UE_LOG(LogPopcornFXPlatformCommon, Verbose, TEXT("Failed compiling bytecodes for %s: couldn't find %s header"), *ToUE(apiName), *ToUE(bytecodeMagic));
return false;
}
}
@@ -380,14 +380,14 @@ bool CompileComputeShaderForAPI( const PopcornFX::CString &source,
{
const FString errorString = error.GetErrorString();
if (!errorString.IsEmpty())
- UE_LOG(LogPopcornFXPlatformCommon, Verbose, TEXT("Failed compiling bytecodes for %s: '%s'"), ANSI_TO_TCHAR(apiName.Data()), *errorString);
+ UE_LOG(LogPopcornFXPlatformCommon, Verbose, TEXT("Failed compiling bytecodes for %s: '%s'"), *ToUE(apiName), *errorString);
}
return false;
}
}
}
- UE_LOG(LogPopcornFXPlatformCommon, Verbose, TEXT("Failed compiling bytecodes for %s: couldn't find shader compiler module"), ANSI_TO_TCHAR(apiName.Data()));
+ UE_LOG(LogPopcornFXPlatformCommon, Verbose, TEXT("Failed compiling bytecodes for %s: couldn't find shader compiler module"), *ToUE(apiName));
return false;
}
#endif // (PK_COMPILE_GPU != 0)
diff --git a/Source/PopcornFX/Private/PopcornFXFunctions.cpp b/Source/PopcornFX/Private/PopcornFXFunctions.cpp
index 1fa6374..7526154 100644
--- a/Source/PopcornFX/Private/PopcornFXFunctions.cpp
+++ b/Source/PopcornFX/Private/PopcornFXFunctions.cpp
@@ -177,7 +177,7 @@ bool UPopcornFXFunctions::IsTextureCPUInUse(const FString &virtualPath)
if (!PK_VERIFY(ihandler != null))
return false;
CResourceHandlerImage_UE *handler = PopcornFX::checked_cast(ihandler);
- const PopcornFX::CString virtPath = TCHAR_TO_ANSI(*virtualPath);
+ const PopcornFX::CString virtPath = ToPk(virtualPath);
return handler->IsUsed(virtPath, false);
}
@@ -189,7 +189,7 @@ bool UPopcornFXFunctions::IsTextureGPUInUse(const FString &virtualPath)
if (!PK_VERIFY(ihandler != null))
return false;
CResourceHandlerImage_UE_D3D11 *handler = PopcornFX::checked_cast(ihandler);
- const PopcornFX::CString virtPath = TCHAR_TO_ANSI(*virtualPath);
+ const PopcornFX::CString virtPath = ToPk(virtualPath);
return handler->IsUsed(virtPath, false);
#else
return false;
@@ -212,8 +212,7 @@ bool UPopcornFXFunctions::RegisterVirtualTextureOverride_CPU_FloatR(const FStri
if (!PK_VERIFY(ihandler != null))
return false;
CResourceHandlerImage_UE *handler = PopcornFX::checked_cast(ihandler);
-
- const PopcornFX::CString virtPath = TCHAR_TO_ANSI(*virtualPath);
+ const PopcornFX::CString virtPath = ToPk(virtualPath);
const PopcornFX::CUint2 size(width, height);
PK_ASSERT(pixels.GetTypeSize() == sizeof(float));
@@ -239,9 +238,9 @@ bool UPopcornFXFunctions::RegisterVirtualTextureOverride_CPU_FloatRGBA(const FS
if (!PK_VERIFY(ihandler != null))
return false;
CResourceHandlerImage_UE *handler = PopcornFX::checked_cast(ihandler);
-
- const PopcornFX::CString virtPath = TCHAR_TO_ANSI(*virtualPath);
+ const PopcornFX::CString virtPath = ToPk(virtualPath);
const PopcornFX::CUint2 size(width, height);
+
PK_ASSERT(pixels.GetTypeSize() == sizeof(FLinearColor));
return handler->RegisterVirtualTexture(
virtPath, false,
@@ -258,7 +257,7 @@ bool UPopcornFXFunctions::UnregisterVirtualTextureOverride_CPU(const FString &v
PopcornFX::IResourceHandler *ihandler = PopcornFX::Resource::DefaultManager()->FindHandler();
if (!PK_VERIFY(ihandler != null))
return false;
- const PopcornFX::CString virtPath = TCHAR_TO_ANSI(*virtualPath);
+ const PopcornFX::CString virtPath = ToPk(virtualPath);
CResourceHandlerImage_UE *handler = PopcornFX::checked_cast(ihandler);
return handler->UnregisterVirtualTexture(virtPath, false);
}
@@ -276,12 +275,8 @@ bool UPopcornFXFunctions::RegisterVirtualTextureOverride_GPU(const FString &vir
if (!PK_VERIFY(ihandler != null))
return false;
CResourceHandlerImage_UE_D3D11 *handler = PopcornFX::checked_cast(ihandler);
-
- const PopcornFX::CString virtPath = TCHAR_TO_ANSI(*virtualPath);
-
- return handler->RegisterVirtualTexture(
- virtPath, false,
- texture);
+ const PopcornFX::CString virtPath = ToPk(virtualPath);
+ return handler->RegisterVirtualTexture(virtPath, false, texture);
#else
return false;
#endif
@@ -294,7 +289,7 @@ bool UPopcornFXFunctions::UnregisterVirtualTextureOverride_GPU(const FString &v
PopcornFX::IResourceHandler *ihandler = PopcornFX::Resource::DefaultManager()->FindHandler();
if (!PK_VERIFY(ihandler != null))
return false;
- const PopcornFX::CString virtPath = TCHAR_TO_ANSI(*virtualPath);
+ const PopcornFX::CString virtPath = ToPk(virtualPath);
CResourceHandlerImage_UE_D3D11 *handler = PopcornFX::checked_cast(ihandler);
return handler->UnregisterVirtualTexture(virtPath, false);
#else
diff --git a/Source/PopcornFX/Private/PopcornFXHelper.cpp b/Source/PopcornFX/Private/PopcornFXHelper.cpp
index b745fba..2f651b1 100644
--- a/Source/PopcornFX/Private/PopcornFXHelper.cpp
+++ b/Source/PopcornFX/Private/PopcornFXHelper.cpp
@@ -7,10 +7,13 @@
#include "PopcornFXSDK.h"
#include
+#include
#if WITH_EDITOR
# include "Misc/MessageDialog.h"
#endif
+//----------------------------------------------------------------------------
+
static const TCHAR *kHumanStr[] = {
TEXT(" "), TEXT("k"), TEXT("m"), TEXT("g"), TEXT("t")
};
@@ -37,6 +40,36 @@ const TCHAR *HumanReadS(float v, u32 base)
return kHumanStr[i];
}
+//----------------------------------------------------------------------------
+
+PopcornFX::CString ToPk(const FString &str)
+{
+ return TCHAR_TO_UTF8(*str);
+}
+
+//----------------------------------------------------------------------------
+
+FString ToUE(const PopcornFX::CString &str)
+{
+ return UTF8_TO_TCHAR(str.Data());
+}
+
+//----------------------------------------------------------------------------
+
+FString ToUE(const PopcornFX::CStringView &str)
+{
+ return UTF8_TO_TCHAR(str.Data());
+}
+
+//----------------------------------------------------------------------------
+
+FString ToUE(const PopcornFX::CStringUnicode &str)
+{
+ return FString((const UTF16CHAR*)str.Data());
+}
+
+//----------------------------------------------------------------------------
+
#if WITH_EDITOR
EAppReturnType::Type OpenMessageBox(EAppMsgType::Type messageType, const FText& message, const FText& title)
{
@@ -47,3 +80,5 @@ EAppReturnType::Type OpenMessageBox(EAppMsgType::Type messageType, const FText&
#endif // (ENGINE_MAJOR_VERSION == 5) && (ENGINE_MINOR_VERSION >= 3)
}
#endif
+
+//----------------------------------------------------------------------------
diff --git a/Source/PopcornFX/Private/PopcornFXHelper.h b/Source/PopcornFX/Private/PopcornFXHelper.h
index 3eb748c..5ad0645 100644
--- a/Source/PopcornFX/Private/PopcornFXHelper.h
+++ b/Source/PopcornFX/Private/PopcornFXHelper.h
@@ -14,10 +14,15 @@
#include "Math/IntPoint.h"
#include "Math/Color.h"
#include "Math/Box.h"
+#include "Containers/UnrealString.h"
#include "PopcornFXSDK.h"
#include
+__PK_API_BEGIN
+class CStringUnicode; // Forward-declare
+__PK_API_END
+
#ifndef POPCORNFX_UE_PROFILER_COLOR
#define POPCORNFX_UE_PROFILER_COLOR CFloat3(1.0f, 0.5f, 0.0f)
#endif
@@ -35,6 +40,7 @@ PK_FORCEINLINE const _OutType &_Reinterpret(const _InType &vec)
PK_FORCEINLINE const CFloat4 &ToPk(const FLinearColor &vec) { return _Reinterpret(vec); }
PK_FORCEINLINE const CInt2 &ToPk(const FIntPoint& point) { return _Reinterpret(point); }
+PK_FORCEINLINE const CUint4 &ToPk(const FIntVector4 &vec) { return _Reinterpret(vec); }
// UE5 LWC: Keep reinterpret casts whenever possible
PK_FORCEINLINE const FVector3f &ToUE(const CFloat3 &vec) { return _Reinterpret(vec); }
@@ -93,6 +99,11 @@ PK_FORCEINLINE CFloat3 &ToPkRef(FVector3f &vec)
return *reinterpret_cast(&vec);
}
+PopcornFX::CString ToPk(const FString &str);
+FString ToUE(const PopcornFX::CString &str);
+FString ToUE(const PopcornFX::CStringView &str);
+FString ToUE(const PopcornFX::CStringUnicode &str);
+
float HumanReadF(float v, u32 base = 1024);
const TCHAR *HumanReadS(float v, u32 base = 1024);
static inline float SafeRcp(float v) { return v == 0.f ? 0.f : 1.f / v; }
diff --git a/Source/PopcornFX/Private/PopcornFXPlugin.cpp b/Source/PopcornFX/Private/PopcornFXPlugin.cpp
index 84be13b..3236167 100644
--- a/Source/PopcornFX/Private/PopcornFXPlugin.cpp
+++ b/Source/PopcornFX/Private/PopcornFXPlugin.cpp
@@ -595,7 +595,7 @@ void FPopcornFXPlugin::_UpdateSimInterfaceBindings(const FString &libraryDir)
{
simInterfaceMapper->Clear();
- const PopcornFX::CString pkLibDir = TCHAR_TO_ANSI(*libraryDir);
+ const PopcornFX::CString pkLibDir = ToPk(libraryDir);
for (const SPopcornFXSimulationInterface &simInterface : kSimInterfaces)
{
@@ -639,10 +639,50 @@ PopcornFX::PFilePack FPopcornFXPlugin::FilePack()
//----------------------------------------------------------------------------
+#if WITH_EDITOR
+void FPopcornFXPlugin::RefreshFromEditorSettings()
+{
+ UPopcornFXSettingsEditor *editorSettings = GetMutableDefault();
+ check(editorSettings);
+ m_SettingsEditor = editorSettings;
+
+ if (m_BakeContext != null &&
+ m_BakeContext->m_BakeContext != null &&
+ m_BakeContext->m_BakeFSController != null)
+ {
+ m_BakeContext->m_BakeFSController->UnmountAllPacks();
+ if (PK_VERIFY(m_BakeContext->m_BakeFSController->MountPack(ToPk(m_SettingsEditor->AbsSourcePackRootDir)) != null))
+ {
+ if (editorSettings->bSourcePackFound)
+ {
+ // Only update bindings when pack is found. we don't want to spam errors for users not having the source pack available (which is legit).
+ // No source pack -> no effects import
+ {
+ // New project, lib dir might have changed, we need to update the sim interface bindings
+ FString libraryDir = editorSettings->AbsSourcePackLibraryDir;
+ if (PK_VERIFY(FPaths::MakePathRelativeTo(libraryDir, *editorSettings->AbsSourcePackRootDir)))
+ _UpdateSimInterfaceBindings(libraryDir);
+ else
+ UE_LOG(LogPopcornFXPlugin, Error, TEXT("Couldn't make LibraryDir relative path from source pack root directory. Sim interfaces will not be bound"));
+ }
+ }
+ }
+ }
+}
+#endif // WITH_EDITOR
+
+//----------------------------------------------------------------------------
+
bool FPopcornFXPlugin::LoadSettingsAndPackIFN()
{
if (!m_LaunchedPopcornFX) // could happen on shutdown
return false;
+
+#if WITH_EDITOR
+ // Lazy init IFN
+ BakeContext();
+#endif
+
if (m_Settings != null)
{
#if WITH_EDITOR
@@ -652,37 +692,7 @@ bool FPopcornFXPlugin::LoadSettingsAndPackIFN()
return m_RootPackLoaded;
}
#if WITH_EDITOR
- {
- UPopcornFXSettingsEditor *editorSettings = GetMutableDefault();
- check(editorSettings);
- editorSettings->UpdateSourcePack();
- m_SettingsEditor = editorSettings;
-
- // Lazy init IFN
- BakeContext();
- if (m_BakeContext != null &&
- m_BakeContext->m_BakeContext != null &&
- m_BakeContext->m_BakeFSController != null)
- {
- m_BakeContext->m_BakeFSController->UnmountAllPacks();
- if (PK_VERIFY(m_BakeContext->m_BakeFSController->MountPack(TCHAR_TO_ANSI(*m_SettingsEditor->SourcePackRootDir)) != null))
- {
- if (editorSettings->bSourcePackFound)
- {
- // Only update bindings when pack is found. we don't want to spam errors for users not having the source pack available (which is legit).
- // No source pack -> no effects import
- {
- // New project, lib dir might have changed, we need to update the sim interface bindings
- FString libraryDir = editorSettings->SourcePackLibraryDir;
- if (PK_VERIFY(FPaths::MakePathRelativeTo(libraryDir, *editorSettings->SourcePackRootDir)))
- _UpdateSimInterfaceBindings(libraryDir);
- else
- UE_LOG(LogPopcornFXPlugin, Error, TEXT("Couldn't make LibraryDir relative path from source pack root directory. Sim interfaces will not be bound"));
- }
- }
- }
- }
- }
+ RefreshFromEditorSettings();
PK_ASSERT(m_SettingsEditor != null);
#endif
m_Settings = GetMutableDefault();
@@ -697,14 +707,14 @@ bool FPopcornFXPlugin::LoadSettingsAndPackIFN()
{
PK_ASSERT(m_FilePack == null);
- const PopcornFX::CString packPath = TCHAR_TO_ANSI(*m_Settings->PackMountPoint);
+ const PopcornFX::CString packPath = ToPk(m_Settings->PackMountPoint);
PK_ASSERT(PopcornFX::File::DefaultFileSystem() != null);
PopcornFX::PFilePack pack = PopcornFX::File::DefaultFileSystem()->MountPack(packPath);
if (!PK_VERIFY(pack != null))
return false;
m_FilePack = pack;
- m_FilePackPath = ANSI_TO_TCHAR(m_FilePack->Path().Data());
+ m_FilePackPath = ToUE(m_FilePack->Path());
m_FilePackPath /= "";
PK_ASSERT(m_FilePackPath[m_FilePackPath.Len() - 1] == '/');
m_RootPackLoaded = true;
@@ -726,17 +736,20 @@ bool FPopcornFXPlugin::LoadSettingsAndPackIFN()
FString FPopcornFXPlugin::BuildPathFromPkPath(const char *pkPath, bool prependPackPath)
{
- PK_NAMEDSCOPEDPROFILE_C("FPopcornFXPlugin::BuildPathFromPkPath", POPCORNFX_UE_PROFILER_COLOR);
+ return BuildPathFromPkPath(PopcornFX::CString(pkPath), prependPackPath);
+}
- if (!LoadSettingsAndPackIFN())
- return FString();
+//----------------------------------------------------------------------------
- if (!PK_VERIFY(FilePack() != null))
- {
+FString FPopcornFXPlugin::BuildPathFromPkPath(const PopcornFX::CString &pkPath, bool prependPackPath)
+{
+ PK_NAMEDSCOPEDPROFILE_C("FPopcornFXPlugin::BuildPathFromPkPath", POPCORNFX_UE_PROFILER_COLOR);
+
+ if (!LoadSettingsAndPackIFN() ||
+ !PK_VERIFY(FilePack() != null))
return FString();
- }
- PopcornFX::CString path(PopcornFX::CStringContainer::NewResizable(pkPath));
+ PopcornFX::CString path = pkPath;
if (path.Empty())
return FString();
if (prependPackPath)
@@ -764,8 +777,7 @@ FString FPopcornFXPlugin::BuildPathFromPkPath(const char *pkPath, bool prependP
else
path.Append(path.Data(), path.Length() - 1 /*the '.'*/);
- FString p = path.Data();
- return p;
+ return ToUE(path);
}
//----------------------------------------------------------------------------
@@ -815,7 +827,8 @@ PopcornFX::PBaseObjectFile FPopcornFXPlugin::LoadPkFile(const UPopcornFXFile *f
const PopcornFX::CString pkPath = file->PkPath();
if (pkPath.Empty())
return null;
- PopcornFX::PBaseObjectFile pkFile = PopcornFX::HBO::g_Context->LoadFile(pkPath.Data(), reload);
+
+ PopcornFX::PBaseObjectFile pkFile = PopcornFX::HBO::g_Context->LoadFile(pkPath, reload);
if (pkFile != null)
_SetupFile(file, pkFile);
return pkFile;
@@ -847,7 +860,7 @@ UPopcornFXFile *FPopcornFXPlugin::GetPopcornFXFile(const PopcornFX::CBaseObject
if (boFile->InternalUserData() == null)
{
- UObject *object = LoadUObjectFromPkPath(boFile->Path().Data(), false);
+ UObject *object = LoadUObjectFromPkPath(boFile->Path(), false);
if (object == null)
return null;
UPopcornFXFile *file = Cast(object);
@@ -859,16 +872,14 @@ UPopcornFXFile *FPopcornFXPlugin::GetPopcornFXFile(const PopcornFX::CBaseObject
UPopcornFXFile *file = reinterpret_cast(boFile->InternalUserData());
- PK_ASSERT(Cast(LoadUObjectFromPkPath(boFile->Path().Data(), false)) == file);
-
+ PK_ASSERT(Cast(LoadUObjectFromPkPath(boFile->Path(), false)) == file);
check(file == null || file->IsBaseObject());
-
return file;
}
//----------------------------------------------------------------------------
-UObject *FPopcornFXPlugin::LoadUObjectFromPkPath(const char *pkPath, bool pathNotVirtual)
+UObject *FPopcornFXPlugin::LoadUObjectFromPkPath(const PopcornFX::CString &pkPath, bool pathNotVirtual)
{
LLM_SCOPE(ELLMTag::Particles);
if (!m_LaunchedPopcornFX) // could happen at shutdown
@@ -879,22 +890,22 @@ UObject *FPopcornFXPlugin::LoadUObjectFromPkPath(const char *pkPath, bool pathN
#if WITH_EDITOR
// Editor only (baking code is the only place where this occurs)
- PopcornFX::CString ext = PopcornFX::CFilePath::ExtractExtension(pkPath);
+ PopcornFX::CStringView ext = PopcornFX::CFilePath::ExtractExtension(PopcornFX::CStringView(pkPath));
if (ext == "pkcf")
return null;
#endif // WITH_EDITOR
- //
// about BuildPathFromPkPath(..., __ bool prependPackPath __):
- //
// if pathNotVirtual: // real path
// already prepended with "/Game/"
// else // virtual path
// no "/Game/", just "Particles/": so prendpend "/Game/"
- FString p = BuildPathFromPkPath(pkPath, !pathNotVirtual);
+
+ FString p = BuildPathFromPkPath(pkPath, !pathNotVirtual);
if (p.IsEmpty())
return null;
- UObject *anyObject = ::FindObject(null, *p);
+
+ UObject *anyObject = ::FindObject(null, *p);
if (anyObject == null)
anyObject = ::LoadObject(null, *p);
if (anyObject != null)
@@ -935,7 +946,7 @@ void FPopcornFXPlugin::NotifyObjectChanged(UObject *object)
if (!objectPath.StartsWith(m_FilePackPath))
return;
const FString virtualPath = objectPath.Right(objectPath.Len() - m_FilePackPath.Len());
- const PopcornFX::CString virtualPathPk(TCHAR_TO_ANSI(*virtualPath));
+ const PopcornFX::CString virtualPathPk(ToPk(virtualPath));
PopcornFX::Resource::DefaultManager()->NotifyResourceChanged(PopcornFX::CFilePackPath(m_FilePack, virtualPathPk));
}
diff --git a/Source/PopcornFX/Private/PopcornFXPlugin.h b/Source/PopcornFX/Private/PopcornFXPlugin.h
index 148926b..e077896 100644
--- a/Source/PopcornFX/Private/PopcornFXPlugin.h
+++ b/Source/PopcornFX/Private/PopcornFXPlugin.h
@@ -117,6 +117,7 @@ class FPopcornFXPlugin : public IPopcornFXPlugin
* return the corresponding path for Unreal assets
*/
FString BuildPathFromPkPath(const char *pkPath, bool prependPackPath);
+ FString BuildPathFromPkPath(const PopcornFX::CString &pkPath, bool prependPackPath);
PopcornFX::PBaseObjectFile FindPkFile(const UPopcornFXFile *file);
PopcornFX::PBaseObjectFile LoadPkFile(const UPopcornFXFile *file, bool reload = false);
@@ -124,7 +125,7 @@ class FPopcornFXPlugin : public IPopcornFXPlugin
UPopcornFXFile *GetPopcornFXFile(const PopcornFX::CBaseObjectFile *file);
- UObject *LoadUObjectFromPkPath(const char *pkPath, bool notVirtual);
+ UObject *LoadUObjectFromPkPath(const PopcornFX::CString &pkPath, bool notVirtual);
void NotifyObjectChanged(UObject *object);
@@ -194,7 +195,7 @@ class FPopcornFXPlugin : public IPopcornFXPlugin
class FRHITexture2D *SceneDepthTexture() { return m_SceneDepthTexture; }
class FRHITexture2D *SceneNormalTexture() { return m_SceneNormalTexture; }
#if (PK_GPU_D3D11 != 0)
- PopcornFX::SParticleStreamBuffer_D3D11 &ViewConstantBuffer_D3D11() { return m_ViewConstantBuffer_D3D11; }
+ PopcornFX::SBuffer_D3D11 &ViewConstantBuffer_D3D11() { return m_ViewConstantBuffer_D3D11; }
#endif // (PK_GPU_D3D11 != 0)
void SetViewUniformData(const SUEViewUniformData &viewUniformData) { m_ViewUniformData = viewUniformData; }
const SUEViewUniformData &ViewUniformData() const { return m_ViewUniformData; }
@@ -204,6 +205,10 @@ class FPopcornFXPlugin : public IPopcornFXPlugin
void ActivateEffectsProfiler(bool activate);
bool EffectsProfilerActive() const;
+#if WITH_EDITOR
+ void RefreshFromEditorSettings();
+#endif
+
private:
bool LoadSettingsAndPackIFN();
#if 0
@@ -231,7 +236,7 @@ class FPopcornFXPlugin : public IPopcornFXPlugin
class FRHITexture2D *m_SceneDepthTexture;
class FRHITexture2D *m_SceneNormalTexture;
#if (PK_GPU_D3D11 != 0)
- PopcornFX::SParticleStreamBuffer_D3D11 m_ViewConstantBuffer_D3D11;
+ PopcornFX::SBuffer_D3D11 m_ViewConstantBuffer_D3D11;
#endif // (PK_GPU_D3D11 != 0)
SUEViewUniformData m_ViewUniformData;
FPostOpaqueRenderDelegate m_PostOpaqueRenderDelegate;
diff --git a/Source/PopcornFX/Private/PopcornFXSettings.cpp b/Source/PopcornFX/Private/PopcornFXSettings.cpp
index 03dcd1b..134371a 100644
--- a/Source/PopcornFX/Private/PopcornFXSettings.cpp
+++ b/Source/PopcornFX/Private/PopcornFXSettings.cpp
@@ -118,7 +118,7 @@ UMaterialInterface *UPopcornFXSettings::GetConfigDefaultMaterial(uint32 ePopcorn
if (mat == null)
{
UE_LOG(LogPopcornFXSettings, Warning, TEXT("PopcornFX Config %s is invalid, falling back on PopcornFX Plugin's default one %s"), *FString(kMaterialTypeNames[materialType]), *FString(kPluginsDefaultMaterials[materialType]));
- mat = ::LoadObject(null, ANSI_TO_TCHAR(kPluginsDefaultMaterials[materialType]));
+ mat = ::LoadObject(null, UTF8_TO_TCHAR(kPluginsDefaultMaterials[materialType]));
PK_ASSERT(mat != null);
}
return mat;
diff --git a/Source/PopcornFX/Private/PopcornFXSettingsEditor.cpp b/Source/PopcornFX/Private/PopcornFXSettingsEditor.cpp
index 59ea7a3..f997664 100644
--- a/Source/PopcornFX/Private/PopcornFXSettingsEditor.cpp
+++ b/Source/PopcornFX/Private/PopcornFXSettingsEditor.cpp
@@ -8,7 +8,6 @@
#include "PopcornFXPlugin.h"
#if WITH_EDITOR
-
# include "PopcornFXSDK.h"
# include
@@ -39,6 +38,7 @@ UPopcornFXSettingsEditor::UPopcornFXSettingsEditor(const FObjectInitializer& PCI
, bRestartEmitterWhenAttributesChanged(false)
#endif // WITH_EDITORONLY_DATA
{
+#if WITH_EDITORONLY_DATA
static const FString kDefaultIncludes[] = {
"*.pkfx", "*.pkat",
"*.fbx",
@@ -52,7 +52,7 @@ UPopcornFXSettingsEditor::UPopcornFXSettingsEditor(const FObjectInitializer& PCI
"Editor/*",
};
static uint32 kDefaultExcludesCount = sizeof(kDefaultExcludes) / sizeof(*kDefaultExcludes);
-#if WITH_EDITORONLY_DATA
+
AutoReimportMirrorPackWildcards.SetNum(kDefaultIncludesCount + kDefaultExcludesCount);
uint32 configwci = 0;
for (uint32 i = 0; i < kDefaultIncludesCount; ++i, ++configwci)
@@ -68,20 +68,25 @@ UPopcornFXSettingsEditor::UPopcornFXSettingsEditor(const FObjectInitializer& PCI
#endif // WITH_EDITORONLY_DATA
}
-#if WITH_EDITOR
-
//----------------------------------------------------------------------------
-void UPopcornFXSettingsEditor::PostLoad()
+#if WITH_EDITORONLY_DATA
+void UPopcornFXSettingsEditor::PostInitProperties()
{
- Super::PostLoad();
+ Super::PostInitProperties();
- // /!\ not actualy called when GetDefault is used
- UpdateSourcePack();
+ AbsSourcePackProjectFile = SourcePackProjectFile.IsEmpty() ? FString() : FPaths::ConvertRelativePathToFull(SourcePackProjectFile);
+ AbsSourcePackRootDir = SourcePackRootDir.IsEmpty() ? FString() : FPaths::ConvertRelativePathToFull(SourcePackRootDir);
+ AbsSourcePackLibraryDir = SourcePackLibraryDir.IsEmpty() ? FString() : FPaths::ConvertRelativePathToFull(SourcePackLibraryDir);
+ AbsSourcePackThumbnailsDir = SourcePackThumbnailsDir.IsEmpty() ? FString() : FPaths::ConvertRelativePathToFull(SourcePackThumbnailsDir);
+ AbsSourcePackCacheDir = SourcePackCacheDir.IsEmpty() ? FString() : FPaths::ConvertRelativePathToFull(SourcePackCacheDir);
}
+#endif // WITH_EDITORONLY_DATA
//----------------------------------------------------------------------------
+#if WITH_EDITOR
+
void UPopcornFXSettingsEditor::PreEditChange(FProperty *propertyAboutToChange)
{
Super::PreEditChange(propertyAboutToChange);
@@ -90,11 +95,11 @@ void UPopcornFXSettingsEditor::PreEditChange(FProperty *propertyAboutToChange)
{
if (propertyAboutToChange->GetName() == GET_MEMBER_NAME_STRING_CHECKED(UPopcornFXSettingsEditor, ImportSourcePack))
{
- SourcePackRootDir_ToRemove = SourcePackRootDir;
+ SourcePackRootDir_ToRemove = AbsSourcePackRootDir;
}
else if (propertyAboutToChange->GetName() == GET_MEMBER_NAME_STRING_CHECKED(UPopcornFXSettingsEditor, bAddSourcePackToMonitoredDirectories))
{
- SourcePackRootDir_ToRemove = SourcePackRootDir;
+ SourcePackRootDir_ToRemove = AbsSourcePackRootDir;
}
}
}
@@ -184,6 +189,8 @@ static bool operator == (const FAutoReimportWildcard &a, const FMyAutoReimportW
return a.Wildcard == b.Wildcard && a.bInclude == b.bInclude;
}
+//----------------------------------------------------------------------------
+
void UPopcornFXSettingsEditor::_CopyWildcards(FAutoReimportDirectoryConfig &config)
{
const u32 wildcardCount = AutoReimportMirrorPackWildcards.Num();
@@ -200,6 +207,8 @@ void UPopcornFXSettingsEditor::_CopyWildcards(FAutoReimportDirectoryConfig &conf
}
}
+//----------------------------------------------------------------------------
+
bool UPopcornFXSettingsEditor::_HasSameWildcards(const FAutoReimportDirectoryConfig &config)
{
const u32 wildcardCount = config.Wildcards.Num();
@@ -213,6 +222,8 @@ bool UPopcornFXSettingsEditor::_HasSameWildcards(const FAutoReimportDirectoryCon
return true;
}
+//----------------------------------------------------------------------------
+
void UPopcornFXSettingsEditor::ForceUpdateAutoReimportSettings()
{
UEditorLoadingSavingSettings *loadSaveSettings = GetMutableDefault();
@@ -223,18 +234,18 @@ void UPopcornFXSettingsEditor::ForceUpdateAutoReimportSettings()
// Remove old one IFN
if (!SourcePackRootDir_ToRemove.IsEmpty() &&
- SourcePackRootDir_ToRemove != SourcePackRootDir)
+ SourcePackRootDir_ToRemove != AbsSourcePackRootDir)
{
notify |= _RemoveAutoReimport(SourcePackRootDir_ToRemove);
}
SourcePackRootDir_ToRemove.Empty();
- const bool autoReimport = !SourcePackRootDir.IsEmpty() && bAddSourcePackToMonitoredDirectories;
+ const bool autoReimport = !AbsSourcePackRootDir.IsEmpty() && bAddSourcePackToMonitoredDirectories;
if (!autoReimport)
{
// remove everything !
- notify |= _RemoveAutoReimport(SourcePackRootDir);
+ notify |= _RemoveAutoReimport(AbsSourcePackRootDir);
}
else
{
@@ -250,7 +261,7 @@ void UPopcornFXSettingsEditor::ForceUpdateAutoReimportSettings()
for (int32 i = 0; i < loadSaveSettings->AutoReimportDirectorySettings.Num(); ++i)
{
const FAutoReimportDirectoryConfig &config = loadSaveSettings->AutoReimportDirectorySettings[i];
- if (config.SourceDirectory != SourcePackRootDir)
+ if (config.SourceDirectory != AbsSourcePackRootDir)
continue;
++foundCount;
if (foundCount > expectedCount)
@@ -273,12 +284,12 @@ void UPopcornFXSettingsEditor::ForceUpdateAutoReimportSettings()
if (hasChanged)
{
// remove all
- notify |= _RemoveAutoReimport(SourcePackRootDir);
+ notify |= _RemoveAutoReimport(AbsSourcePackRootDir);
const int32 diri = loadSaveSettings->AutoReimportDirectorySettings.Add(FAutoReimportDirectoryConfig());
check(diri >= 0);
FAutoReimportDirectoryConfig &config = loadSaveSettings->AutoReimportDirectorySettings[diri];
- config.SourceDirectory = SourcePackRootDir;
+ config.SourceDirectory = AbsSourcePackRootDir;
config.MountPoint = settings->PackMountPoint;
_CopyWildcards(config);
@@ -291,53 +302,58 @@ void UPopcornFXSettingsEditor::ForceUpdateAutoReimportSettings()
_NotifyReimportManager();
}
-
//----------------------------------------------------------------------------
-static const FString kOldPopcornFXProjectFileName = "PopcornProject.xml";
-static const FString kPopcornFXProjectFileName = "PopcornProject.pkproj";
+static const FString kOldPopcornFXProjectFileName = "PopcornProject.xml";
+static const FString kPopcornFXProjectFileName = "PopcornProject.pkproj";
-// static
-FString UPopcornFXSettingsEditor::FixAndAppendPopcornFXProjectFileName(const FString &path)
+static FString FixAndAppendPopcornFXProjectFileName(const FString &path)
{
// fix old path
if (path.EndsWith(kOldPopcornFXProjectFileName))
{
- FString newPath = path;
+ FString newPath = path;
newPath.RemoveAt(newPath.Len() - kOldPopcornFXProjectFileName.Len(), kOldPopcornFXProjectFileName.Len(), false);
newPath /= kPopcornFXProjectFileName;
return newPath;
}
- // append ifn
+ // append IFN
if (!path.EndsWith(kPopcornFXProjectFileName))
return path / kPopcornFXProjectFileName;
return path;
}
+//----------------------------------------------------------------------------
+
void UPopcornFXSettingsEditor::UpdateSourcePack()
{
// if not in editor, do nothing, keep saved values
-
SourcePackProjectFile.Empty();
SourcePackRootDir.Empty();
SourcePackLibraryDir.Empty();
- SourcePackCacheDir.Empty();
SourcePackThumbnailsDir.Empty();
- bSourcePackFound = 0;
+ SourcePackCacheDir.Empty();
+
+ AbsSourcePackProjectFile.Empty();
+ AbsSourcePackRootDir.Empty();
+ AbsSourcePackLibraryDir.Empty();
+ AbsSourcePackThumbnailsDir.Empty();
+ AbsSourcePackCacheDir.Empty();
+
+ bSourcePackFound = false;
if (!ImportSourcePack.IsEmpty())
{
- FString projectFile = ImportSourcePack;
+ FString projectFile = ImportSourcePack;
FPaths::NormalizeFilename(projectFile);
FPaths::RemoveDuplicateSlashes(projectFile);
-
projectFile = FixAndAppendPopcornFXProjectFileName(projectFile);
if (FPaths::IsRelative(projectFile))
projectFile = FPaths::ProjectDir() / projectFile;
SourcePackProjectFile = projectFile;
- int32 lastSlash = projectFile.Find("/", ESearchCase::CaseSensitive, ESearchDir::FromEnd);
+ int32 lastSlash = projectFile.Find("/", ESearchCase::CaseSensitive, ESearchDir::FromEnd);
if (lastSlash != INDEX_NONE)
SourcePackRootDir = projectFile.Left(lastSlash + 1);
SourcePackLibraryDir = SourcePackRootDir / "Library";
@@ -346,29 +362,26 @@ void UPopcornFXSettingsEditor::UpdateSourcePack()
if (FPaths::FileExists(projectFile))
{
- bSourcePackFound = 1;
-
TArray fileContent;
if (FFileHelper::LoadFileToArray(fileContent, *projectFile))
{
PopcornFX::CConstMemoryStream stream(fileContent.GetData(), fileContent.Num());
-
- PopcornFX::HBO::CContext *localBoContext = PK_NEW(PopcornFX::HBO::CContext());
+ PopcornFX::HBO::CContext *localBoContext = PK_NEW(PopcornFX::HBO::CContext());
if (PK_VERIFY(localBoContext != null))
{
PopcornFX::PProjectSettings projectSettings = PopcornFX::CProjectSettings::LoadFromStream(stream, localBoContext);
if (projectSettings != null && projectSettings->General() != null)
{
- bSourcePackFound = 1;
+ bSourcePackFound = true;
if (!projectSettings->General()->RootDir().Empty())
- SourcePackRootDir /= ANSI_TO_TCHAR(projectSettings->General()->RootDir().Data());
+ SourcePackRootDir /= ToUE(projectSettings->General()->RootDir());
if (!projectSettings->General()->LibraryDir().Empty())
- SourcePackLibraryDir = SourcePackRootDir / ANSI_TO_TCHAR(projectSettings->General()->LibraryDir().Data());
+ SourcePackLibraryDir = SourcePackRootDir / ToUE(projectSettings->General()->LibraryDir());
if (!projectSettings->General()->ThumbnailsDir().Empty())
- SourcePackThumbnailsDir = SourcePackRootDir / ANSI_TO_TCHAR(projectSettings->General()->ThumbnailsDir().Data());
+ SourcePackThumbnailsDir = SourcePackRootDir / ToUE(projectSettings->General()->ThumbnailsDir());
if (!projectSettings->General()->EditorCacheDir().Empty())
- SourcePackCacheDir = SourcePackRootDir / ANSI_TO_TCHAR(projectSettings->General()->EditorCacheDir().Data());
+ SourcePackCacheDir = SourcePackRootDir / ToUE(projectSettings->General()->EditorCacheDir());
localBoContext->UnloadAllFiles();
PK_DELETE(localBoContext);
@@ -388,18 +401,42 @@ void UPopcornFXSettingsEditor::UpdateSourcePack()
{
// Log error
}
- SourcePackProjectFile = FPaths::ConvertRelativePathToFull(SourcePackProjectFile);
- SourcePackRootDir = FPaths::ConvertRelativePathToFull(SourcePackRootDir);
- SourcePackLibraryDir = FPaths::ConvertRelativePathToFull(SourcePackLibraryDir);
- SourcePackThumbnailsDir = FPaths::ConvertRelativePathToFull(SourcePackThumbnailsDir);
- SourcePackCacheDir = FPaths::ConvertRelativePathToFull(SourcePackCacheDir);
+
+ // Can't use 'FPaths::CollapseRelativeDirectories()' to collapse '..' inside the path if they start with '..'
+ // So convert to PopcornFX strings and use CFilePath::Purify(), then convert back to FPath
+ SourcePackProjectFile = ToUE(PopcornFX::CFilePath::Purified(ToPk(SourcePackProjectFile)));
+ SourcePackRootDir = ToUE(PopcornFX::CFilePath::Purified(ToPk(SourcePackRootDir)));
+ SourcePackLibraryDir = ToUE(PopcornFX::CFilePath::Purified(ToPk(SourcePackLibraryDir)));
+ SourcePackThumbnailsDir = ToUE(PopcornFX::CFilePath::Purified(ToPk(SourcePackThumbnailsDir)));
+ SourcePackCacheDir = ToUE(PopcornFX::CFilePath::Purified(ToPk(SourcePackCacheDir)));
+
+ AbsSourcePackProjectFile = FPaths::ConvertRelativePathToFull(SourcePackProjectFile);
+ AbsSourcePackRootDir = FPaths::ConvertRelativePathToFull(SourcePackRootDir);
+ AbsSourcePackLibraryDir = FPaths::ConvertRelativePathToFull(SourcePackLibraryDir);
+ AbsSourcePackThumbnailsDir = FPaths::ConvertRelativePathToFull(SourcePackThumbnailsDir);
+ AbsSourcePackCacheDir = FPaths::ConvertRelativePathToFull(SourcePackCacheDir);
}
// Avoid adding invalid source pack folders
if (bSourcePackFound)
- {
ForceUpdateAutoReimportSettings();
- }
+
+ // Fix #13209: Update bake context & other plugin-global things that depend on the project paths
+ FPopcornFXPlugin::Get().RefreshFromEditorSettings();
+}
+
+//----------------------------------------------------------------------------
+
+static bool _IsValidSourcePack(const FString &path)
+{
+ FString projectFile = path;
+ FPaths::NormalizeFilename(projectFile);
+ FPaths::RemoveDuplicateSlashes(projectFile);
+ projectFile = FixAndAppendPopcornFXProjectFileName(projectFile);
+ if (FPaths::IsRelative(projectFile))
+ projectFile = FPaths::ProjectDir() / projectFile;
+
+ return FPaths::FileExists(projectFile);
}
//----------------------------------------------------------------------------
@@ -409,11 +446,10 @@ bool UPopcornFXSettingsEditor::AskForAValidSourcePackForIFN(const FString &sourc
if (!PK_VERIFY(!sourceAssetPath.IsEmpty()))
return false;
- bool isValid = ValidSourcePack();
- if (isValid)
+ if (ValidSourcePack())
{
const FString sourceAssetPathAbs = FPaths::ConvertRelativePathToFull(sourceAssetPath);
- if (!sourceAssetPathAbs.StartsWith(SourcePackRootDir))
+ if (!sourceAssetPathAbs.StartsWith(AbsSourcePackRootDir))
{
UE_LOG(LogPopcornFXEditorSettings, Error, TEXT("Asset outside Source PopcornFX Project: '%s'"), *sourceAssetPath);
const FText title = LOCTEXT("PopcornFXAssetOutsidePackTitle", "PopcornFX: Asset outside Source PopcornFX Project");
@@ -426,44 +462,62 @@ bool UPopcornFXSettingsEditor::AskForAValidSourcePackForIFN(const FString &sourc
"Project Settings > PopcornFX Editor > Source PopcornFX Project path:\n"
"{1}\n"
"\n"
- "Continue anyway ?\n"), FText::FromString(sourceAssetPath), FText::FromString(SourcePackRootDir));
+ "Continue anyway ?\n"), FText::FromString(sourceAssetPathAbs), FText::FromString(AbsSourcePackRootDir));
return OpenMessageBox(EAppMsgType::YesNo, msg, title) == EAppReturnType::Yes;
}
return true;
}
- const FString oldImportSourcePath = ImportSourcePack;
- if (!sourceAssetPath.IsEmpty())
+ const FString oldImportSourcePath = ImportSourcePack;
+ bool isValid = false;
+ FString sourcePack = FPaths::ConvertRelativePathToFull(sourceAssetPath);
+
+ static const FString kTrySubPaths[] = {
+ "PopcornFX",
+ "PopcornFX/Editor",
+ "Editor",
+ };
+
+ // GetPath will make it loop over all parent folders to find the right one IFP
+ while (!isValid && !sourcePack.IsEmpty())
{
- ImportSourcePack = FPaths::ConvertRelativePathToFull(sourceAssetPath);
- PK_ASSERT(!isValid);
+ FString newSourcePack = FPaths::GetPath(sourcePack); // gets dirname: removes last name in path, effectively does a ../
+ if (!FPaths::IsRelative(newSourcePack))
+ {
+ FString relativePath = newSourcePack;
+ const FString projectDir = FPaths::ProjectDir();
+
+ if (FPaths::MakePathRelativeTo(relativePath, *projectDir))
+ newSourcePack = relativePath;
+ }
- // GetPath will make it loop over all parent folders to find the right one IFP
- while (!isValid)
+ if (newSourcePack.IsEmpty() || !PK_VERIFY(newSourcePack[newSourcePack.Len() - 1] != '/'))
+ break;
+
+ sourcePack = newSourcePack;
+ isValid = _IsValidSourcePack(sourcePack);
+ if (!isValid)
{
- const FString sourcePack = ImportSourcePack;
- FString newSourcePack = FPaths::GetPath(sourcePack); // dirname !
- // sanity checks !
- if (newSourcePack.Len() < 3 || // matches drive paths and too small to be valid
- newSourcePack.Len() >= sourcePack.Len()) // GetPath does that too
- break;
- if (!FPaths::IsRelative(newSourcePack))
+ for (const auto &subPath : kTrySubPaths)
{
- FString relativePath = newSourcePack;
- const FString projectDir = FPaths::ProjectDir();
-
- if (FPaths::MakePathRelativeTo(relativePath, *projectDir) &&
- relativePath.Len() > 1 && relativePath.Len() <= newSourcePack.Len()) // use it only if shorter
+ const FString tryPath = sourcePack / subPath;
+ isValid = _IsValidSourcePack(tryPath);
+ if (isValid)
{
- newSourcePack = relativePath;
+ sourcePack = tryPath;
+ break;
}
}
- if (!PK_VERIFY(newSourcePack[newSourcePack.Len() - 1] != '/'))
- break;
- ImportSourcePack = newSourcePack;
+ }
+
+ if (isValid) // Quick detection found a .pkproj, try the full-force resolve that will actually load it:
+ {
+ ImportSourcePack = sourcePack;
UpdateSourcePack();
isValid = ValidSourcePack();
+ if (!isValid)
+ sourcePack = newSourcePack; // revert the potential subpath & continue iterating downstream
}
}
@@ -480,7 +534,6 @@ bool UPopcornFXSettingsEditor::AskForAValidSourcePackForIFN(const FString &sourc
OpenMessageBox(EAppMsgType::Ok, text, title);
SaveConfig(); // Force save
- return true;
}
else
{
@@ -495,15 +548,16 @@ bool UPopcornFXSettingsEditor::AskForAValidSourcePackForIFN(const FString &sourc
UE_LOG(LogPopcornFXEditorSettings, Error, TEXT("Source PopcornFX Project NOT found: '%s'"), *ImportSourcePack);
const FText title = LOCTEXT("PopcornFXSourcePackNOTFoundTitle", "PopcornFX: Invalid Source PopcornFX Project path");
const FText msg = LOCTEXT( "PopcornFXSourcePackNOTFoundTitleMsg",
- "Invalid Source PopcornFX Project path, and could automaticaly find one.\n\
- Please setup:\n\
- \n\
- Project Settings > PopcornFX > Source PopcornFX Project path\n\
- \n\
- Continue anyway ?\n");
+ "Invalid Source PopcornFX Project path, and could not automatically find one.\n"
+ "Please setup:\n"
+ "\n"
+ "Project Settings > PopcornFX > Source PopcornFX Project path\n"
+ "\n"
+ "Continue anyway ?\n");
return OpenMessageBox(EAppMsgType::YesNo, msg, title) == EAppReturnType::Yes;
}
- return false;
+
+ return isValid;
}
//----------------------------------------------------------------------------
diff --git a/Source/PopcornFX/Private/PopcornFXSettingsEditor.h b/Source/PopcornFX/Private/PopcornFXSettingsEditor.h
index dab3c6b..fb460c2 100644
--- a/Source/PopcornFX/Private/PopcornFXSettingsEditor.h
+++ b/Source/PopcornFX/Private/PopcornFXSettingsEditor.h
@@ -78,22 +78,32 @@ class UPopcornFXSettingsEditor : public UObject
UPROPERTY(Config, VisibleAnywhere, Category="SourcePack", DisplayName="Resolved Project File path")
FString SourcePackProjectFile;
+ FString AbsSourcePackProjectFile;
+
/** Plugin internal: resolved root dir */
UPROPERTY(Config, VisibleAnywhere, Category="SourcePack", DisplayName="Resolved Root directory")
FString SourcePackRootDir;
+ FString AbsSourcePackRootDir;
+
/** Plugin internal: resolved library dir */
UPROPERTY(Config, VisibleAnywhere, Category="SourcePack", DisplayName="Resolved Root directory")
FString SourcePackLibraryDir;
+ FString AbsSourcePackLibraryDir;
+
/** Plugin internal: resolved thumbnails dir */
UPROPERTY(Config, VisibleAnywhere, Category="SourcePack", DisplayName="Resolved Thumbnails directory")
FString SourcePackThumbnailsDir;
+ FString AbsSourcePackThumbnailsDir;
+
/** Plugin internal: resolved cache dir */
UPROPERTY(Config, VisibleAnywhere, Category="SourcePack", DisplayName="Resolved Cache directory")
FString SourcePackCacheDir;
+ FString AbsSourcePackCacheDir;
+
/**
Enables auto reimport/mirroring of Source PopcornFX Project assets.
@@ -139,6 +149,9 @@ class UPopcornFXSettingsEditor : public UObject
/** Check this to restart effects when their attributes are modified via the details panel (useful when tweaking attributes for infinite particles) */
UPROPERTY(Config, EditAnywhere, Category="Debug")
uint32 bRestartEmitterWhenAttributesChanged : 1;
+
+private:
+ virtual void PostInitProperties() override;
#endif // WITH_EDITORONLY_DATA
#if WITH_EDITOR
@@ -146,13 +159,10 @@ class UPopcornFXSettingsEditor : public UObject
void UpdateSourcePack();
//bool ResolveSourcePackFromFilePathIFP(const FString &inFilePath);
- bool ValidSourcePack() const { return !SourcePackRootDir.IsEmpty() && bSourcePackFound != 0; }
+ bool ValidSourcePack() const { return !AbsSourcePackRootDir.IsEmpty() && bSourcePackFound != 0; }
bool AskForAValidSourcePackForIFN(const FString &sourceAssetPath);
- static FString FixAndAppendPopcornFXProjectFileName(const FString &path);
-
private:
- virtual void PostLoad() override;
virtual void PreEditChange(FProperty *propertyAboutToChange) override;
virtual void PostEditChangeProperty(struct FPropertyChangedEvent& propertyChangedEvent) override;
diff --git a/Source/PopcornFX/Private/Render/AudioPools.cpp b/Source/PopcornFX/Private/Render/AudioPools.cpp
index 1b901e9..36ab06e 100644
--- a/Source/PopcornFX/Private/Render/AudioPools.cpp
+++ b/Source/PopcornFX/Private/Render/AudioPools.cpp
@@ -257,7 +257,7 @@ bool CSoundDescriptorPool::Setup(CSoundDescriptorPoolCollection *poolCollection,
const PopcornFX::SRendererFeaturePropertyValue *soundProperty = rendererData->m_Declaration.FindProperty(PopcornFX::BasicRendererProperties::SID_Sound_SoundData());
if (soundProperty == null || soundProperty->ValuePath().Empty())
return false;
- m_SoundPath = FPopcornFXPlugin::Get().BuildPathFromPkPath(soundProperty->ValuePath().Data(), true);
+ m_SoundPath = FPopcornFXPlugin::Get().BuildPathFromPkPath(soundProperty->ValuePath(), true);
if (GetOrLoadSound() == null)
return false;
diff --git a/Source/PopcornFX/Private/Render/BatchDrawer_Billboard_CPU.cpp b/Source/PopcornFX/Private/Render/BatchDrawer_Billboard_CPU.cpp
index f0d4aa5..239a752 100644
--- a/Source/PopcornFX/Private/Render/BatchDrawer_Billboard_CPU.cpp
+++ b/Source/PopcornFX/Private/Render/BatchDrawer_Billboard_CPU.cpp
@@ -185,6 +185,9 @@ bool CBatchDrawer_Billboard_CPUBB::_IsAdditionalInputSupported(const PopcornFX::
{
if (fieldName == PopcornFX::BasicRendererProperties::SID_Emissive_EmissiveColor())
outStreamOffsetType = StreamOffset_EmissiveColors;
+
+ if (fieldName == PopcornFX::BasicRendererProperties::SID_ComputeVelocity_PreviousPosition())
+ outStreamOffsetType = StreamOffset_PreviousPosition;
}
else if (type == PopcornFX::BaseType_Float)
{
@@ -586,10 +589,14 @@ void CBatchDrawer_Billboard_CPUBB::_IssueDrawCall_Billboard(const SUERenderConte
bool outputVelocity;
sceneProxy->GetScene().GetPrimitiveUniformShaderParameters_RenderThread(sceneProxy->GetPrimitiveSceneInfo(), hasPrecomputedVolumetricLightmap, previousLocalToWorld, singleCaptureIndex, outputVelocity);
+ outputVelocity |= sceneProxy->AlwaysHasVelocity();
FMatrix localToWorld = FMatrix::Identity;
if (view->GlobalScale() != 1.0f)
+ {
localToWorld *= view->GlobalScale();
+ previousLocalToWorld *= view->GlobalScale();
+ }
CRendererCache *matCache = static_cast(desc.m_RendererCaches.First().Get());
if (!PK_VERIFY(matCache != null))
@@ -664,6 +671,7 @@ void CBatchDrawer_Billboard_CPUBB::_IssueDrawCall_Billboard(const SUERenderConte
vsUniformsBillboard.TotalParticleCount = desc.m_TotalParticleCount;
vsUniformsBillboard.CapsulesOffset = m_CapsulesOffset;
vsUniformsBillboard.InColorsOffset = m_AdditionalStreamOffsets[StreamOffset_Colors].OffsetForShaderConstant();
+ vsUniformsBillboard.InPreviousPositionOffset = m_AdditionalStreamOffsets[StreamOffset_PreviousPosition].OffsetForShaderConstant();
vsUniformsBillboard.InEmissiveColorsOffset = m_AdditionalStreamOffsets[StreamOffset_EmissiveColors].OffsetForShaderConstant();
vsUniformsBillboard.InAlphaCursorsOffset = m_AdditionalStreamOffsets[StreamOffset_AlphaCursors].OffsetForShaderConstant();
vsUniformsBillboard.InDynamicParameter1sOffset = m_AdditionalStreamOffsets[StreamOffset_DynParam1s].OffsetForShaderConstant();
diff --git a/Source/PopcornFX/Private/Render/BatchDrawer_Billboard_CPU.h b/Source/PopcornFX/Private/Render/BatchDrawer_Billboard_CPU.h
index 5c10503..c0f141b 100644
--- a/Source/PopcornFX/Private/Render/BatchDrawer_Billboard_CPU.h
+++ b/Source/PopcornFX/Private/Render/BatchDrawer_Billboard_CPU.h
@@ -23,6 +23,7 @@ class CBatchDrawer_Billboard_CPUBB : public PopcornFX::CRendererBatchJobs_Billbo
{
StreamOffset_Colors = 0,
StreamOffset_EmissiveColors,
+ StreamOffset_PreviousPosition,
StreamOffset_AlphaCursors,
StreamOffset_DynParam1s,
StreamOffset_DynParam2s,
diff --git a/Source/PopcornFX/Private/Render/BatchDrawer_Billboard_GPU.cpp b/Source/PopcornFX/Private/Render/BatchDrawer_Billboard_GPU.cpp
index c21b367..cc0e3e6 100644
--- a/Source/PopcornFX/Private/Render/BatchDrawer_Billboard_GPU.cpp
+++ b/Source/PopcornFX/Private/Render/BatchDrawer_Billboard_GPU.cpp
@@ -540,6 +540,8 @@ bool CBatchDrawer_Billboard_GPUBB::_IsAdditionalInputSupported(const PopcornFX::
{
if (fieldName == PopcornFX::BasicRendererProperties::SID_Emissive_EmissiveColor())
outStreamOffsetType = StreamOffset_EmissiveColors;
+ if (fieldName == PopcornFX::BasicRendererProperties::SID_ComputeVelocity_PreviousPosition())
+ outStreamOffsetType = StreamOffset_PreviousPosition;
}
else if (type == PopcornFX::BaseType_Float)
{
@@ -1084,7 +1086,10 @@ bool CBatchDrawer_Billboard_GPUBB::_FillDrawCallUniforms_GPU(u32 drId,
return false;
if ((m_ViewIndependentInputs & PopcornFX::Drawers::GenInput_ParticlePosition) != 0)
+ {
m_StreamOffsets[StreamOffset_Positions] = stream->StreamOffset(br.m_PositionStreamId);
+ m_StreamOffsets[StreamOffset_Enabled] = stream->StreamOffset(br.m_EnabledStreamId);
+ }
if ((m_ViewIndependentInputs & PopcornFX::Drawers::GenInput_ParticleSize) != 0)
m_StreamOffsets[StreamOffset_Sizes] = stream->StreamOffset(br.m_SizeStreamId);
else if ((m_ViewIndependentInputs & PopcornFX::Drawers::GenInput_ParticleSize2) != 0)
@@ -1222,6 +1227,7 @@ void CBatchDrawer_Billboard_GPUBB::_IssueDrawCall_Billboard(const SUERenderConte
vsUniformsGPUBillboard.CapsulesDC = m_CapsulesDC ? 1 : 0;
vsUniformsGPUBillboard.HasSecondUVSet = m_HasAtlasBlending ? 1 : 0;
vsUniformsGPUBillboard.InPositionsOffset = m_StreamOffsets[StreamOffset_Positions].Valid() ? static_cast(m_StreamOffsets[StreamOffset_Positions] / sizeof(float)) : -1;
+ vsUniformsGPUBillboard.InEnabledOffset = m_StreamOffsets[StreamOffset_Enabled].Valid() ? static_cast(m_StreamOffsets[StreamOffset_Enabled] / sizeof(float)) : -1;
vsUniformsGPUBillboard.InSizesOffset = m_StreamOffsets[StreamOffset_Sizes].Valid() ? static_cast(m_StreamOffsets[StreamOffset_Sizes] / sizeof(float)) : -1;
vsUniformsGPUBillboard.InSize2sOffset = m_StreamOffsets[StreamOffset_Size2s].Valid() ? static_cast(m_StreamOffsets[StreamOffset_Size2s] / sizeof(float)) : -1;
vsUniformsGPUBillboard.InRotationsOffset = m_StreamOffsets[StreamOffset_Rotations].Valid() ? static_cast(m_StreamOffsets[StreamOffset_Rotations] / sizeof(float)) : -1;
@@ -1229,6 +1235,7 @@ void CBatchDrawer_Billboard_GPUBB::_IssueDrawCall_Billboard(const SUERenderConte
vsUniformsGPUBillboard.InAxis1sOffset = m_StreamOffsets[StreamOffset_Axis1s].Valid() ? static_cast(m_StreamOffsets[StreamOffset_Axis1s] / sizeof(float)) : -1;
vsUniformsGPUBillboard.InTextureIDsOffset = m_AdditionalStreamOffsets[StreamOffset_TextureIDs].Valid() ? static_cast(m_AdditionalStreamOffsets[StreamOffset_TextureIDs] / sizeof(float)) : -1;
vsUniformsGPUBillboard.InColorsOffset = m_AdditionalStreamOffsets[StreamOffset_Colors].Valid() ? static_cast(m_AdditionalStreamOffsets[StreamOffset_Colors] / sizeof(float)) : -1;
+ vsUniformsGPUBillboard.InPreviousPositionOffset = m_AdditionalStreamOffsets[StreamOffset_PreviousPosition].Valid() ? static_cast(m_AdditionalStreamOffsets[StreamOffset_PreviousPosition] / sizeof(float)) : -1;
vsUniformsGPUBillboard.InEmissiveColorsOffset = m_AdditionalStreamOffsets[StreamOffset_EmissiveColors].Valid() ? static_cast(m_AdditionalStreamOffsets[StreamOffset_EmissiveColors] / sizeof(float)) : -1;
vsUniformsGPUBillboard.InAlphaCursorsOffset = m_AdditionalStreamOffsets[StreamOffset_AlphaCursors].Valid() ? static_cast(m_AdditionalStreamOffsets[StreamOffset_AlphaCursors] / sizeof(float)) : -1;
vsUniformsGPUBillboard.InDynamicParameter1sOffset = m_AdditionalStreamOffsets[StreamOffset_DynParam1s].Valid() ? static_cast(m_AdditionalStreamOffsets[StreamOffset_DynParam1s] / sizeof(float)) : -1;
diff --git a/Source/PopcornFX/Private/Render/BatchDrawer_Billboard_GPU.h b/Source/PopcornFX/Private/Render/BatchDrawer_Billboard_GPU.h
index 75803d0..2a75186 100644
--- a/Source/PopcornFX/Private/Render/BatchDrawer_Billboard_GPU.h
+++ b/Source/PopcornFX/Private/Render/BatchDrawer_Billboard_GPU.h
@@ -112,6 +112,7 @@ class CBatchDrawer_Billboard_GPUBB : public PopcornFX::CRendererBatchJobs_Billbo
enum EPopcornFXStreamOffsets
{
StreamOffset_Positions = 0,
+ StreamOffset_Enabled,
StreamOffset_Sizes,
StreamOffset_Size2s,
StreamOffset_Rotations,
@@ -124,6 +125,7 @@ class CBatchDrawer_Billboard_GPUBB : public PopcornFX::CRendererBatchJobs_Billbo
{
StreamOffset_Colors = 0,
StreamOffset_EmissiveColors,
+ StreamOffset_PreviousPosition,
StreamOffset_TextureIDs,
StreamOffset_AlphaCursors,
StreamOffset_DynParam1s,
diff --git a/Source/PopcornFX/Private/Render/BatchDrawer_Ribbon_CPU.cpp b/Source/PopcornFX/Private/Render/BatchDrawer_Ribbon_CPU.cpp
index 942f9bd..3db462d 100644
--- a/Source/PopcornFX/Private/Render/BatchDrawer_Ribbon_CPU.cpp
+++ b/Source/PopcornFX/Private/Render/BatchDrawer_Ribbon_CPU.cpp
@@ -197,6 +197,8 @@ bool CBatchDrawer_Ribbon_CPUBB::_IsAdditionalInputSupported(const PopcornFX::CSt
{
if (fieldName == PopcornFX::BasicRendererProperties::SID_Emissive_EmissiveColor())
outStreamOffsetType = StreamOffset_EmissiveColors;
+ if (fieldName == PopcornFX::BasicRendererProperties::SID_ComputeVelocity_PreviousPosition())
+ outStreamOffsetType = StreamOffset_PreviousPosition;
}
else if (type == PopcornFX::BaseType_Float)
{
@@ -627,10 +629,14 @@ void CBatchDrawer_Ribbon_CPUBB::_IssueDrawCall_Ribbon(const SUERenderContext &re
bool outputVelocity;
sceneProxy->GetScene().GetPrimitiveUniformShaderParameters_RenderThread(sceneProxy->GetPrimitiveSceneInfo(), hasPrecomputedVolumetricLightmap, previousLocalToWorld, singleCaptureIndex, outputVelocity);
+ outputVelocity |= sceneProxy->AlwaysHasVelocity();
FMatrix localToWorld = FMatrix::Identity;
if (view->GlobalScale() != 1.0f)
+ {
localToWorld *= view->GlobalScale();
+ previousLocalToWorld *= view->GlobalScale();
+ }
CRendererCache *matCache = static_cast(desc.m_RendererCaches.First().Get());
if (!PK_VERIFY(matCache != null))
@@ -710,6 +716,7 @@ void CBatchDrawer_Ribbon_CPUBB::_IssueDrawCall_Ribbon(const SUERenderContext &re
vsUniformsbillboard.VPP = m_VPP;
vsUniformsbillboard.InColorsOffset = m_AdditionalStreamOffsets[StreamOffset_Colors].OffsetForShaderConstant();
vsUniformsbillboard.InEmissiveColorsOffset = m_AdditionalStreamOffsets[StreamOffset_EmissiveColors].OffsetForShaderConstant();
+ vsUniformsbillboard.InPreviousPositionOffset = m_AdditionalStreamOffsets[StreamOffset_PreviousPosition].OffsetForShaderConstant();
vsUniformsbillboard.InAlphaCursorsOffset = m_AdditionalStreamOffsets[StreamOffset_AlphaCursors].OffsetForShaderConstant();
vsUniformsbillboard.InDynamicParameter1sOffset = m_AdditionalStreamOffsets[StreamOffset_DynParam1s].OffsetForShaderConstant();
vsUniformsbillboard.InDynamicParameter2sOffset = m_AdditionalStreamOffsets[StreamOffset_DynParam2s].OffsetForShaderConstant();
diff --git a/Source/PopcornFX/Private/Render/BatchDrawer_Ribbon_CPU.h b/Source/PopcornFX/Private/Render/BatchDrawer_Ribbon_CPU.h
index 1ef1c5a..cedbcf2 100644
--- a/Source/PopcornFX/Private/Render/BatchDrawer_Ribbon_CPU.h
+++ b/Source/PopcornFX/Private/Render/BatchDrawer_Ribbon_CPU.h
@@ -23,6 +23,7 @@ class CBatchDrawer_Ribbon_CPUBB : public PopcornFX::CRendererBatchJobs_Ribbon_CP
{
StreamOffset_Colors = 0,
StreamOffset_EmissiveColors,
+ StreamOffset_PreviousPosition,
StreamOffset_AlphaCursors,
StreamOffset_DynParam1s,
StreamOffset_DynParam2s,
diff --git a/Source/PopcornFX/Private/Render/PopcornFXGPUVertexFactory.h b/Source/PopcornFX/Private/Render/PopcornFXGPUVertexFactory.h
index b9a80b6..359bfba 100644
--- a/Source/PopcornFX/Private/Render/PopcornFXGPUVertexFactory.h
+++ b/Source/PopcornFX/Private/Render/PopcornFXGPUVertexFactory.h
@@ -24,6 +24,7 @@ BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT(FPopcornFXGPUBillboardVSUniforms, POPCORNFX
SHADER_PARAMETER(int32, CapsulesDC)
SHADER_PARAMETER(int32, HasSecondUVSet)
SHADER_PARAMETER(int32, InPositionsOffset)
+ SHADER_PARAMETER(int32, InEnabledOffset)
SHADER_PARAMETER(int32, InSizesOffset)
SHADER_PARAMETER(int32, InSize2sOffset)
SHADER_PARAMETER(int32, InRotationsOffset)
@@ -32,6 +33,7 @@ BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT(FPopcornFXGPUBillboardVSUniforms, POPCORNFX
SHADER_PARAMETER(int32, InTextureIDsOffset)
SHADER_PARAMETER(int32, InColorsOffset)
SHADER_PARAMETER(int32, InEmissiveColorsOffset)
+ SHADER_PARAMETER(int32, InPreviousPositionOffset)
SHADER_PARAMETER(int32, InAlphaCursorsOffset)
SHADER_PARAMETER(int32, InDynamicParameter1sOffset)
SHADER_PARAMETER(int32, InDynamicParameter2sOffset)
diff --git a/Source/PopcornFX/Private/Render/PopcornFXMeshVertexFactory.h b/Source/PopcornFX/Private/Render/PopcornFXMeshVertexFactory.h
index 6f660d2..d3f13bf 100644
--- a/Source/PopcornFX/Private/Render/PopcornFXMeshVertexFactory.h
+++ b/Source/PopcornFX/Private/Render/PopcornFXMeshVertexFactory.h
@@ -21,6 +21,7 @@ BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT(FPopcornFXMeshVSUniforms, POPCORNFX_API)
SHADER_PARAMETER(int32, InColorsOffset)
SHADER_PARAMETER(int32, InEmissiveColorsOffset)
SHADER_PARAMETER(int32, InAlphaCursorsOffset)
+ SHADER_PARAMETER(int32, InPreviousPositionOffset)
SHADER_PARAMETER(int32, InTextureIDsOffset)
SHADER_PARAMETER(int32, InVATCursorsOffset)
SHADER_PARAMETER(int32, InDynamicParameter0sOffset)
diff --git a/Source/PopcornFX/Private/Render/PopcornFXVertexFactory.h b/Source/PopcornFX/Private/Render/PopcornFXVertexFactory.h
index 9206e8b..e0c619b 100644
--- a/Source/PopcornFX/Private/Render/PopcornFXVertexFactory.h
+++ b/Source/PopcornFX/Private/Render/PopcornFXVertexFactory.h
@@ -31,6 +31,7 @@ BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT(FPopcornFXBillboardVSUniforms, POPCORNFX_AP
//SHADER_PARAMETER(int, InTextureIDsOffset)
SHADER_PARAMETER(int32, InColorsOffset)
SHADER_PARAMETER(int32, InEmissiveColorsOffset)
+ SHADER_PARAMETER(int32, InPreviousPositionOffset)
SHADER_PARAMETER(int32, InAlphaCursorsOffset)
SHADER_PARAMETER(int32, InDynamicParameter1sOffset)
SHADER_PARAMETER(int32, InDynamicParameter2sOffset)
diff --git a/Source/PopcornFX/Private/World/PopcornFXEmitterComponent.cpp b/Source/PopcornFX/Private/World/PopcornFXEmitterComponent.cpp
index 6a5d879..39def44 100644
--- a/Source/PopcornFX/Private/World/PopcornFXEmitterComponent.cpp
+++ b/Source/PopcornFX/Private/World/PopcornFXEmitterComponent.cpp
@@ -32,6 +32,7 @@
#include
#include
+#include
#include
//----------------------------------------------------------------------------
@@ -363,9 +364,7 @@ void UPopcornFXEmitterComponent::CheckForErrors()
if (filever.Empty())
filever = PopcornFX::SEngineVersion(1, 7, 3, 0); // bo file version did not exists
- bool outOfDate = filever.Major() < current.Major();
- if (!outOfDate && filever.Minor() < current.Minor())
- outOfDate = true;
+ const bool outOfDate = filever.Lower_IgnorePatch(current);
if (outOfDate)
{
FFormatNamedArguments Arguments;
@@ -997,7 +996,7 @@ bool UPopcornFXEmitterComponent::RegisterEventListener(FPopcornFXRaiseEventSigna
UE_LOG(LogPopcornFXEmitterComponent, Warning, TEXT("Register Event Listener: Empty EventName"));
return false;
}
- const PopcornFX::CStringId eventNameId = PopcornFX::CStringId(TCHAR_TO_ANSI(*EventName.ToString()));
+ const PopcornFX::CStringId eventNameId = PopcornFX::CStringId(ToPk(EventName.ToString()));
PK_ASSERT(!eventNameId.Empty());
if (!Delegate.IsBound())
@@ -1020,7 +1019,7 @@ void UPopcornFXEmitterComponent::UnregisterEventListener(FPopcornFXRaiseEventSig
if (!PK_VERIFY(m_CurrentScene != null))
return;
- const PopcornFX::CStringId eventNameId = PopcornFX::CStringId(TCHAR_TO_ANSI(*EventName.ToString()));
+ const PopcornFX::CStringId eventNameId = PopcornFX::CStringId(ToPk(EventName.ToString()));
if (eventNameId.Empty())
{
UE_LOG(LogPopcornFXEmitterComponent, Warning, TEXT("Unregister Event Listener: Empty EventName"));
@@ -1139,6 +1138,9 @@ void UPopcornFXEmitterComponent::ApplyWorldOffset(const FVector &inOffset, bool
void UPopcornFXEmitterComponent::Scene_PreUpdate(CParticleScene *scene, float deltaTime)
{
+ using namespace PopcornFX;
+ PK_CALL_CONTEXT("Emitter", PopcornFX::CStringView(Effect->Effect()->ParticleEffectIFP()->File()->Path()));
+ PK_SCOPEDPROFILE();
LLM_SCOPE(ELLMTag::Particles);
PK_ASSERT(!IsTemplate());
@@ -1244,6 +1246,14 @@ void UPopcornFXEmitterComponent::Scene_PostUpdate(CParticleScene *scene, float d
{
// Destroy component if instance was destroyed during update
CheckForDead();
+
+#if WITH_EDITOR
+ // This will be called after the update has been complete.
+ // Post-update the attributes if we have some: Needed to reset pulsed bool attributes
+ UPopcornFXAttributeList *attributeList = GetAttributeListIFP();
+ if (attributeList != null && IsValid(attributeList))
+ attributeList->ResetPulsedBoolAttributesIFN();
+#endif // WITH_EDITOR
}
//----------------------------------------------------------------------------
diff --git a/Source/PopcornFX/Private/World/PopcornFXSceneProxy.cpp b/Source/PopcornFX/Private/World/PopcornFXSceneProxy.cpp
index c32ab37..2fb5929 100644
--- a/Source/PopcornFX/Private/World/PopcornFXSceneProxy.cpp
+++ b/Source/PopcornFX/Private/World/PopcornFXSceneProxy.cpp
@@ -23,9 +23,7 @@ FPopcornFXSceneProxy::FPopcornFXSceneProxy(UPopcornFXSceneComponent *component)
bVerifyUsedMaterials = true;
#if (ENGINE_MAJOR_VERSION == 5)
-#if 0
bAlwaysHasVelocity = true;
-#endif
#endif // (ENGINE_MAJOR_VERSION == 5)
}
@@ -162,7 +160,7 @@ FPrimitiveViewRelevance FPopcornFXSceneProxy::GetViewRelevance(const FSceneView*
viewRelevance.bHasVolumeMaterialDomain = true;
viewRelevance.bTranslucentSelfShadow = true;
- viewRelevance.bVelocityRelevance = DrawsVelocity();
+ viewRelevance.bVelocityRelevance = true;
return viewRelevance;
}
diff --git a/Source/PopcornFX/Public/Assets/PopcornFXEffect.h b/Source/PopcornFX/Public/Assets/PopcornFXEffect.h
index d193cf2..f236847 100644
--- a/Source/PopcornFX/Public/Assets/PopcornFXEffect.h
+++ b/Source/PopcornFX/Public/Assets/PopcornFXEffect.h
@@ -61,7 +61,7 @@ class UPopcornFXEffect : public UPopcornFXFile
private:
void ClearEffect();
- bool LoadEffect();
+ bool LoadEffect(bool forceImport = false);
protected:
#if WITH_EDITOR
diff --git a/Source/PopcornFX/Public/PopcornFXAttributeList.h b/Source/PopcornFX/Public/PopcornFXAttributeList.h
index 00bb1e0..48a59bf 100644
--- a/Source/PopcornFX/Public/PopcornFXAttributeList.h
+++ b/Source/PopcornFX/Public/PopcornFXAttributeList.h
@@ -259,6 +259,10 @@ class UPopcornFXAttributeList : public UObject
template void SetAttributeDim(uint32 attributeId, uint32 dim, _Scalar value, bool fromUI = false);
template _Scalar GetAttributeDim(uint32 attributeId, uint32 dim);
+
+ void PulseBoolAttributeDim(uint32 attributeId, uint32 dim, bool fromUI = false);
+
+ void ResetPulsedBoolAttributesIFN();
#endif // WITH_EDITOR
uint32 FileVersionId() const { return m_FileVersionId; }
@@ -310,6 +314,10 @@ class UPopcornFXAttributeList : public UObject
bool m_RestartEmitter = false; // UPopcornFXSettingsEditor::bRestartEmitterWhenAttributesChanged
#endif // WITH_EDITORONLY_DATA
+#if WITH_EDITOR
+ bool m_HasPendingOneShotReset = false;
+#endif // WITH_EDITOR
+
public:
UPROPERTY(Category="PopcornFX Attributes", EditAnywhere, BlueprintReadOnly, EditFixedSize)
TArray m_AttributesRawData;
diff --git a/Source/PopcornFX/Public/PopcornFXAttributeSampler.h b/Source/PopcornFX/Public/PopcornFXAttributeSampler.h
index eb2986e..d20de29 100644
--- a/Source/PopcornFX/Public/PopcornFXAttributeSampler.h
+++ b/Source/PopcornFX/Public/PopcornFXAttributeSampler.h
@@ -31,6 +31,7 @@ namespace EPopcornFXAttributeSamplerComponentType
Shape,
SkinnedMesh,
Image,
+ Grid,
Curve,
AnimTrack,
Turbulence,
@@ -46,6 +47,7 @@ namespace EPopcornFXAttributeSamplerType
None = 0,
Shape,
Image,
+ Grid,
Curve,
AnimTrack,
Turbulence,
diff --git a/Source/PopcornFX/Public/PopcornFXAttributeSamplerActor.h b/Source/PopcornFX/Public/PopcornFXAttributeSamplerActor.h
index a545168..0405a17 100644
--- a/Source/PopcornFX/Public/PopcornFXAttributeSamplerActor.h
+++ b/Source/PopcornFX/Public/PopcornFXAttributeSamplerActor.h
@@ -45,7 +45,7 @@ class POPCORNFX_API APopcornFXAttributeSamplerActor : public AActor
void ReloadSprite();
EPopcornFXAttributeSamplerComponentType::Type m_SamplerComponentType;
- bool m_IsValidSpecializedActor = false;
+ bool m_IsValidSpecializedActor = false;
};
/** Can override an Attribute Sampler **Shape** by a **UStaticMesh**. */
@@ -57,6 +57,9 @@ UCLASS() class POPCORNFX_API APopcornFXAttributeSamplerSkinnedMeshActor : public
/** Can override an Attribute Sampler **Image** by a **UTexture**. */
UCLASS() class POPCORNFX_API APopcornFXAttributeSamplerImageActor : public APopcornFXAttributeSamplerActor { GENERATED_UCLASS_BODY() };
+/** Can override an Attribute Sampler **Grid** by a **UTexture**. */
+UCLASS() class POPCORNFX_API APopcornFXAttributeSamplerGridActor : public APopcornFXAttributeSamplerActor { GENERATED_UCLASS_BODY() };
+
/** Can override an Attribute Sampler **Curve** by a **UCurve...**. */
UCLASS() class POPCORNFX_API APopcornFXAttributeSamplerCurveActor : public APopcornFXAttributeSamplerActor { GENERATED_UCLASS_BODY() };
diff --git a/Source/PopcornFX/Public/PopcornFXAttributeSamplerGrid.h b/Source/PopcornFX/Public/PopcornFXAttributeSamplerGrid.h
new file mode 100644
index 0000000..c7ef387
--- /dev/null
+++ b/Source/PopcornFX/Public/PopcornFXAttributeSamplerGrid.h
@@ -0,0 +1,102 @@
+//----------------------------------------------------------------------------
+// Copyright Persistant Studios, SARL. All Rights Reserved.
+// https://www.popcornfx.com/terms-and-conditions/
+//----------------------------------------------------------------------------
+
+#pragma once
+
+#include "PopcornFXPublic.h"
+
+#include "PopcornFXTypes.h"
+#include "PopcornFXAttributeSampler.h"
+
+#include "PopcornFXAttributeSamplerGrid.generated.h"
+
+FWD_PK_API_BEGIN
+class CParticleSamplerDescriptor_Grid;
+FWD_PK_API_END
+// Statement to help the UE Header Parser not crash on FWD_PK_API_...
+class FPopcornFXPlugin;
+
+// this forward declaration is here to help the UE Header Parser which seems to crash because of FWD_PK_API_...
+class UPopcornFXAttributeSamplerGrid;
+
+struct FAttributeSamplerGridData;
+
+UENUM(BlueprintType)
+enum class EPopcornFXGridDataType : uint8
+{
+ R,
+ RG,
+ RGBA
+};
+
+/** Can override an Attribute Sampler **Grid** by a **UTexture**. */
+UCLASS(EditInlineNew, meta=(BlueprintSpawnableComponent), ClassGroup=PopcornFX)
+class POPCORNFX_API UPopcornFXAttributeSamplerGrid : public UPopcornFXAttributeSampler
+{
+ GENERATED_UCLASS_BODY()
+
+public:
+ UFUNCTION(BlueprintCallable, Category="PopcornFX AttributeSampler")
+ void SetRenderTarget(class UTextureRenderTarget *InRenderTarget);
+
+ UFUNCTION(BlueprintCallable, Category="PopcornFX AttributeSampler", meta=(UnsafeDuringActorConstruction="true"))
+ void SetAsMaterialTextureParameter(UMaterialInstanceDynamic *Material, FName ParameterName);
+
+ /** If true, this grid attribute sampler is setup from a 2D or Volume render target asset instead of being setup through SizeX, SizeY, SizeZ & DataType. */
+ UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="PopcornFX AttributeSampler")
+ uint32 bAssetGrid : 1;
+
+ /**
+ If true, render target has its sRGB flag force enabled (or disabled if false).
+ Enable this if writes into the grid in the source effect(s) are not linear.
+ */
+ UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="PopcornFX AttributeSampler")
+ uint32 bSRGB : 1;
+
+ /**
+ 2D or Volume Render target asset used by the grid attribute sampler.
+ Note: this is only supported by GPU simulated particles (binding this sampler on an effect with CPU simulated particles will fallback to sampling the default resource defined in the effect).
+ */
+ UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="PopcornFX AttributeSampler")
+ class UTextureRenderTarget *RenderTarget;
+
+ /** Grid Dimensions (Width) */
+ UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="PopcornFX AttributeSampler", meta=(ClampMin="1", ClampMax="4096"))
+ int32 SizeX;
+
+ /** Grid Dimensions (Height) */
+ UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="PopcornFX AttributeSampler", meta=(ClampMin="1", ClampMax="4096"))
+ int32 SizeY;
+
+ /** Grid Dimensions (Depth) */
+ UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="PopcornFX AttributeSampler", meta=(ClampMin="1", ClampMax="4096"))
+ int32 SizeZ;
+
+ /** Grid Data Type */
+ UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="PopcornFX AttributeSampler")
+ EPopcornFXGridDataType DataType;
+
+ // overrides
+ void OnUnregister() override;
+ void BeginDestroy() override;
+
+ class UTexture *GridTexture();
+
+#if WITH_EDITOR
+ void PostEditChangeProperty(FPropertyChangedEvent& propertyChangedEvent) override;
+#endif // WITH_EDITOR
+
+ // PopcornFX Internal
+ virtual PopcornFX::CParticleSamplerDescriptor *_AttribSampler_SetupSamplerDescriptor(FPopcornFXSamplerDesc &desc, const PopcornFX::CResourceDescriptor *defaultSampler) override;
+
+private:
+ bool RebuildGridSampler();
+ bool _RebuildGridSampler();
+
+ UPROPERTY(Transient)
+ UTexture *m_GridTexture;
+
+ FAttributeSamplerGridData *m_Data;
+};
diff --git a/Source/PopcornFX/Public/PopcornFXEmitterComponent.h b/Source/PopcornFX/Public/PopcornFXEmitterComponent.h
index 76e1d02..948f3ad 100644
--- a/Source/PopcornFX/Public/PopcornFXEmitterComponent.h
+++ b/Source/PopcornFX/Public/PopcornFXEmitterComponent.h
@@ -151,7 +151,7 @@ class POPCORNFX_API UPopcornFXEmitterComponent : public USceneComponent
// Stops all layers/emitters of this instance, and kills all particles spawned by this effect instance
// The kill will be processed during the next medium-collection update.
- UFUNCTION(BlueprintCallable, Category = "PopcornFX|Emitter", meta = (Keywords = "popcornfx particle emitter effect system kill", UnsafeDuringActorConstruction = "true"))
+ UFUNCTION(BlueprintCallable, Category = "PopcornFX|Emitter", meta = (Keywords="popcornfx particle emitter effect system kill", UnsafeDuringActorConstruction = "true"))
void KillParticles();
/** Get whether the emitter is still emitting particles or not */
diff --git a/Source/PopcornFX/Public/PopcornFXSettings.h b/Source/PopcornFX/Public/PopcornFXSettings.h
index c49169e..07f7a8a 100644
--- a/Source/PopcornFX/Public/PopcornFXSettings.h
+++ b/Source/PopcornFX/Public/PopcornFXSettings.h
@@ -330,6 +330,5 @@ class UPopcornFXSettings : public UObject
virtual void PostEditChangeProperty(struct FPropertyChangedEvent& propertyChangedEvent) override;
#endif
- void UpdateSourcePack();
UMaterialInterface *GetConfigDefaultMaterial(uint32 ePopcornFXMaterialType) const;
};
diff --git a/Source/PopcornFX/Public/PopcornFXVersionGenerated.h b/Source/PopcornFX/Public/PopcornFXVersionGenerated.h
index 007c734..9858d7c 100644
--- a/Source/PopcornFX/Public/PopcornFXVersionGenerated.h
+++ b/Source/PopcornFX/Public/PopcornFXVersionGenerated.h
@@ -6,6 +6,6 @@
#pragma once
#define POPCORNFX_PLUGIN_VERSION_MAJOR 2
-#define POPCORNFX_PLUGIN_VERSION_MINOR 18
-#define POPCORNFX_PLUGIN_VERSION_PATCH 6
+#define POPCORNFX_PLUGIN_VERSION_MINOR 19
+#define POPCORNFX_PLUGIN_VERSION_PATCH 0
#define POPCORNFX_PLUGIN_VERSION_TAG ""