From 74d348706c41774d4b6cb73a3d81a7eae969425e Mon Sep 17 00:00:00 2001 From: ruan Date: Sat, 27 Jan 2024 14:23:41 -0400 Subject: [PATCH] Add skeleton mask asset parameter to Blend With Mask anim node. --- Source/Editor/Surface/Archetypes/Animation.cs | 50 ++++++++++++++++++- .../Animations/Graph/AnimGroup.Animation.cpp | 11 ++++ 2 files changed, 60 insertions(+), 1 deletion(-) 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())