void UK2Node_SpawnActorFromClass::CreatePinsForClass(UClass* InClass, TArray<UEdGraphPin*>& OutClassPins) { check(InClass != NULL); const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); const UObject* const ClassDefaultObject = InClass->GetDefaultObject(false); for (TFieldIterator<UProperty> PropertyIt(InClass, EFieldIteratorFlags::IncludeSuper); PropertyIt; ++PropertyIt) { UProperty* Property = *PropertyIt; UClass* PropertyClass = CastChecked<UClass>(Property->GetOuter()); const bool bIsDelegate = Property->IsA(UMulticastDelegateProperty::StaticClass()); const bool bIsExposedToSpawn = UEdGraphSchema_K2::IsPropertyExposedOnSpawn(Property); const bool bIsSettableExternally = !Property->HasAnyPropertyFlags(CPF_DisableEditOnInstance); if( bIsExposedToSpawn && !Property->HasAnyPropertyFlags(CPF_Parm) && bIsSettableExternally && Property->HasAllPropertyFlags(CPF_BlueprintVisible) && !bIsDelegate && (NULL == FindPin(Property->GetName()) ) ) { UEdGraphPin* Pin = CreatePin(EGPD_Input, TEXT(""), TEXT(""), NULL, false, false, Property->GetName()); const bool bPinGood = (Pin != NULL) && K2Schema->ConvertPropertyToPinType(Property, /*out*/ Pin->PinType); OutClassPins.Add(Pin); if (ClassDefaultObject && Pin != NULL && K2Schema->PinDefaultValueIsEditable(*Pin)) { FString DefaultValueAsString; const bool bDefaultValueSet = FBlueprintEditorUtils::PropertyValueToString(Property, reinterpret_cast<const uint8*>(ClassDefaultObject), DefaultValueAsString); check( bDefaultValueSet ); K2Schema->TrySetDefaultValue(*Pin, DefaultValueAsString); } // Copy tooltip from the property. if (Pin != nullptr) { K2Schema->ConstructBasicPinTooltip(*Pin, Property->GetToolTipText(), Pin->PinToolTip); } } } // Change class of output pin UEdGraphPin* ResultPin = GetResultPin(); ResultPin->PinType.PinSubCategoryObject = InClass; }
void AActor::ResetPropertiesForConstruction() { // Get class CDO AActor* Default = GetClass()->GetDefaultObject<AActor>(); // RandomStream struct name to compare against const FName RandomStreamName(TEXT("RandomStream")); // We don't want to reset references to world object const bool bIsLevelScriptActor = IsA(ALevelScriptActor::StaticClass()); // Iterate over properties for( TFieldIterator<UProperty> It(GetClass()) ; It ; ++It ) { UProperty* Prop = *It; UStructProperty* StructProp = Cast<UStructProperty>(Prop); UClass* PropClass = CastChecked<UClass>(Prop->GetOuter()); // get the class that added this property // First see if it is a random stream, if so reset before running construction script if( (StructProp != NULL) && (StructProp->Struct != NULL) && (StructProp->Struct->GetFName() == RandomStreamName) ) { FRandomStream* StreamPtr = StructProp->ContainerPtrToValuePtr<FRandomStream>(this); StreamPtr->Reset(); } // If it is a blueprint added variable that is not editable per-instance, reset to default before running construction script else if( !bIsLevelScriptActor && Prop->HasAnyPropertyFlags(CPF_DisableEditOnInstance) && PropClass->HasAnyClassFlags(CLASS_CompiledFromBlueprint) && !Prop->IsA(UDelegateProperty::StaticClass()) && !Prop->IsA(UMulticastDelegateProperty::StaticClass()) ) { Prop->CopyCompleteValue_InContainer(this, Default); } } }
bool FScriptCodeGeneratorBase::CanExportFunction(const FString& ClassNameCPP, UClass* Class, UFunction* Function) { // We don't support delegates and non-public functions if ((Function->FunctionFlags & FUNC_Delegate)) { return false; } // Reject if any of the parameter types is unsupported yet for (TFieldIterator<UProperty> ParamIt(Function); ParamIt; ++ParamIt) { UProperty* Param = *ParamIt; if (Param->IsA(UArrayProperty::StaticClass()) || Param->ArrayDim > 1 || Param->IsA(UDelegateProperty::StaticClass()) || Param->IsA(UMulticastDelegateProperty::StaticClass()) || Param->IsA(UWeakObjectProperty::StaticClass()) || Param->IsA(UInterfaceProperty::StaticClass())) { return false; } } return true; }
FString CollectPropertyDescription(const UObject* Ob, const UClass* StopAtClass, const TArray<UProperty*>& PropertyData) { FString RetString; for (UProperty* TestProperty = Ob->GetClass()->PropertyLink; TestProperty; TestProperty = TestProperty->PropertyLinkNext) { // stop when reaching base class if (TestProperty->GetOuter() == StopAtClass) { break; } // skip properties without any setup data if (TestProperty->HasAnyPropertyFlags(CPF_Transient) || TestProperty->HasAnyPropertyFlags(CPF_DisableEditOnInstance) || PropertyData.Contains(TestProperty)) { continue; } if (TestProperty->IsA(UClassProperty::StaticClass()) || TestProperty->IsA(UStructProperty::StaticClass()) || CanUsePropertyType(TestProperty)) { if (RetString.Len()) { RetString.AppendChar(TEXT('\n')); } const uint8* PropData = TestProperty->ContainerPtrToValuePtr<uint8>(Ob); RetString += DescribeProperty(TestProperty, PropData); } } return RetString; }
void UBehaviorTreeGraphNode::DiffProperties(UStruct* Struct, void* DataA, void* DataB, FDiffResults& Results, FDiffSingleResult& Diff) { for (TFieldIterator<UProperty> PropertyIt(Struct, EFieldIteratorFlags::IncludeSuper); PropertyIt; ++PropertyIt) { UProperty* Prop = *PropertyIt; // skip properties we cant see if (!Prop->HasAnyPropertyFlags(CPF_Edit|CPF_BlueprintVisible) || Prop->HasAnyPropertyFlags(CPF_Transient) || Prop->HasAnyPropertyFlags(CPF_DisableEditOnInstance) || Prop->IsA(UFunction::StaticClass()) || Prop->IsA(UDelegateProperty::StaticClass()) || Prop->IsA(UMulticastDelegateProperty::StaticClass())) { continue; } FString ValueStringA = BlueprintNodeHelpers::DescribeProperty(Prop, Prop->ContainerPtrToValuePtr<uint8>(DataA)); FString ValueStringB = BlueprintNodeHelpers::DescribeProperty(Prop, Prop->ContainerPtrToValuePtr<uint8>(DataB)); if ( ValueStringA != ValueStringB ) { if(Results) { Diff.DisplayString = FText::Format(LOCTEXT("DIF_NodePropertyFmt", "Property Changed: {0} "), FText::FromString(Prop->GetName())); Results.Add(Diff); } } } }
void SGraphPinLiveEditVar::GenerateComboBoxIndexesRecurse( UStruct *InStruct, FString PropertyPrefix, TArray< TSharedPtr<int32> >& OutComboBoxIndexes ) { check( InStruct != NULL ); for (TFieldIterator<UProperty> PropertyIt(InStruct, EFieldIteratorFlags::IncludeSuper); PropertyIt; ++PropertyIt) { UProperty* Property = *PropertyIt; if ( !Property->IsA(UNumericProperty::StaticClass()) ) { if ( Property->IsA(UStructProperty::StaticClass()) ) { UStructProperty *StructProp = Cast<UStructProperty>(Property); if ( IsPropertyPermitedForLiveEditor(*StructProp) ) { if ( Property->ArrayDim > 1 ) { for ( int32 i = 0; i < Property->ArrayDim; ++i ) { FString arrayIndex = FString::Printf( TEXT("[%d]"), i ); FString NewPropertyPrefix = FString::Printf( TEXT("%s%s%s."), *PropertyPrefix, *Property->GetName(), *arrayIndex ); GenerateComboBoxIndexesRecurse( StructProp->Struct, NewPropertyPrefix, OutComboBoxIndexes ); } } else { FString NewPropertyPrefix = FString::Printf( TEXT("%s%s."), *PropertyPrefix, *Property->GetName() ); GenerateComboBoxIndexesRecurse( StructProp->Struct, NewPropertyPrefix, OutComboBoxIndexes ); } } } else if ( Property->IsA(UArrayProperty::StaticClass()) ) { UArrayProperty *ArrayProp = Cast<UArrayProperty>(Property); } continue; } if ( IsPropertyPermitedForLiveEditor(*Property) ) { if ( Property->ArrayDim > 1 ) { for ( int32 i = 0; i < Property->ArrayDim; ++i ) { FString arrayIndex = FString::Printf( TEXT("[%d]"), i ); FString Name = PropertyPrefix + Property->GetName() + arrayIndex; VariableNameList.Add( Name ); } } else { FString Name = PropertyPrefix + Property->GetName(); VariableNameList.Add( Name ); } } } }
void UK2Node_SpawnActor::CreatePinsForClass(UClass* InClass) { check(InClass != NULL); const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); for (TFieldIterator<UProperty> PropertyIt(InClass, EFieldIteratorFlags::IncludeSuper); PropertyIt; ++PropertyIt) { UProperty* Property = *PropertyIt; UClass* PropertyClass = CastChecked<UClass>(Property->GetOuter()); const bool bIsDelegate = Property->IsA(UMulticastDelegateProperty::StaticClass()); const bool bIsExposedToSpawn = UEdGraphSchema_K2::IsPropertyExposedOnSpawn(Property); const bool bIsSettableExternally = !Property->HasAnyPropertyFlags(CPF_DisableEditOnInstance); if( bIsExposedToSpawn && !Property->HasAnyPropertyFlags(CPF_Parm) && bIsSettableExternally && Property->HasAllPropertyFlags(CPF_BlueprintVisible) && !bIsDelegate ) { UEdGraphPin* Pin = CreatePin(EGPD_Input, TEXT(""), TEXT(""), NULL, false, false, Property->GetName()); const bool bPinGood = (Pin != NULL) && K2Schema->ConvertPropertyToPinType(Property, /*out*/ Pin->PinType); } } // Change class of output pin UEdGraphPin* ResultPin = GetResultPin(); ResultPin->PinType.PinSubCategoryObject = InClass; }
void SetCellValue( const TSharedRef< IPropertyTableCell >& Cell, FString Value ) { if ( Cell->IsReadOnly() ) { return; } // We need to sanitize property name strings TSharedPtr<FPropertyNode> PropertyNode = Cell->GetNode(); if (PropertyNode.IsValid()) { UProperty* NodeProperty = PropertyNode->GetProperty(); if (NodeProperty->IsA(UNameProperty::StaticClass())) { // Remove any pre-existing return characters Value = Value.TrimQuotes().Replace(TEXT("\n"), TEXT("")); } } FString CurrentValue = Cell->GetValueAsString(); if ( CurrentValue != Value ) { // Set value Cell->SetValueFromString( Value ); } }
uint8* UAnimSequenceBase::FindNotifyPropertyData(int32 NotifyIndex, UArrayProperty*& ArrayProperty) { // initialize to NULL ArrayProperty = NULL; if(Notifies.IsValidIndex(NotifyIndex)) { // find Notifies property start point UProperty* Property = FindField<UProperty>(GetClass(), TEXT("Notifies")); // found it and if it is array if(Property && Property->IsA(UArrayProperty::StaticClass())) { // find Property Value from UObject we got uint8* PropertyValue = Property->ContainerPtrToValuePtr<uint8>(this); // it is array, so now get ArrayHelper and find the raw ptr of the data ArrayProperty = CastChecked<UArrayProperty>(Property); FScriptArrayHelper ArrayHelper(ArrayProperty, PropertyValue); if(ArrayProperty->Inner && NotifyIndex < ArrayHelper.Num()) { //Get property data based on selected index return ArrayHelper.GetRawPtr(NotifyIndex); } } } return NULL; }
void SPropertyEditorCombo::SendToObjects( const FString& NewValue ) { const TSharedRef< FPropertyNode > PropertyNode = PropertyEditor->GetPropertyNode(); UProperty* Property = PropertyNode->GetProperty(); FString Value; if ( bUsesAlternateDisplayValues && !Property->IsA(UStrProperty::StaticClass())) { // currently only enum properties can use alternate display values; this // might change, so assert here so that if support is expanded to other // property types without updating this block of code, we'll catch it quickly UEnum* Enum = CastChecked<UByteProperty>(Property)->Enum; check(Enum != nullptr); const int32 Index = FindEnumValueIndex(Enum, NewValue); check( Index != INDEX_NONE ); Value = Enum->GetEnumName(Index); FText ToolTipValue = Enum->GetToolTipText(Index); FText ToolTipText = Property->GetToolTipText(); if (!ToolTipValue.IsEmpty()) { ToolTipText = FText::Format(FText::FromString(TEXT("{0}\n\n{1}")), ToolTipText, ToolTipValue); } SetToolTipText(ToolTipText); } else { Value = NewValue; } const TSharedRef< IPropertyHandle > PropertyHandle = PropertyEditor->GetPropertyHandle(); PropertyHandle->SetValueFromFormattedString( Value ); }
//------------------------------------------------------------------------------ static void BlueprintActionDatabaseImpl::AddClassPropertyActions(UClass const* const Class, FActionList& ActionListOut) { using namespace FBlueprintNodeSpawnerFactory; // for MakeDelegateNodeSpawner() bool const bIsComponent = Class->IsChildOf<UActorComponent>(); bool const bIsActorClass = Class->IsChildOf<AActor>(); // loop over all the properties in the specified class; exclude-super because // we can always get the super properties by looking up that class separateHavely for (TFieldIterator<UProperty> PropertyIt(Class, EFieldIteratorFlags::ExcludeSuper); PropertyIt; ++PropertyIt) { UProperty* Property = *PropertyIt; if (!IsPropertyBlueprintVisible(Property)) { continue; } bool const bIsDelegate = Property->IsA(UMulticastDelegateProperty::StaticClass()); if (bIsDelegate) { UMulticastDelegateProperty* DelegateProperty = CastChecked<UMulticastDelegateProperty>(Property); if (DelegateProperty->HasAnyPropertyFlags(CPF_BlueprintAssignable)) { UBlueprintNodeSpawner* AddSpawner = UBlueprintDelegateNodeSpawner::Create(UK2Node_AddDelegate::StaticClass(), DelegateProperty); ActionListOut.Add(AddSpawner); UBlueprintNodeSpawner* AssignSpawner = MakeAssignDelegateNodeSpawner(DelegateProperty); ActionListOut.Add(AssignSpawner); } if (DelegateProperty->HasAnyPropertyFlags(CPF_BlueprintCallable)) { UBlueprintNodeSpawner* CallSpawner = UBlueprintDelegateNodeSpawner::Create(UK2Node_CallDelegate::StaticClass(), DelegateProperty); ActionListOut.Add(CallSpawner); } UBlueprintNodeSpawner* RemoveSpawner = UBlueprintDelegateNodeSpawner::Create(UK2Node_RemoveDelegate::StaticClass(), DelegateProperty); ActionListOut.Add(RemoveSpawner); UBlueprintNodeSpawner* ClearSpawner = UBlueprintDelegateNodeSpawner::Create(UK2Node_ClearDelegate::StaticClass(), DelegateProperty); ActionListOut.Add(ClearSpawner); if (bIsComponent) { ActionListOut.Add(MakeComponentBoundEventSpawner(DelegateProperty)); } else if (bIsActorClass) { ActionListOut.Add(MakeActorBoundEventSpawner(DelegateProperty)); } } else { UBlueprintVariableNodeSpawner* GetterSpawner = UBlueprintVariableNodeSpawner::Create(UK2Node_VariableGet::StaticClass(), Property); ActionListOut.Add(GetterSpawner); UBlueprintVariableNodeSpawner* SetterSpawner = UBlueprintVariableNodeSpawner::Create(UK2Node_VariableSet::StaticClass(), Property); ActionListOut.Add(SetterSpawner); } } }
bool FPropertyTableColumn::CanSortBy() const { TWeakObjectPtr< UObject > Object = DataSource->AsUObject(); UProperty* Property = Cast< UProperty >( Object.Get() ); TSharedPtr< FPropertyPath > Path = DataSource->AsPropertyPath(); if ( Property == NULL && Path.IsValid() ) { Property = Path->GetLeafMostProperty().Property.Get(); } if ( Property != NULL ) { return Property->IsA( UByteProperty::StaticClass() ) || Property->IsA( UIntProperty::StaticClass() ) || Property->IsA( UBoolProperty::StaticClass() ) || Property->IsA( UFloatProperty::StaticClass() ) || Property->IsA( UNameProperty::StaticClass() ) || Property->IsA( UStrProperty::StaticClass() ) || ( Property->IsA( UObjectProperty::StaticClass() ) && !Property->HasAnyPropertyFlags(CPF_InstancedReference) ); //Property->IsA( UTextProperty::StaticClass() ); } return false; }
void FCSharpWrapperGenerator::GenerateFunctionWrapper(const UFunction* Function) { FString formalInteropArgs, actualInteropArgs, formalManagedArgs, actualManagedArgs; UProperty* returnValue = GetWrapperArgsAndReturnType( Function, formalInteropArgs, actualInteropArgs, formalManagedArgs, actualManagedArgs ); const bool bHasReturnValue = (returnValue != nullptr); const bool bReturnsBool = (bHasReturnValue && returnValue->IsA(UBoolProperty::StaticClass())); const FString returnValueInteropTypeName = bHasReturnValue ? GetPropertyInteropType(returnValue) : TEXT("void"); const FString returnValueManagedTypeName = bHasReturnValue ? GetPropertyManagedType(returnValue) : TEXT("void"); const FString delegateTypeName = GetDelegateTypeName(Function->GetName(), bHasReturnValue); const FString delegateName = GetDelegateName(Function->GetName()); GeneratedGlue // declare a managed delegate type matching the type of the native wrapper function << UnmanagedFunctionPointerAttribute << (bReturnsBool ? MarshalReturnedBoolAsUint8Attribute : FString()) << FString::Printf( TEXT("private delegate %s %s(%s);"), *returnValueInteropTypeName, *delegateTypeName, *formalInteropArgs ) // declare a delegate instance that will be bound to the native wrapper function << FString::Printf( TEXT("private static %s %s;"), *delegateTypeName, *delegateName ) // define a managed method that calls the native wrapper function through the delegate // declared above << FString::Printf( TEXT("public %s %s(%s)"), *returnValueManagedTypeName, *Function->GetName(), *formalManagedArgs ) << FCodeFormatter::OpenBrace(); // call the delegate bound to the native wrapper function if (bHasReturnValue) { GeneratedGlue << FString::Printf(TEXT("var value = %s(%s);"), *delegateName, *actualInteropArgs) << GetReturnValueHandler(returnValue); } else { GeneratedGlue << FString::Printf(TEXT("%s(%s);"), *delegateName, *actualInteropArgs); } GeneratedGlue << FCodeFormatter::CloseBrace() << FCodeFormatter::LineTerminator(); FExportedFunction funcInfo; funcInfo.DelegateName = delegateName; funcInfo.DelegateTypeName = delegateTypeName; ExportedFunctions.Add(funcInfo); }
void SPropertyEditorCombo::SendToObjects( const FString& NewValue ) { const TSharedRef< FPropertyNode > PropertyNode = PropertyEditor->GetPropertyNode(); UProperty* Property = PropertyNode->GetProperty(); FString Value; FString ToolTipValue; if ( bUsesAlternateDisplayValues && !Property->IsA(UStrProperty::StaticClass())) { // currently only enum properties can use alternate display values; this might change, so assert here so that if support is expanded to other property types // without updating this block of code, we'll catch it quickly UEnum* Enum = CastChecked<UByteProperty>(Property)->Enum; check(Enum); int32 Index = INDEX_NONE; for( int32 ItemIndex = 0; ItemIndex < Enum->NumEnums(); ++ItemIndex ) { const FString EnumName = Enum->GetEnumName(ItemIndex); const FString DisplayName = Enum->GetDisplayNameText(ItemIndex ).ToString(); if( DisplayName.Len() > 0 ) { if ( DisplayName == NewValue ) { Index = ItemIndex; break; } } else if (EnumName == NewValue) { Index = ItemIndex; break; } } check( Index != INDEX_NONE ); Value = Enum->GetEnumName(Index); ToolTipValue = Enum->GetMetaData( TEXT("ToolTip"), Index ); FString ToolTipText = Property->GetToolTipText().ToString(); if (ToolTipValue.Len() > 0) { ToolTipText = FString::Printf(TEXT("%s\n\n%s"), *ToolTipText, *ToolTipValue); } SetToolTipText(ToolTipText); } else { Value = NewValue; } const TSharedRef< IPropertyHandle > PropertyHandle = PropertyEditor->GetPropertyHandle(); PropertyHandle->SetValueFromFormattedString( Value ); }
void UK2Node_AddComponent::AllocatePinsForExposedVariables() { const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); const UActorComponent* TemplateComponent = GetTemplateFromNode(); const UClass* ComponentClass = TemplateComponent ? TemplateComponent->GetClass() : nullptr; if (ComponentClass != nullptr) { const UObject* ClassDefaultObject = ComponentClass ? ComponentClass->ClassDefaultObject : nullptr; for (TFieldIterator<UProperty> PropertyIt(ComponentClass, EFieldIteratorFlags::IncludeSuper); PropertyIt; ++PropertyIt) { UProperty* Property = *PropertyIt; const bool bNotDelegate = !Property->IsA(UMulticastDelegateProperty::StaticClass()); const bool bIsExposedToSpawn = UEdGraphSchema_K2::IsPropertyExposedOnSpawn(Property); const bool bIsVisible = Property->HasAllPropertyFlags(CPF_BlueprintVisible); const bool bNotParam = !Property->HasAllPropertyFlags(CPF_Parm); if(bNotDelegate && bIsExposedToSpawn && bIsVisible && bNotParam) { FEdGraphPinType PinType; K2Schema->ConvertPropertyToPinType(Property, /*out*/ PinType); const bool bIsUnique = (NULL == FindPin(Property->GetName())); if (K2Schema->FindSetVariableByNameFunction(PinType) && bIsUnique) { UEdGraphPin* Pin = CreatePin(EGPD_Input, TEXT(""), TEXT(""), NULL, false, false, Property->GetName()); Pin->PinType = PinType; bHasExposedVariable = true; if ((ClassDefaultObject != nullptr) && K2Schema->PinDefaultValueIsEditable(*Pin)) { FString DefaultValueAsString; const bool bDefaultValueSet = FBlueprintEditorUtils::PropertyValueToString(Property, reinterpret_cast<const uint8*>(ClassDefaultObject), DefaultValueAsString); check(bDefaultValueSet); K2Schema->TrySetDefaultValue(*Pin, DefaultValueAsString); } // Copy tooltip from the property. K2Schema->ConstructBasicPinTooltip(*Pin, Property->GetToolTipText(), Pin->PinToolTip); } } } } // Hide transform and attachment pins if it is not a scene component const bool bHideTransformPins = (ComponentClass != nullptr) ? !ComponentClass->IsChildOf(USceneComponent::StaticClass()) : false; UEdGraphPin* ManualAttachmentPin = GetManualAttachmentPin(); ManualAttachmentPin->SafeSetHidden(bHideTransformPins); UEdGraphPin* TransformPin = GetRelativeTransformPin(); TransformPin->SafeSetHidden(bHideTransformPins); }
bool FStructureEditorUtils::CanEnableMultiLineText(const UUserDefinedStruct* Struct, FGuid VarGuid) { auto VarDesc = GetVarDescByGuid(Struct, VarGuid); if (VarDesc) { UProperty* Property = FindField<UProperty>(Struct, VarDesc->VarName); // If this is an array, we need to test its inner property as that's the real type if (UArrayProperty* ArrayProperty = Cast<UArrayProperty>(Property)) { Property = ArrayProperty->Inner; } if (Property) { // Can only set multi-line text on string and text properties return Property->IsA(UStrProperty::StaticClass()) || Property->IsA(UTextProperty::StaticClass()); } } return false; }
void ULiveEditorKismetLibrary::ReplicateChangesToChildren( FName PropertyName, UObject *Archetype ) { if ( Archetype == NULL ) return; //find our child instances from the LiveEditManage lookup cache TArray< TWeakObjectPtr<UObject> > PiePartners; FLiveEditorManager::Get().FindPiePartners( Archetype, PiePartners ); for(TArray< TWeakObjectPtr<UObject> >::TIterator It(PiePartners); It; ++It) { if ( !(*It).IsValid() ) continue; UObject *Object = (*It).Get(); check( Object->IsA(Archetype->GetClass()) ); //little sanity check, but the object cache manages all this for us nLiveEditorKismetLibrary::CopyPropertyFromArchetype( Object, Archetype, PropertyName ); } void *ContainerPtr = Archetype; int32 ArrayIndex = 0; UProperty *Prop = nLiveEditorKismetLibrary::GetPropertyByName( Archetype, Archetype->GetClass(), PropertyName.ToString(), &ContainerPtr, ArrayIndex ); if ( Prop && Prop->IsA( UNumericProperty::StaticClass() ) ) { check( ContainerPtr != NULL ); FString ClassName = Archetype->GetClass()->GetName(); FString ValueString; void *Value = Prop->ContainerPtrToValuePtr<void>(ContainerPtr, ArrayIndex); Prop->ExportTextItem(ValueString, Value, NULL, NULL, 0); FLiveEditorManager::Get().BroadcastValueUpdate( ClassName, PropertyName.ToString(), ValueString ); } /** * Object iteration method should we want to dump the PIEObjectCache * Downside is that it is perceptably slow (though still usable) TArray<UObject*> ObjectsToChange; const bool bIncludeDerivedClasses = true; GetObjectsOfClass(Archetype->GetClass(), ObjectsToChange, bIncludeDerivedClasses); for ( auto ObjIt = ObjectsToChange.CreateIterator(); ObjIt; ++ObjIt ) { UObject *Object = *ObjIt; UWorld *World = GEngine->GetWorldFromContextObject( Object, false ); if ( World == NULL || World->WorldType != EWorldType::PIE ) continue; CopyPropertyFromArchetype( Object, Archetype, PropertyName ); } */ }
bool FDeviceProfileTextureLODSettingsColumn::Supports(const TSharedRef< IPropertyTableColumn >& Column, const TSharedRef< IPropertyTableUtilities >& Utilities) const { if( Column->GetDataSource()->IsValid() ) { TSharedPtr< FPropertyPath > PropertyPath = Column->GetDataSource()->AsPropertyPath(); if( PropertyPath.IsValid() && PropertyPath->GetNumProperties() > 0 ) { const FPropertyInfo& PropertyInfo = PropertyPath->GetRootProperty(); UProperty* Property = PropertyInfo.Property.Get(); if (Property->GetName() == TEXT("TextureLODGroups") && Property->IsA(UArrayProperty::StaticClass())) { return true; } } } return false; }
bool SGraphPinLiveEditVar::IsPropertyPermitedForLiveEditor( UProperty &Property ) { const bool bIsDelegate = Property.IsA(UMulticastDelegateProperty::StaticClass()); //YES (must have all) uint64 MustHaveFlags = CPF_Edit; //NO (must not have any) uint64 MustNotHaveFlags = CPF_BlueprintReadOnly | CPF_DisableEditOnInstance | CPF_EditConst | CPF_Parm; if ( !Property.HasAllPropertyFlags(MustHaveFlags) ) return false; if ( Property.HasAnyPropertyFlags(MustNotHaveFlags) ) return false; if ( bIsDelegate ) return false; return true; }
void FPropertyTableRow::GenerateChildren() { if ( !DataSource->IsValid() || DataSource->AsPropertyPath().IsValid() ) { return; } const TSharedRef< class IPropertyTable > TableRef = GetTable(); TWeakObjectPtr< UObject > Object = DataSource->AsUObject(); TSharedRef< FObjectPropertyNode > ObjectNode = TableRef->GetObjectPropertyNode( Object ); TSharedRef< FPropertyPath > RootPath = TableRef->GetRootPath(); TSharedPtr< FPropertyNode > PropertyNode = FPropertyNode::FindPropertyNodeByPath( RootPath, ObjectNode ); if ( !PropertyNode.IsValid() ) { return; } PropertyNode = FPropertyNode::FindPropertyNodeByPath( PartialPath, PropertyNode.ToSharedRef() ); if ( !PropertyNode.IsValid() ) { return; } UProperty* Property = PropertyNode->GetProperty(); if ( Property != NULL && Property->IsA( UArrayProperty::StaticClass() ) ) { for (int Index = 0; Index < PropertyNode->GetNumChildNodes(); Index++) { TSharedPtr< FPropertyNode > ChildNode = PropertyNode->GetChildNode( Index ); FPropertyInfo Extension; Extension.Property = ChildNode->GetProperty(); Extension.ArrayIndex = ChildNode->GetArrayIndex(); Children.Add( MakeShareable( new FPropertyTableRow( TableRef, Object, RootPath->ExtendPath( Extension ) ) ) ); } } }
uint8* UAnimSequenceBase::FindArrayProperty(const TCHAR* PropName, UArrayProperty*& ArrayProperty, int32 ArrayIndex) { // find Notifies property start point UProperty* Property = FindField<UProperty>(GetClass(), PropName); // found it and if it is array if (Property && Property->IsA(UArrayProperty::StaticClass())) { // find Property Value from UObject we got uint8* PropertyValue = Property->ContainerPtrToValuePtr<uint8>(this); // it is array, so now get ArrayHelper and find the raw ptr of the data ArrayProperty = CastChecked<UArrayProperty>(Property); FScriptArrayHelper ArrayHelper(ArrayProperty, PropertyValue); if (ArrayProperty->Inner && ArrayIndex < ArrayHelper.Num()) { //Get property data based on selected index return ArrayHelper.GetRawPtr(ArrayIndex); } } return NULL; }
/** * Caches the property value */ void CacheValue() { Data.Reset(); FPropertyNode& PropertyNodeRef = *PropertyNode.Pin(); UProperty* Property = PropertyNodeRef.GetProperty(); { // Not supported yet check( !Property->IsA( UArrayProperty::StaticClass() ) ) if( PropertyNodeRef.GetArrayIndex() == INDEX_NONE && Property->ArrayDim > 1 ) { // Check static arrays Data.AddZeroed( Property->ArrayDim * Property->ElementSize ); Property->CopyCompleteValue( Data.GetData(), PropertyValueAddress); } else { // Regular properties Data.AddZeroed( Property->ElementSize ); Property->CopySingleValue( Data.GetData(), PropertyValueAddress ); } } }
void FPropertyTable::UpdateRows() { if( Orientation == EPropertyTableOrientation::AlignPropertiesInColumns ) { TMultiMap< UObject*, TSharedRef< IPropertyTableRow > > RowsMap; for (int RowIdx = 0; RowIdx < Rows.Num(); ++RowIdx) { RowsMap.Add(Rows[RowIdx]->GetDataSource()->AsUObject().Get(), Rows[RowIdx]); } Rows.Empty(); for( auto ObjectIter = SourceObjects.CreateConstIterator(); ObjectIter; ++ObjectIter ) { const TWeakObjectPtr< UObject >& Object = *ObjectIter; if( Object.IsValid() ) { const TSharedRef< FObjectPropertyNode > ObjectNode = GetObjectPropertyNode( Object ); const TSharedPtr< FPropertyNode > PropertyNode = FPropertyNode::FindPropertyNodeByPath( RootPath, ObjectNode ); //@todo This system will need to change in order to properly support arrays [11/30/2012 Justin.Sargent] if ( PropertyNode.IsValid() ) { UProperty* Property = PropertyNode->GetProperty(); if ( Property != NULL && Property->IsA( UArrayProperty::StaticClass() ) ) { for (int ChildIdx = 0; ChildIdx < PropertyNode->GetNumChildNodes(); ChildIdx++) { TSharedPtr< FPropertyNode > ChildNode = PropertyNode->GetChildNode( ChildIdx ); FPropertyInfo Extension; Extension.Property = ChildNode->GetProperty(); Extension.ArrayIndex = ChildNode->GetArrayIndex(); TSharedRef< FPropertyPath > Path = FPropertyPath::CreateEmpty()->ExtendPath( Extension ); TArray< TSharedRef< IPropertyTableRow > > MapResults; bool Found = false; RowsMap.MultiFind(Object.Get(), MapResults); for (int MapIdx = 0; MapIdx < MapResults.Num(); ++MapIdx) { if (FPropertyPath::AreEqual(Path, MapResults[MapIdx]->GetPartialPath())) { Found = true; Rows.Add(MapResults[MapIdx]); break; } } if (!Found) { Rows.Add( MakeShareable( new FPropertyTableRow( SharedThis( this ), Object, Path ) ) ); } } } else { TArray< TSharedRef< IPropertyTableRow > > MapResults; bool Found = false; RowsMap.MultiFind(Object.Get(), MapResults); for (int MapIdx = 0; MapIdx < MapResults.Num(); ++MapIdx) { if (MapResults[MapIdx]->GetPartialPath()->GetNumProperties() == 0) { Found = true; Rows.Add(MapResults[MapIdx]); break; } } if (!Found) { Rows.Add( MakeShareable( new FPropertyTableRow( SharedThis( this ), Object ) ) ); } } } } } } const TSharedPtr< IPropertyTableColumn > Column = SortedByColumn.Pin(); if ( Column.IsValid() && SortedColumnMode != EColumnSortMode::None ) { Column->Sort( Rows, SortedColumnMode ); } RowsChanged.Broadcast(); }
void FPropertyTable::UpdateColumns() { if( Orientation == EPropertyTableOrientation::AlignPropertiesInColumns) { TMultiMap< UProperty*, TSharedRef< IPropertyTableColumn > > ColumnsMap; for (int ColumnIdx = 0; ColumnIdx < Columns.Num(); ++ColumnIdx) { TSharedRef< IDataSource > DataSource = Columns[ColumnIdx]->GetDataSource(); TSharedPtr< FPropertyPath > PropertyPath = DataSource->AsPropertyPath(); if( PropertyPath.IsValid() && PropertyPath->GetNumProperties() > 0 ) { ColumnsMap.Add(PropertyPath->GetRootProperty().Property.Get(), Columns[ColumnIdx]); } } Columns.Empty(); if ( ShowRowHeader ) { TSharedRef< IPropertyTableColumn > NewColumn = MakeShareable( new FPropertyTableRowHeaderColumn( SharedThis( this ) ) ); Columns.Add( NewColumn ); } if ( ShowObjectName ) { TSharedRef< IPropertyTableColumn > NewColumn = MakeShareable( new FPropertyTableObjectNameColumn( SharedThis( this ) ) ); NewColumn->SetFrozen( true ); Columns.Add( NewColumn ); } TArray< TWeakObjectPtr< UStruct > > UniqueTypes; TArray< int > TypeCounter; for( auto ObjectIter = SourceObjects.CreateConstIterator(); ObjectIter; ++ObjectIter ) { auto Object = *ObjectIter; if( !Object.IsValid() ) { continue; } const TSharedRef< FObjectPropertyNode > RootObjectNode = GetObjectPropertyNode( Object ); TWeakObjectPtr< UStruct > Type; if ( RootPath->GetNumProperties() == 0 ) { Type = RootObjectNode->GetObjectBaseClass(); } else { const TSharedPtr< FPropertyNode > PropertyNode = FPropertyNode::FindPropertyNodeByPath( RootPath, RootObjectNode ); if ( !PropertyNode.IsValid() ) { continue; } const TWeakObjectPtr< UProperty > Property = PropertyNode->GetProperty(); if ( !Property.IsValid() || !Property->IsA( UStructProperty::StaticClass() ) ) { continue; } UStructProperty* StructProperty = Cast< UStructProperty >( Property.Get() ); Type = StructProperty->Struct; } if ( !Type.IsValid() ) { continue; } int FoundIndex = -1; if ( UniqueTypes.Find( Type, /*OUT*/FoundIndex ) ) { TypeCounter[ FoundIndex ] = TypeCounter[ FoundIndex ] + 1; continue; } UniqueTypes.Add( Type ); TypeCounter.Add( 1 ); } if ( UniqueTypes.Num() > 0 ) { int HighestCountIndex = 0; int HighestCount = 0; for (int Index = 0; Index < TypeCounter.Num(); Index++) { if ( TypeCounter[Index] > HighestCount ) { HighestCountIndex = Index; HighestCount = TypeCounter[Index]; } } TWeakObjectPtr< UStruct > PrimaryType = UniqueTypes[ HighestCountIndex ]; for (TFieldIterator<UProperty> PropertyIter( PrimaryType.Get(), EFieldIteratorFlags::IncludeSuper); PropertyIter; ++PropertyIter) { TWeakObjectPtr< UProperty > Property = *PropertyIter; if ( PropertyIter->HasAnyPropertyFlags(CPF_AssetRegistrySearchable) ) { TArray< TSharedRef< IPropertyTableColumn > > MapResults; ColumnsMap.MultiFind(Property.Get(), MapResults); if(MapResults.Num() > 0) { for (int MapIdx = 0; MapIdx < MapResults.Num(); ++MapIdx) { Columns.Add(MapResults[MapIdx]); } } else { TSharedRef< IPropertyTableColumn > NewColumn = CreateColumn( Property ); Columns.Add( NewColumn ); } } } } } else { Columns.Empty(); if( SourceObjects.Num() > 0 ) { UClass* ObjectClass = SourceObjects[0]->GetClass(); TSharedRef< IPropertyTableColumn > HeadingColumn = MakeShareable( new FPropertyTablePropertyNameColumn( SharedThis( this ) ) ); Columns.Add( HeadingColumn ); for( auto ObjectIter = SourceObjects.CreateConstIterator(); ObjectIter; ++ObjectIter ) { auto Object = *ObjectIter; if( Object.IsValid() ) { const TSharedRef< FObjectPropertyNode > ObjectNode = GetObjectPropertyNode( Object ); const TSharedPtr< FPropertyNode > PropertyNode = FPropertyNode::FindPropertyNodeByPath( RootPath, ObjectNode ); UProperty* Property = PropertyNode->GetProperty(); if ( Property != NULL && Property->IsA( UArrayProperty::StaticClass() ) ) { for (int ChildIdx = 0; ChildIdx < PropertyNode->GetNumChildNodes(); ChildIdx++) { TSharedPtr< FPropertyNode > ChildNode = PropertyNode->GetChildNode( ChildIdx ); FPropertyInfo Extension; Extension.Property = ChildNode->GetProperty(); Extension.ArrayIndex = ChildNode->GetArrayIndex(); TSharedRef< FPropertyPath > Path = FPropertyPath::CreateEmpty()->ExtendPath( Extension ); TSharedRef< IPropertyTableColumn > NewColumn = MakeShareable( new FPropertyTableColumn( SharedThis( this ), Object, Path ) ); Columns.Add( NewColumn ); } } else if ( Property != NULL ) { TSharedRef< IPropertyTableColumn > NewColumn = MakeShareable( new FPropertyTableColumn( SharedThis( this ), Object ) ); Columns.Add( NewColumn ); } } } } } ColumnsChanged.Broadcast(); }
static void CopyPropertyFromArchetype( UObject *Target, UObject *Archetype, FName PropertyName ) { if ( Target == NULL || Archetype == NULL || !Target->IsA( Archetype->GetClass() ) ) return; void *ArchetypeContainerPtr = Archetype; int32 ArchetypeArrayIndex; UProperty *Prop = GetPropertyByName( Archetype, Archetype->GetClass(), PropertyName.ToString(), &ArchetypeContainerPtr, ArchetypeArrayIndex ); if ( !Prop || !Prop->IsA( UNumericProperty::StaticClass() ) ) return; check(ArchetypeContainerPtr != NULL); void *TargetContainerPtr = Target; //(void*)((uint8*)ArchetypeContainerPtr - (uint8*)Archetype + (uint8*)Target); int32 TargetArrayIndex; UProperty *TargetProp = GetPropertyByName( Target, Target->GetClass(), PropertyName.ToString(), &TargetContainerPtr, TargetArrayIndex ); check( TargetProp != NULL && TargetProp->IsA( UNumericProperty::StaticClass() ) ); check( TargetArrayIndex == ArchetypeArrayIndex ); if ( Prop->IsA( UByteProperty::StaticClass() ) ) { UByteProperty *NumericProp = CastChecked<UByteProperty>(Prop); uint8 ArchetypeVal = NumericProp->GetPropertyValue_InContainer(ArchetypeContainerPtr, ArchetypeArrayIndex); NumericProp->SetPropertyValue_InContainer(TargetContainerPtr, ArchetypeVal, ArchetypeArrayIndex); } else if ( Prop->IsA( UInt8Property::StaticClass() ) ) { UInt8Property *NumericProp = CastChecked<UInt8Property>(Prop); int32 ArchetypeVal = NumericProp->GetPropertyValue_InContainer(ArchetypeContainerPtr, ArchetypeArrayIndex); NumericProp->SetPropertyValue_InContainer(TargetContainerPtr, ArchetypeVal, ArchetypeArrayIndex); } else if ( Prop->IsA( UInt16Property::StaticClass() ) ) { UInt16Property *NumericProp = CastChecked<UInt16Property>(Prop); int16 ArchetypeVal = NumericProp->GetPropertyValue_InContainer(ArchetypeContainerPtr, ArchetypeArrayIndex); NumericProp->SetPropertyValue_InContainer(TargetContainerPtr, ArchetypeVal, ArchetypeArrayIndex); } else if ( Prop->IsA( UIntProperty::StaticClass() ) ) { UIntProperty *NumericProp = CastChecked<UIntProperty>(Prop); int32 ArchetypeVal = NumericProp->GetPropertyValue_InContainer(ArchetypeContainerPtr, ArchetypeArrayIndex); NumericProp->SetPropertyValue_InContainer(TargetContainerPtr, ArchetypeVal, ArchetypeArrayIndex); } else if ( Prop->IsA( UInt64Property::StaticClass() ) ) { UInt64Property *NumericProp = CastChecked<UInt64Property>(Prop); int64 ArchetypeVal = NumericProp->GetPropertyValue_InContainer(ArchetypeContainerPtr, ArchetypeArrayIndex); NumericProp->SetPropertyValue_InContainer(TargetContainerPtr, ArchetypeVal, ArchetypeArrayIndex); } else if ( Prop->IsA( UUInt16Property::StaticClass() ) ) { UUInt16Property *NumericProp = CastChecked<UUInt16Property>(Prop); uint16 ArchetypeVal = NumericProp->GetPropertyValue_InContainer(ArchetypeContainerPtr, ArchetypeArrayIndex); NumericProp->SetPropertyValue_InContainer(TargetContainerPtr, ArchetypeVal, ArchetypeArrayIndex); } else if ( Prop->IsA( UUInt32Property::StaticClass() ) ) { UUInt32Property *NumericProp = CastChecked<UUInt32Property>(Prop); uint32 ArchetypeVal = NumericProp->GetPropertyValue_InContainer(ArchetypeContainerPtr, ArchetypeArrayIndex); NumericProp->SetPropertyValue_InContainer(TargetContainerPtr, ArchetypeVal, ArchetypeArrayIndex); } else if ( Prop->IsA( UInt64Property::StaticClass() ) ) { UInt64Property *NumericProp = CastChecked<UInt64Property>(Prop); uint64 ArchetypeVal = NumericProp->GetPropertyValue_InContainer(ArchetypeContainerPtr, ArchetypeArrayIndex); NumericProp->SetPropertyValue_InContainer(TargetContainerPtr, ArchetypeVal, ArchetypeArrayIndex); } else if ( Prop->IsA( UFloatProperty::StaticClass() ) ) { UFloatProperty *NumericProp = CastChecked<UFloatProperty>(Prop); float ArchetypeVal = NumericProp->GetPropertyValue_InContainer(ArchetypeContainerPtr, ArchetypeArrayIndex); NumericProp->SetPropertyValue_InContainer(TargetContainerPtr, ArchetypeVal, ArchetypeArrayIndex); } else if ( Prop->IsA( UDoubleProperty::StaticClass() ) ) { UDoubleProperty *NumericProp = CastChecked<UDoubleProperty>(Prop); double ArchetypeVal = NumericProp->GetPropertyValue_InContainer(ArchetypeContainerPtr, ArchetypeArrayIndex); NumericProp->SetPropertyValue_InContainer(TargetContainerPtr, ArchetypeVal, ArchetypeArrayIndex); } }
void UK2Node_LiveEditObject::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) { Super::ExpandNode(CompilerContext, SourceGraph); const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema(); UEdGraphPin *SourceExecPin = GetExecPin(); UEdGraphPin *SourceThenPin = GetThenPin(); UEdGraphPin *SourceBlueprintPin = GetBlueprintPin(); UEdGraphPin *SourceBaseClassPin = GetBaseClassPin(); UEdGraphPin *SourceDescriptionPin = GetDescriptionPin(); UEdGraphPin *SourcePermittedBindingsPin = GetPermittedBindingsPin(); UEdGraphPin *SourceOnMidiInputPin = GetOnMidiInputPin(); UEdGraphPin *SourceVariablePin = GetVariablePin(); if(NULL == SourceVariablePin) { CompilerContext.MessageLog.Error(*LOCTEXT("LiveEditObjectNodeMissingBlueprint_Error", "LiveEdit node @@ must have a blueprint specified and a variable selected to tune.").ToString(), this); // we break exec links so this is the only error we get, don't want the SpawnActor node being considered and giving 'unexpected node' type warnings BreakAllNodeLinks(); return; } UClass* SpawnClass = GetClassToSpawn(); if(NULL == SpawnClass) { CompilerContext.MessageLog.Error(*LOCTEXT("LiveEditObjectNodeMissingBaseClass_Error", "LiveEdit node @@ must have a Base Class specified.").ToString(), this); // we break exec links so this is the only error we get, don't want the SpawnActor node being considered and giving 'unexpected node' type warnings BreakAllNodeLinks(); return; } if ( SourcePermittedBindingsPin->LinkedTo.Num() == 0 ) { CompilerContext.MessageLog.Error(*LOCTEXT("LiveEditObjectNodeMissingBinding_Error", "LiveEdit node @@ must specify Permitted Bindings.").ToString(), this); // we break exec links so this is the only error we get, don't want the SpawnActor node being considered and giving 'unexpected node' type warnings BreakAllNodeLinks(); return; } //sanity check the VariablePin value { UProperty *Property = UK2Node_LiveEditObjectStatics::GetPropertyByName( SpawnClass, *SourceVariablePin->DefaultValue ); if ( Property == NULL || !Property->IsA(UNumericProperty::StaticClass()) ) { CompilerContext.MessageLog.Error(*LOCTEXT("LiveEditObjectNodeInvalidVariable_Error", "LiveEdit node @@ must have a valid variable selected.").ToString(), this); // we break exec links so this is the only error we get, don't want the SpawnActor node being considered and giving 'unexpected node' type warnings BreakAllNodeLinks(); return; } } //hooks to pins that are generated after a BaseClass is set UEdGraphPin *DeltaMultPin = GetDeltaMultPin(); UEdGraphPin *ShouldClampPin = GetShouldClampPin(); UEdGraphPin *ClampMinPin = GetClampMinPin(); UEdGraphPin *ClampMaxPin = GetClampMaxPin(); UK2Node_Self *SelfNode = CompilerContext.SpawnIntermediateNode<UK2Node_Self>(this,SourceGraph); SelfNode->AllocateDefaultPins(); UEdGraphPin *SelfNodeThenPin = SelfNode->FindPinChecked(Schema->PN_Self); FString EventNameGuid = GetEventName(); //Create the registration part of the LiveEditor binding process { UK2Node_CallFunction *RegisterForMIDINode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph); RegisterForMIDINode->FunctionReference.SetExternalMember( TEXT("RegisterForLiveEditEvent"), ULiveEditorKismetLibrary::StaticClass() ); RegisterForMIDINode->AllocateDefaultPins(); UEdGraphPin *ExecPin = RegisterForMIDINode->GetExecPin(); CompilerContext.MovePinLinksToIntermediate(*SourceExecPin, *ExecPin); UEdGraphPin *ThenPin = RegisterForMIDINode->GetThenPin(); CompilerContext.MovePinLinksToIntermediate(*SourceThenPin, *ThenPin); UEdGraphPin *TargetPin = RegisterForMIDINode->FindPinChecked( FString(TEXT("Target")) ); TargetPin->MakeLinkTo(SelfNodeThenPin); UEdGraphPin *EventNamePin = RegisterForMIDINode->FindPinChecked( FString(TEXT("EventName")) ); EventNamePin->DefaultValue = EventNameGuid; UEdGraphPin *DescriptionPin = RegisterForMIDINode->FindPinChecked( FString(TEXT("Description")) ); CompilerContext.CopyPinLinksToIntermediate( *SourceDescriptionPin, *DescriptionPin); UEdGraphPin *PermittedBindingsPin = RegisterForMIDINode->FindPinChecked( FString(TEXT("PermittedBindings")) ); CompilerContext.CopyPinLinksToIntermediate( *SourcePermittedBindingsPin, *PermittedBindingsPin); } //Create the event handling part of the LiveEditor binding process { // //the event itself // UFunction *EventMIDISignature = GetEventMIDISignature(); UK2Node_Event* EventNode = CompilerContext.SpawnIntermediateNode<UK2Node_Event>(this, SourceGraph); check(EventNode); EventNode->EventSignatureClass = Cast<UClass>(EventMIDISignature->GetOuter()); EventNode->EventSignatureName = EventMIDISignature->GetFName(); EventNode->CustomFunctionName = *EventNameGuid; EventNode->bInternalEvent = true; EventNode->AllocateDefaultPins(); // Cache these out because we'll connect the sequence to it UEdGraphPin *EventThenPin = EventNode->FindPinChecked( Schema->PN_Then ); UEdGraphPin *EventDeltaPin = EventNode->FindPinChecked( FString(TEXT("Delta")) ); UEdGraphPin *EventMidiValuePin = EventNode->FindPinChecked( FString(TEXT("MidiValue")) ); UEdGraphPin *EventControlTypePin = EventNode->FindPinChecked( FString(TEXT("ControlType")) ); // // Check if Blueprint is NULL // UEdGraphPin *CompareBlueprintToNullBranchThenPin = NULL; { UK2Node_CallFunction *CompareBlueprintToNullNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph); CompareBlueprintToNullNode->FunctionReference.SetExternalMember( TEXT("NotEqual_ObjectObject"), UKismetMathLibrary::StaticClass() ); CompareBlueprintToNullNode->AllocateDefaultPins(); //Set A Pin to the Blueprint Pin UEdGraphPin *CompareBlueprintToNullAPin = CompareBlueprintToNullNode->FindPinChecked( FString(TEXT("A")) ); CompilerContext.CopyPinLinksToIntermediate( *SourceBlueprintPin, *CompareBlueprintToNullAPin); // hook for Compare Blueprint to NULL result UEdGraphPin *CompareBlueprintToNullResultPin = CompareBlueprintToNullNode->GetReturnValuePin(); // Create the BRANCH that will drive the comparison UK2Node_IfThenElse* CompareBlueprintToNullBranchNode = CompilerContext.SpawnIntermediateNode<UK2Node_IfThenElse>(this, SourceGraph); CompareBlueprintToNullBranchNode->AllocateDefaultPins(); //hook up the condition CompareBlueprintToNullResultPin->MakeLinkTo( CompareBlueprintToNullBranchNode->GetConditionPin() ); //hook event to the branck input EventThenPin->MakeLinkTo( CompareBlueprintToNullBranchNode->GetExecPin() ); //cache ot the THEN pin for later linkup CompareBlueprintToNullBranchThenPin = CompareBlueprintToNullBranchNode->GetThenPin(); } // // Get Class Default Object // UK2Node_CallFunction *GetClassDefaultObjectNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph); GetClassDefaultObjectNode->FunctionReference.SetExternalMember( TEXT("GetBlueprintClassDefaultObject"), ULiveEditorKismetLibrary::StaticClass() ); GetClassDefaultObjectNode->AllocateDefaultPins(); UEdGraphPin *GetClassDefaultObjectBlueprintPin = GetClassDefaultObjectNode->FindPinChecked( TEXT("Blueprint") ); CompilerContext.CopyPinLinksToIntermediate( *SourceBlueprintPin, *GetClassDefaultObjectBlueprintPin); //hook for later -> the pointer to the ClassDefaultObject of our BlueprintPin UEdGraphPin *GetClassDefaultObjectResultPin = GetClassDefaultObjectNode->GetReturnValuePin(); // // Compare to BaseClass to make sure that the target Blueprint IsA(BaseClass) // UEdGraphPin *ClassIsChildOfBranchThenPin = NULL; { // //we need to get the class of the Blueprint pin UK2Node_CallFunction *GetClassNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph); GetClassNode->FunctionReference.SetExternalMember( TEXT("GetObjectClass"), UGameplayStatics::StaticClass() ); GetClassNode->AllocateDefaultPins(); //Pin in the GetClassDefaultObjectResultPin to the Object Parameter of the GetObjectClass FUNCTION //we want to make sure that the Class of the DEFAULT_OBJECT IsA( BaseClass ) UEdGraphPin *GetClassObjectPin = GetClassNode->FindPinChecked( FString(TEXT("Object")) ); GetClassDefaultObjectResultPin->MakeLinkTo( GetClassObjectPin ); //hook for the Class result UEdGraphPin *GetClassReturnValuePin = GetClassNode->GetReturnValuePin(); // //the ClassIsChildOf FUNCTION UK2Node_CallFunction *ClassIsChildOfNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph); ClassIsChildOfNode->FunctionReference.SetExternalMember( TEXT("ClassIsChildOf"), UKismetMathLibrary::StaticClass() ); ClassIsChildOfNode->AllocateDefaultPins(); //hook up the test pin UEdGraphPin *ClassIsChildOfTestPin = ClassIsChildOfNode->FindPinChecked( FString(TEXT("TestClass")) ); GetClassReturnValuePin->MakeLinkTo( ClassIsChildOfTestPin ); //copy our BaseClass Pin into the ClassIsChildOf Parameter UEdGraphPin *ClassIsChildOfParentPin = ClassIsChildOfNode->FindPinChecked( FString(TEXT("ParentClass")) ); CompilerContext.CopyPinLinksToIntermediate( *SourceBaseClassPin, *ClassIsChildOfParentPin); //hook for return value UEdGraphPin *ClassIsChildOfResultPin = ClassIsChildOfNode->GetReturnValuePin(); // // Create the BRANCH that will drive the comparison UK2Node_IfThenElse* ClassIsChildOfBranchNode = CompilerContext.SpawnIntermediateNode<UK2Node_IfThenElse>(this, SourceGraph); ClassIsChildOfBranchNode->AllocateDefaultPins(); //hook up the previous branch to this one check( CompareBlueprintToNullBranchThenPin != NULL ); CompareBlueprintToNullBranchThenPin->MakeLinkTo( ClassIsChildOfBranchNode->GetExecPin() ); //hook up our condition ClassIsChildOfResultPin->MakeLinkTo( ClassIsChildOfBranchNode->GetConditionPin() ); //cache ot the THEN pin for later linkup ClassIsChildOfBranchThenPin = ClassIsChildOfBranchNode->GetThenPin(); } // //The set variable function (to set LiveEdited new value) // UK2Node_CallFunction *ModifyVarNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph); ModifyVarNode->FunctionReference.SetExternalMember( TEXT("ModifyPropertyByName"), ULiveEditorKismetLibrary::StaticClass() ); ModifyVarNode->AllocateDefaultPins(); // Make link from the event to the Set variable node UEdGraphPin *ModifyVarExecPin = ModifyVarNode->GetExecPin(); ClassIsChildOfBranchThenPin->MakeLinkTo( ModifyVarExecPin ); //link up the Target Pin UEdGraphPin *ModifyVarNodeTargetPin = ModifyVarNode->FindPinChecked( TEXT("Target") ); GetClassDefaultObjectResultPin->MakeLinkTo( ModifyVarNodeTargetPin ); //link up the PropertyName Pin UEdGraphPin *ModifyVarNodePropertyNamePin = ModifyVarNode->FindPinChecked( TEXT("PropertyName") ); ModifyVarNodePropertyNamePin->DefaultValue = SourceVariablePin->DefaultValue; //link up the MIDI Value Pin UEdGraphPin *ModifyVarNodeMidiValuePin = ModifyVarNode->FindPinChecked( TEXT("MidiValue") ); EventMidiValuePin->MakeLinkTo(ModifyVarNodeMidiValuePin); //link up the ControlType Pin UEdGraphPin *ModifyVarNodeControlTypePin = ModifyVarNode->FindPinChecked( TEXT("ControlType") ); EventControlTypePin->MakeLinkTo(ModifyVarNodeControlTypePin); //hook for the Delta Pin UEdGraphPin *ModifyVarNodeDeltaPin = ModifyVarNode->FindPinChecked( TEXT("Delta") ); //Clamping if ( ShouldClampPin->DefaultValue == FString(TEXT("true")) ) { UEdGraphPin *ModifyVarNodeShouldClampPin = ModifyVarNode->FindPinChecked( TEXT("bShouldClamp") ); CompilerContext.CopyPinLinksToIntermediate( *ShouldClampPin, *ModifyVarNodeShouldClampPin); check( ClampMinPin != NULL ); UEdGraphPin *ModifyVarNodeClampMinPin = ModifyVarNode->FindPinChecked( TEXT("ClampMin") ); CompilerContext.CopyPinLinksToIntermediate( *ClampMinPin, *ModifyVarNodeClampMinPin); check( ClampMaxPin != NULL ); UEdGraphPin *ModifyVarNodeClampMaxPin = ModifyVarNode->FindPinChecked( TEXT("ClampMax") ); CompilerContext.CopyPinLinksToIntermediate( *ClampMaxPin, *ModifyVarNodeClampMaxPin); } //hook for ModifyVar THEN UEdGraphPin *ModifyVarNodeThenPin = ModifyVarNode->GetThenPin(); // // The Multiply Delta * DeltaMult function // UK2Node_CallFunction *MultiplyNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph); MultiplyNode->FunctionReference.SetExternalMember( TEXT("Multiply_FloatFloat"), UKismetMathLibrary::StaticClass() ); MultiplyNode->AllocateDefaultPins(); //cache this out. it will be linked to from the output of the (int)Delta -> (float)Delta Conversion function UEdGraphPin *MultiplyNodeFirstPin = MultiplyNode->FindPinChecked( FString(TEXT("A")) ); // 2nd input to the Add function comes from the Current variable value UEdGraphPin *MultiplyNodeSecondPin = MultiplyNode->FindPinChecked( FString(TEXT("B")) ); CompilerContext.CopyPinLinksToIntermediate( *DeltaMultPin, *MultiplyNodeSecondPin); UEdGraphPin *MultiplyNodeReturnValuePin = MultiplyNode->GetReturnValuePin(); MultiplyNodeReturnValuePin->MakeLinkTo( ModifyVarNodeDeltaPin ); // // The Convert function to go from (int)Delta to ULiveEditorKismetLibrary::ModifyPropertyByName(... float Delta ...) // FName ConvertFunctionName; bool success = Schema->SearchForAutocastFunction( EventDeltaPin, MultiplyNodeFirstPin, ConvertFunctionName ); check( success ); UK2Node_CallFunction *ConvertDeltaNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph); ConvertDeltaNode->FunctionReference.SetExternalMember( ConvertFunctionName, UKismetMathLibrary::StaticClass() ); ConvertDeltaNode->AllocateDefaultPins(); FName PinName; success = UK2Node_LiveEditObjectStatics::SearchForConvertPinName( Schema, EventDeltaPin, PinName ); check( success ); UEdGraphPin *ConvertDeltaInputPin = ConvertDeltaNode->FindPinChecked( PinName.ToString() ); EventDeltaPin->MakeLinkTo( ConvertDeltaInputPin ); UEdGraphPin *ConvertDeltaOutputPin = ConvertDeltaNode->GetReturnValuePin(); ConvertDeltaOutputPin->MakeLinkTo( MultiplyNodeFirstPin ); // // TODO - markDirty // // // send out the object value updates // UK2Node_CallFunction *ReplicationNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this,SourceGraph); ReplicationNode->FunctionReference.SetExternalMember( TEXT("ReplicateChangesToChildren"), ULiveEditorKismetLibrary::StaticClass() ); ReplicationNode->AllocateDefaultPins(); UEdGraphPin *ReplicationNodeVarNamePin = ReplicationNode->FindPinChecked( TEXT("PropertyName") ); ReplicationNodeVarNamePin->DefaultValue = SourceVariablePin->DefaultValue; UEdGraphPin *ReplicationNodeArchetypePin = ReplicationNode->FindPinChecked( FString(TEXT("Archetype")) ); GetClassDefaultObjectResultPin->MakeLinkTo( ReplicationNodeArchetypePin ); UEdGraphPin *ReplicationNodeExecPin = ReplicationNode->GetExecPin(); ModifyVarNodeThenPin->MakeLinkTo( ReplicationNodeExecPin ); UEdGraphPin *ReplicationNodeThenPin = ReplicationNode->FindPinChecked( FString(TEXT("then")) ); // // Finally, activate our OnMidiInput pin // CompilerContext.CopyPinLinksToIntermediate( *SourceOnMidiInputPin, *ReplicationNodeThenPin); } // Break any links to the expanded node BreakAllNodeLinks(); }
void SSingleProperty::SetObject( UObject* InObject ) { DestroyColorPicker(); if( !RootPropertyNode.IsValid() ) { RootPropertyNode = MakeShareable( new FObjectPropertyNode ); } RootPropertyNode->RemoveAllObjects(); ValueNode.Reset(); if( InObject ) { RootPropertyNode->AddObject( InObject ); } FPropertyNodeInitParams InitParams; InitParams.ParentNode = NULL; InitParams.Property = NULL; InitParams.ArrayOffset = 0; InitParams.ArrayIndex = INDEX_NONE; // we'll generate the children InitParams.bAllowChildren = false; InitParams.bForceHiddenPropertyVisibility = false; RootPropertyNode->InitNode( InitParams ); ValueNode = RootPropertyNode->GenerateSingleChild( PropertyName ); bool bIsAcceptableProperty = false; // valid criteria for standalone properties if( ValueNode.IsValid() ) { UProperty* Property = ValueNode->GetProperty(); bIsAcceptableProperty = true; // not an array property (dynamic or static) bIsAcceptableProperty &= !( Property->IsA( UArrayProperty::StaticClass() ) || (Property->ArrayDim > 1 && ValueNode->GetArrayIndex() == INDEX_NONE) ); // not a struct property unless its a built in type like a vector bIsAcceptableProperty &= ( !Property->IsA( UStructProperty::StaticClass() ) || PropertyEditorHelpers::IsBuiltInStructProperty( Property ) ); } if( bIsAcceptableProperty ) { ValueNode->RebuildChildren(); TSharedRef< FPropertyEditor > PropertyEditor = FPropertyEditor::Create( ValueNode.ToSharedRef(), TSharedPtr< IPropertyUtilities >( PropertyUtilities ).ToSharedRef() ); ValueNode->SetDisplayNameOverride( NameOverride ); TSharedPtr<SHorizontalBox> HorizontalBox; ChildSlot [ SAssignNew( HorizontalBox, SHorizontalBox ) ]; if( NamePlacement != EPropertyNamePlacement::Hidden ) { HorizontalBox->AddSlot() .Padding( 2.0f, 0.0f, 2.0f, 4.0f ) .AutoWidth() .VAlign( VAlign_Center ) [ SNew( SPropertyNameWidget, PropertyEditor ) .DisplayResetToDefault( false ) ]; } HorizontalBox->AddSlot() .Padding( 0.0f, 2.0f, 0.0f, 2.0f ) .FillWidth(1.0f) .VAlign( VAlign_Center ) [ SNew( SPropertyValueWidget, PropertyEditor, PropertyUtilities.ToSharedRef() ) ]; HorizontalBox->AddSlot() .Padding( 2.0f ) .AutoWidth() .VAlign( VAlign_Center ) [ SNew( SResetToDefaultPropertyEditor, PropertyEditor ) ]; } else { ChildSlot [ SNew(STextBlock) .Font(PropertyFont) .Text(NSLOCTEXT("PropertyEditor", "SinglePropertyInvalidType", "Cannot Edit Inline")) .ToolTipText(NSLOCTEXT("PropertyEditor", "SinglePropertyInvalidType_Tooltip", "Properties of this type cannot be edited inline; edit it elsewhere")) ]; // invalid or missing property RootPropertyNode->RemoveAllObjects(); ValueNode.Reset(); RootPropertyNode.Reset(); } }
static void SetPropertyValue( UObject *Target, const FString &PropertyName, const FString &PropertyValue ) { if ( Target == NULL ) return; void *ContainerPtr = Target; int32 ArrayIndex; UProperty *Prop = nLiveEditorListenServer::GetPropertyByName( Target, Target->GetClass(), PropertyName, &ContainerPtr, ArrayIndex ); if ( !Prop || !Prop->IsA( UNumericProperty::StaticClass() ) ) { return; } check( ContainerPtr != NULL ); if ( Prop->IsA( UByteProperty::StaticClass() ) ) { UByteProperty *NumericProp = CastChecked<UByteProperty>(Prop); uint8 Value = FCString::Atoi( *PropertyValue ); NumericProp->SetPropertyValue_InContainer(ContainerPtr, Value, ArrayIndex); } else if ( Prop->IsA( UInt8Property::StaticClass() ) ) { UInt8Property *NumericProp = CastChecked<UInt8Property>(Prop); int32 Value = FCString::Atoi( *PropertyValue ); NumericProp->SetPropertyValue_InContainer(ContainerPtr, Value, ArrayIndex); } else if ( Prop->IsA( UInt16Property::StaticClass() ) ) { UInt16Property *NumericProp = CastChecked<UInt16Property>(Prop); int16 Value = FCString::Atoi( *PropertyValue ); NumericProp->SetPropertyValue_InContainer(ContainerPtr, Value, ArrayIndex); } else if ( Prop->IsA( UIntProperty::StaticClass() ) ) { UIntProperty *NumericProp = CastChecked<UIntProperty>(Prop); int32 Value = FCString::Atoi( *PropertyValue ); NumericProp->SetPropertyValue_InContainer(ContainerPtr, Value, ArrayIndex); } else if ( Prop->IsA( UInt64Property::StaticClass() ) ) { UInt64Property *NumericProp = CastChecked<UInt64Property>(Prop); int64 Value = FCString::Atoi64( *PropertyValue ); NumericProp->SetPropertyValue_InContainer(ContainerPtr, Value, ArrayIndex); } else if ( Prop->IsA( UUInt16Property::StaticClass() ) ) { UUInt16Property *NumericProp = CastChecked<UUInt16Property>(Prop); uint16 Value = FCString::Atoi( *PropertyValue ); NumericProp->SetPropertyValue_InContainer(ContainerPtr, Value, ArrayIndex); } else if ( Prop->IsA( UUInt32Property::StaticClass() ) ) { UUInt32Property *NumericProp = CastChecked<UUInt32Property>(Prop); uint32 Value = FCString::Atoi( *PropertyValue ); NumericProp->SetPropertyValue_InContainer(ContainerPtr, Value, ArrayIndex); } else if ( Prop->IsA( UInt64Property::StaticClass() ) ) { UInt64Property *NumericProp = CastChecked<UInt64Property>(Prop); uint64 Value = FCString::Atoi64( *PropertyValue ); NumericProp->SetPropertyValue_InContainer(ContainerPtr, Value, ArrayIndex); } else if ( Prop->IsA( UFloatProperty::StaticClass() ) ) { UFloatProperty *NumericProp = CastChecked<UFloatProperty>(Prop); float Value = FCString::Atof( *PropertyValue ); NumericProp->SetPropertyValue_InContainer(ContainerPtr, Value, ArrayIndex); } else if ( Prop->IsA( UDoubleProperty::StaticClass() ) ) { UDoubleProperty *NumericProp = CastChecked<UDoubleProperty>(Prop); double Value = FCString::Atod( *PropertyValue ); NumericProp->SetPropertyValue_InContainer(ContainerPtr, Value, ArrayIndex); } }
void UK2Node_LatentAbilityCall::CreatePinsForClass(UClass* InClass) { check(InClass != NULL); const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>(); const UObject* const ClassDefaultObject = InClass->GetDefaultObject(false); SpawnParmPins.Empty(); // Tasks can hide spawn parameters by doing meta = (HideSpawnParms="PropertyA,PropertyB") // (For example, hide Instigator in situations where instigator is not relevant to your task) TArray<FString> IgnorePropertyList; { UFunction* ProxyFunction = ProxyFactoryClass->FindFunctionByName(ProxyFactoryFunctionName); FString IgnorePropertyListStr = ProxyFunction->GetMetaData(FName(TEXT("HideSpawnParms"))); if (!IgnorePropertyListStr.IsEmpty()) { IgnorePropertyListStr.ParseIntoArray(IgnorePropertyList, TEXT(","), true); } } for (TFieldIterator<UProperty> PropertyIt(InClass, EFieldIteratorFlags::IncludeSuper); PropertyIt; ++PropertyIt) { UProperty* Property = *PropertyIt; UClass* PropertyClass = CastChecked<UClass>(Property->GetOuter()); const bool bIsDelegate = Property->IsA(UMulticastDelegateProperty::StaticClass()); const bool bIsExposedToSpawn = UEdGraphSchema_K2::IsPropertyExposedOnSpawn(Property); const bool bIsSettableExternally = !Property->HasAnyPropertyFlags(CPF_DisableEditOnInstance); if (bIsExposedToSpawn && !Property->HasAnyPropertyFlags(CPF_Parm) && bIsSettableExternally && Property->HasAllPropertyFlags(CPF_BlueprintVisible) && !bIsDelegate && !IgnorePropertyList.Contains(Property->GetName()) && (FindPin(Property->GetName()) == nullptr) ) { UEdGraphPin* Pin = CreatePin(EGPD_Input, TEXT(""), TEXT(""), NULL, false, false, Property->GetName()); const bool bPinGood = (Pin != NULL) && K2Schema->ConvertPropertyToPinType(Property, /*out*/ Pin->PinType); SpawnParmPins.Add(Pin); if (ClassDefaultObject && Pin && K2Schema->PinDefaultValueIsEditable(*Pin)) { FString DefaultValueAsString; const bool bDefaultValueSet = FBlueprintEditorUtils::PropertyValueToString(Property, reinterpret_cast<const uint8*>(ClassDefaultObject), DefaultValueAsString); check(bDefaultValueSet); K2Schema->TrySetDefaultValue(*Pin, DefaultValueAsString); } // Copy tooltip from the property. if (Pin != nullptr) { K2Schema->ConstructBasicPinTooltip(*Pin, Property->GetToolTipText(), Pin->PinToolTip); } } } }
void FPropertyTableColumn::Sort( TArray< TSharedRef< class IPropertyTableRow > >& Rows, const EColumnSortMode::Type SortMode ) { if ( SortMode == EColumnSortMode::None ) { return; } TWeakObjectPtr< UObject > Object = DataSource->AsUObject(); UProperty* Property = Cast< UProperty >( Object.Get() ); TSharedPtr< FPropertyPath > Path = DataSource->AsPropertyPath(); if ( Property == NULL && Path.IsValid() ) { Property = Path->GetLeafMostProperty().Property.Get(); } if (!Property) { return; } if ( Property->IsA( UByteProperty::StaticClass() ) ) { TWeakObjectPtr<UByteProperty> ByteProperty( Cast< UByteProperty >( Property ) ); if ( SortMode == EColumnSortMode::Ascending ) { Rows.Sort( FCompareRowByColumnAscending< UByteProperty >( SharedThis( this ), ByteProperty ) ); } else { Rows.Sort( FCompareRowByColumnDescending< UByteProperty >( SharedThis( this ), ByteProperty ) ); } } else if ( Property->IsA( UIntProperty::StaticClass() ) ) { TWeakObjectPtr<UIntProperty> IntProperty( Cast< UIntProperty >( Property ) ); if ( SortMode == EColumnSortMode::Ascending ) { Rows.Sort( FCompareRowByColumnAscending< UIntProperty >( SharedThis( this ), IntProperty ) ); } else { Rows.Sort( FCompareRowByColumnDescending< UIntProperty >( SharedThis( this ), IntProperty ) ); } } else if ( Property->IsA( UBoolProperty::StaticClass() ) ) { TWeakObjectPtr<UBoolProperty> BoolProperty( Cast< UBoolProperty >( Property ) ); if ( SortMode == EColumnSortMode::Ascending ) { Rows.Sort( FCompareRowByColumnAscending< UBoolProperty >( SharedThis( this ), BoolProperty ) ); } else { Rows.Sort( FCompareRowByColumnDescending< UBoolProperty >( SharedThis( this ), BoolProperty ) ); } } else if ( Property->IsA( UFloatProperty::StaticClass() ) ) { TWeakObjectPtr<UFloatProperty> FloatProperty( Cast< UFloatProperty >( Property ) ); if ( SortMode == EColumnSortMode::Ascending ) { Rows.Sort( FCompareRowByColumnAscending< UFloatProperty >( SharedThis( this ), FloatProperty ) ); } else { Rows.Sort( FCompareRowByColumnDescending< UFloatProperty >( SharedThis( this ), FloatProperty ) ); } } else if ( Property->IsA( UNameProperty::StaticClass() ) ) { TWeakObjectPtr<UNameProperty> NameProperty( Cast< UNameProperty >( Property ) ); if ( SortMode == EColumnSortMode::Ascending ) { Rows.Sort( FCompareRowByColumnAscending< UNameProperty >( SharedThis( this ), NameProperty ) ); } else { Rows.Sort( FCompareRowByColumnDescending< UNameProperty >( SharedThis( this ), NameProperty ) ); } } else if ( Property->IsA( UStrProperty::StaticClass() ) ) { TWeakObjectPtr<UStrProperty> StrProperty( Cast< UStrProperty >( Property ) ); if ( SortMode == EColumnSortMode::Ascending ) { Rows.Sort( FCompareRowByColumnAscending< UStrProperty >( SharedThis( this ), StrProperty ) ); } else { Rows.Sort( FCompareRowByColumnDescending< UStrProperty >( SharedThis( this ), StrProperty ) ); } } else if ( Property->IsA( UObjectProperty::StaticClass() ) ) { TWeakObjectPtr<UObjectProperty> ObjectProperty( Cast< UObjectProperty >( Property ) ); if ( SortMode == EColumnSortMode::Ascending ) { Rows.Sort( FCompareRowByColumnAscending< UObjectProperty >( SharedThis( this ), ObjectProperty ) ); } else { Rows.Sort( FCompareRowByColumnDescending< UObjectProperty >( SharedThis( this ), ObjectProperty ) ); } } //else if ( Property->IsA( UTextProperty::StaticClass() ) ) //{ // if ( SortMode == EColumnSortMode::Ascending ) // { // Rows.Sort( FCompareRowByColumnAscending< UTextProperty >( SharedThis( this ) ) ); // } // else // { // Rows.Sort( FCompareRowByColumnDescending< UTextProperty >( SharedThis( this ) ) ); // } //} else { check( false && "Cannot Sort Rows by this Column!" ); } }