// Copyright Epic Games, Inc. All Rights Reserved. #include "GetGroomAssetNode.h" #include "GroomEdit.h" #include "GroomInstance.h" #include "GroomCollectionFacades.h" #include "Dataflow/DataflowInputOutput.h" #include "Dataflow/DataflowObjectInterface.h" #include UE_INLINE_GENERATED_CPP_BY_NAME(GetGroomAssetNode) namespace UE::Groom::Private { template FORCEINLINE const UGroomAsset* BuildGroomCollection(Dataflow::FContext& Context, const UGroomAsset* NodeGroom, FManagedArrayCollection& GroomCollection, FEditableGroom& EditGroom) { const UGroomAsset* GroomAsset = NodeGroom; if (!GroomAsset) { if (const Dataflow::FEngineContext* EngineContext = Context.AsType()) { GroomAsset = Cast(EngineContext->Owner); } } if (GroomAsset) { ConvertFromGroomAsset(const_cast(GroomAsset), &EditGroom, false, false, false); TArray PointRestPositions; TArray ObjectCurveOffsets; TArray CurvePointOffsets; TArray ObjectGroupNames; uint32 GroupIndex = 0; for(FEditableGroomGroup& GroomGroup : EditGroom.Groups) { for( const typename FacadeType::FEditableType& EditType : FacadeType::GetEditableGroom(GroomGroup)) { for(auto& GuidePoint : EditType.ControlPoints) { PointRestPositions.Add(GuidePoint.Position); } CurvePointOffsets.Add(PointRestPositions.Num()); } ObjectCurveOffsets.Add(CurvePointOffsets.Num()); const FString GroupName = GroomAsset->GetName() + TEXT("_") + FacadeType::GroupPrefix.ToString(); ObjectGroupNames.Add(GroupName); ++GroupIndex; } FacadeType CurvesFacade(GroomCollection); CurvesFacade.InitGroomCollection(PointRestPositions, CurvePointOffsets, ObjectCurveOffsets, ObjectGroupNames); const FString GroomName = GroomAsset->GetName(); return GroomAsset; } return nullptr; } } void FGetGroomAssetDataflowNode::Evaluate(UE::Dataflow::FContext& Context, const FDataflowOutput* Out) const { if (Out->IsA(&Collection)) { FManagedArrayCollection GroomCollection; FEditableGroom EditGroom; const UGroomAsset* LocalGroom = nullptr; if(CurvesType == EGroomCollectionType::Guides) { LocalGroom = UE::Groom::Private::BuildGroomCollection( Context, GroomAsset, GroomCollection, EditGroom); } else if(CurvesType == EGroomCollectionType::Strands) { LocalGroom = UE::Groom::Private::BuildGroomCollection( Context, GroomAsset, GroomCollection, EditGroom); } if(LocalGroom) { TArray ObjectPointSamples, CurveStrandIndices; const TArray& GroupsPhysics = LocalGroom->GetHairGroupsPhysics(); for(const FHairGroupsPhysics& GroupPhysics : GroupsPhysics) { ObjectPointSamples.Add(static_cast(GroupPhysics.StrandsParameters.StrandsSize)); } UE::Groom::FGroomGuidesFacade GuidesFacade(GroomCollection); if(GroomCollection.NumElements(UE::Groom::FGroomGuidesFacade::ObjectsGroup) == 0) { GroomCollection.AddElements(ObjectPointSamples.Num(), UE::Groom::FGroomGuidesFacade::ObjectsGroup); } GuidesFacade.SetObjectPointSamples(ObjectPointSamples); } SetValue(Context, MoveTemp(GroomCollection), &Collection); } } TArray FGetGroomAssetDataflowNode::GetRenderParametersImpl() const { if(CurvesType == EGroomCollectionType::Guides) { return { {TEXT("GuidesRender"), FName("FGroomCollection"), {TEXT("Collection")}}}; } else { return { {TEXT("StrandsRender"), FName("FGroomCollection"), {TEXT("Collection")}}}; } }