diff --git a/Source/Editor/Surface/Archetypes/Animation.cs b/Source/Editor/Surface/Archetypes/Animation.cs
index c659b475a..b2494081a 100644
--- a/Source/Editor/Surface/Archetypes/Animation.cs
+++ b/Source/Editor/Surface/Archetypes/Animation.cs
@@ -28,6 +28,52 @@ namespace FlaxEditor.Surface.Archetypes
}
}
+ ///
+ /// Customized for Blend with Mask node.
+ ///
+ public class SkeletonMaskSample : SurfaceNode
+ {
+ private AssetSelect _assetSelect;
+ private Box _assetBox;
+
+ ///
+ public SkeletonMaskSample(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch)
+ : base(id, context, nodeArch, groupArch)
+ {
+ }
+
+ ///
+ public override void OnSurfaceLoaded(SurfaceNodeActions action)
+ {
+ base.OnSurfaceLoaded(action);
+
+ if (Surface != null)
+ {
+ _assetSelect = GetChild();
+
+ // 4 is the id of skeleton mask parameter node.
+ if (TryGetBox(4, out var box))
+ {
+ _assetBox = box;
+ _assetSelect.Visible = !_assetBox.HasAnyConnection;
+ }
+ }
+ }
+
+ ///
+ public override void ConnectionTick(Box box)
+ {
+ base.ConnectionTick(box);
+
+ if (_assetBox == null)
+ return;
+ if (box.ID != _assetBox.ID)
+ return;
+
+ _assetSelect.Visible = !box.HasAnyConnection;
+ }
+ }
+
///
/// Customized for the animation sampling nodes
///
@@ -552,6 +598,7 @@ namespace FlaxEditor.Surface.Archetypes
TypeID = 11,
Title = "Blend with Mask",
Description = "Blend animation poses using skeleton mask",
+ Create = (id, context, arch, groupArch) => new SkeletonMaskSample(id, context, arch, groupArch),
Flags = NodeFlags.AnimGraph,
Size = new Float2(180, 140),
DefaultValues = new object[]
@@ -565,7 +612,8 @@ namespace FlaxEditor.Surface.Archetypes
NodeElementArchetype.Factory.Input(0, "Pose A", true, typeof(void), 1),
NodeElementArchetype.Factory.Input(1, "Pose B", true, typeof(void), 2),
NodeElementArchetype.Factory.Input(2, "Alpha", true, typeof(float), 3, 0),
- NodeElementArchetype.Factory.Asset(0, 70, 1, typeof(SkeletonMask)),
+ NodeElementArchetype.Factory.Input(3, "Skeleton Mask Asset", true, typeof(SkeletonMask), 4),
+ NodeElementArchetype.Factory.Asset(0, Surface.Constants.LayoutOffsetY * 4, 1, typeof(SkeletonMask)),
}
},
new NodeArchetype
diff --git a/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp b/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp
index cdf1ebd84..ab3bb0250 100644
--- a/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp
+++ b/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp
@@ -1131,6 +1131,17 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
{
const float alpha = Math::Saturate((float)tryGetValue(node->GetBox(3), node->Values[0]));
auto mask = node->Assets[0].As();
+ auto maskAssetBox = node->GetBox(4); // 4 is the id of skeleton mask parameter node.
+
+ // Check if have some mask asset conected with the mask node
+ if (maskAssetBox->HasConnection())
+ {
+ const Value assetBoxValue = tryGetValue(maskAssetBox, Value::Null);
+
+ // Use the mask conected with this node instead of default mask asset
+ if (assetBoxValue != Value::Null)
+ mask = (SkeletonMask *)assetBoxValue.AsAsset;
+ }
// Only A or missing/invalid mask
if (Math::NearEqual(alpha, 0.0f, ANIM_GRAPH_BLEND_THRESHOLD) || mask == nullptr || mask->WaitForLoaded())