I rescind my previous statement, I figured it out. if you have experience with c++, here’s how to access values of attributes. This is a custom PCGSettings node I created based off PCGDistanceSettings:
FPCGAsync::AsyncPointProcessing(Context, SourcePointData->GetPoints(), OutputData->GetMutablePoints(),
[OutputData, OwnerBP, GridPositionAttribute, ModifierAttribute, /*SourceShape, SourceShape,*/ &SourcePointDatas/*, MaximumDistance, ScalarAttribute, VectorAttribute, bSetDensity*/](const FPCGPoint& SourcePoint, FPCGPoint& OutPoint) {
OutPoint = SourcePoint;
/// OutPoint is the actual point, and the MetaDataEntry is just an int64 identifier
/// GetValue() asks for PCGMetadataValueKey but that is just a typedef for int32
FVector gridPosition = GridPositionAttribute->GetValue(OutPoint.MetadataEntry);
}
};
Header:
// Copyright Jordan Cain. All Rights Reserved.
#pragma once
#include "PCGSettings.h"
#include "Elements/PCGPointProcessingElementBase.h"
#include "PCG/PCGBuildingBlueprint.h"
#include "PCGAssignModifierTagsToPoints.generated.h"
namespace PCGAssignModifierTagsToPoints
{
extern const FName SourceLabel;
//extern const FName TargetLabel;
}
/**
* Assigns the provided tag to a point whose grid position falls within the provided reqs for that tag
*/
UCLASS(BlueprintType, ClassGroup = (Procedural))
class UPCGAssignModifierTagsToPointsSettings : public UPCGSettings
{
GENERATED_BODY()
public:
//~Begin UPCGSettings interface
#if WITH_EDITOR
virtual FName GetDefaultNodeName() const override { return FName(TEXT("AssignModifierTagsToPoints")); }
virtual FText GetDefaultNodeTitle() const override { return NSLOCTEXT("PCGAssignModifierTagsToPointsSettings", "NodeTitle", "AssignModifierTagsToPoints"); }
virtual FText GetNodeTooltipText() const override;
virtual EPCGSettingsType GetType() const override { return EPCGSettingsType::Spatial; }
#endif
virtual TArray<FPCGPinProperties> InputPinProperties() const override;
virtual TArray<FPCGPinProperties> OutputPinProperties() const override;
protected:
virtual FPCGElementPtr CreateElement() const override;
//~End UPCGSettings interface
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = Settings, meta = (PCG_Overridable))
/// As we cannot pass in custom structs nor arrays of structs as attribute parameter, we'll just access the bp variables directly
TSoftObjectPtr<APCGBuildingBlueprint> OwnerBlueprint = nullptr;
};
class FPCGAssignModifierTagsElement : public FPCGPointProcessingElementBase
{
protected:
virtual bool ExecuteInternal(FPCGContext* Context) const override;
};
#if UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_2
#include "CoreMinimal.h"
#endif
CPP:
// Copyright Jordan Cain. All Rights Reserved.
#include "PCG/PCGAssignModifierTagsToPoints.h"
#include "Data/PCGSpatialData.h"
#include "Helpers/PCGAsync.h"
#include "Data/PCGPointData.h"
#include "PCGContext.h"
#include "PCGPin.h"
#include "Kismet/KismetMathLibrary.h"
#include "GlobalLog.h"
#define LOCTEXT_NAMESPACE "PCGAssignModifierTagsElement"
namespace PCGAssignModifierTagsToPoints
{
const FName SourceLabel = TEXT("Source");
}
#if WITH_EDITOR
FText UPCGAssignModifierTagsToPointsSettings::GetNodeTooltipText() const
{
return LOCTEXT("PCGDistanceTooltip", "Calculates and appends a signed 'GridPosition' attribute to the source data. For each of the source points, a GridPosition attribute will be calculated against origin of points.");
}
#endif // WITH_EDITOR
TArray<FPCGPinProperties> UPCGAssignModifierTagsToPointsSettings::InputPinProperties() const
{
TArray<FPCGPinProperties> PinProperties;
FPCGPinProperties& PinPropertySource = PinProperties.Emplace_GetRef(PCGAssignModifierTagsToPoints::SourceLabel, EPCGDataType::Point);
#if WITH_EDITOR
PinPropertySource.Tooltip = LOCTEXT("PCGSourcePinTooltip", "For each of the source points, a grid position attribute will be calculated against origin of points.");
#endif // WITH_EDITOR
return PinProperties;
}
TArray<FPCGPinProperties> UPCGAssignModifierTagsToPointsSettings::OutputPinProperties() const
{
TArray<FPCGPinProperties> PinProperties;
FPCGPinProperties& PinPropertyOutput = PinProperties.Emplace_GetRef(PCGPinConstants::DefaultOutputLabel, EPCGDataType::Point);
#if WITH_EDITOR
PinPropertyOutput.Tooltip = LOCTEXT("PCGOutputPinTooltip", "The source points will be output with the newly added 'GridPosition' attribute.");
#endif // WITH_EDITOR
return PinProperties;
}
FPCGElementPtr UPCGAssignModifierTagsToPointsSettings::CreateElement() const
{
return MakeShared<FPCGAssignModifierTagsElement>();
}
bool FPCGAssignModifierTagsElement::ExecuteInternal(FPCGContext* Context) const
{
TRACE_CPUPROFILER_EVENT_SCOPE(FPCGDistanceElement::Execute);
const UPCGAssignModifierTagsToPointsSettings* Settings = Context->GetInputSettings<UPCGAssignModifierTagsToPointsSettings>();
check(Settings);
check(Settings->OwnerBlueprint);
TSoftObjectPtr<APCGBuildingBlueprint> OwnerBP = Settings->OwnerBlueprint;
//const FName AttributeName = Settings->AttributeName;
//FVector WorldLocationOfOwner = Settings->WorldLocationOfOwner;
//FRotator RotationOfOwner = Settings->RotationOfOwner;
//float WallSize = Settings->WallSize;
TArray<FPCGTaggedData> Sources = Context->InputData.GetInputsByPin(PCGAssignModifierTagsToPoints::SourceLabel);
TArray<FPCGTaggedData>& Outputs = Context->OutputData.TaggedData;
TArray<const UPCGPointData*> SourcePointDatas;
SourcePointDatas.Reserve(Sources.Num());
for (const FPCGTaggedData& Source : Sources)
{
const UPCGSpatialData* SourceData = Cast<UPCGSpatialData>(Source.Data);
if (!SourceData)
{
PCGE_LOG(Error, GraphAndLog, FText::Format(LOCTEXT("SourceMustBeSpatial", "Source must be Spatial data, found '{0}'"), FText::FromString(Source.Data->GetClass()->GetName())));
continue;
}
const UPCGPointData* SourcePointData = SourceData->ToPointData(Context);
if (!SourcePointData)
{
PCGE_LOG(Error, GraphAndLog, FText::Format(LOCTEXT("CannotConvertToPoint", "Cannot convert target '{0}' into Point data"), FText::FromString(Source.Data->GetClass()->GetName())));
continue;
}
SourcePointDatas.Add(SourcePointData);
}
for (const FPCGTaggedData& Source : Sources)
{
const UPCGSpatialData* SourceData = Cast<UPCGSpatialData>(Source.Data);
if (!SourceData)
{
PCGE_LOG(Error, GraphAndLog, LOCTEXT("InvalidInputData", "Invalid input data"));
continue;
}
const UPCGPointData* SourcePointData = SourceData->ToPointData(Context);
if (!SourcePointData)
{
PCGE_LOG(Error, GraphAndLog, LOCTEXT("CannotConvertToPointData", "Cannot convert input Spatial data to Point data"));
continue;
}
UPCGPointData* OutputData = NewObject<UPCGPointData>();
OutputData->InitializeFromData(SourcePointData);
Outputs.Add_GetRef(Source).Data = OutputData;
const FPCGMetadataAttribute<FVector>* GridPositionAttribute = OutputData->Metadata->GetConstTypedAttribute<FVector>(FName("GridPosition"));
FPCGMetadataAttribute<FName>* ModifierAttribute = OutputData->Metadata->FindOrCreateAttribute<FName>(FName("ModifierTag"), FName("NoModifier"));
check(GridPositionAttribute);
check(ModifierAttribute);
FPCGAsync::AsyncPointProcessing(Context, SourcePointData->GetPoints(), OutputData->GetMutablePoints(),
[OutputData, OwnerBP, GridPositionAttribute, ModifierAttribute, /*SourceShape, SourceShape,*/ &SourcePointDatas/*, MaximumDistance, ScalarAttribute, VectorAttribute, bSetDensity*/](const FPCGPoint& SourcePoint, FPCGPoint& OutPoint) {
OutPoint = SourcePoint;
OutPoint.MetadataEntry;
FName modifierTag = "NoModifier";
bool bMeetsModifierCriteria = false;
FVector gridPosition = GridPositionAttribute->GetValue(OutPoint.MetadataEntry);
for (FPCGModifierTagReqs& criterion : OwnerBP->modifierConditions)
{
bMeetsModifierCriteria = criterion.PointMeetsCriteria(gridPosition);
if (bMeetsModifierCriteria) { break; }/// We can break at first true criterion
/// Todo: PCG; What if a point can meet 2 criteria?
}
if (bMeetsModifierCriteria)
{
if (ModifierAttribute)
{
OutputData->Metadata->InitializeOnSet(OutPoint.MetadataEntry);
ModifierAttribute->SetValue(OutPoint.MetadataEntry, modifierTag);
}
else
{
Global::LogError(LogPCG, "UPCGAssignModifierTagsToPointsSettings", "ExecuteInternal", TEXT("Modifier: %s"), ModifierAttribute ? TEXT("Is Valid.") : TEXT("Is Not Valid"));
}
}
return true;
}
);
}
return true;
}
#undef LOCTEXT_NAMESPACE