void FAbcImportSettingsCustomization::CustomizeDetails(IDetailLayoutBuilder& LayoutBuilder) { TSharedRef<IPropertyHandle> ImportType = LayoutBuilder.GetProperty(GET_MEMBER_NAME_CHECKED(UAbcImportSettings, ImportType)); uint8 EnumValue; ImportType->GetValue(EnumValue); IDetailCategoryBuilder& CompressionBuilder = LayoutBuilder.EditCategory("Compression"); CompressionBuilder.SetCategoryVisibility(EnumValue == (uint8)EAlembicImportType::Skeletal); IDetailCategoryBuilder& StaticMeshBuilder = LayoutBuilder.EditCategory("StaticMesh"); StaticMeshBuilder.SetCategoryVisibility(EnumValue == (uint8)EAlembicImportType::StaticMesh); FSimpleDelegate OnImportTypeChangedDelegate = FSimpleDelegate::CreateSP(this, &FAbcImportSettingsCustomization::OnImportTypeChanged, &LayoutBuilder); ImportType->SetOnPropertyValueChanged(OnImportTypeChangedDelegate); if (UAbcImportSettings::Get()->bReimport) { UEnum* ImportTypeEnum = FindObject<UEnum>(ANY_PACKAGE, TEXT("EAlembicImportType")); static FText RestrictReason = FText::FromString("Unable to change type while reimporting"); TSharedPtr<FPropertyRestriction> EnumRestriction = MakeShareable(new FPropertyRestriction(RestrictReason)); for (uint8 EnumIndex = 0; EnumIndex < (ImportTypeEnum->GetMaxEnumValue() + 1); ++EnumIndex) { if (EnumValue != EnumIndex) { const FString RestrictValue = ImportTypeEnum->GetDisplayNameTextByValue(EnumIndex).ToString(); EnumRestriction->AddValue(RestrictValue); } } ImportType->AddRestriction(EnumRestriction.ToSharedRef()); } }
TSharedRef<SWidget> FTextureLODGroupLayout::MakeMipGenSettingsComboWidget(TSharedPtr<TextureMipGenSettings> InItem) { UEnum* TextureGroupEnum = FindObject<UEnum>(NULL, TEXT("/Script/Engine.TextureMipGenSettings")); const FString MipGenSettingsName = TextureGroupEnum->GetMetaData(TEXT("DisplayName"), *InItem.Get()); return SNew(STextBlock).Text(FText::FromString(MipGenSettingsName)).Font(IDetailLayoutBuilder::GetDetailFont()); }
FText FTextureLODGroupLayout::GetMipGenSettingsComboBoxContent() const { UEnum* TextureGroupEnum = FindObject<UEnum>(NULL, TEXT("/Script/Engine.TextureMipGenSettings")); const FString MipGenSettingsName = TextureGroupEnum->GetMetaData(TEXT("DisplayName"), LodGroup->MipGenSettings); return FText::FromString(MipGenSettingsName); }
void FIntroTutorials::AddSummonBlueprintTutorialsMenuExtension(FMenuBuilder& MenuBuilder, UObject* PrimaryObject) { MenuBuilder.BeginSection("Tutorials", LOCTEXT("TutorialsLabel", "Tutorials")); MenuBuilder.AddMenuEntry( LOCTEXT("BlueprintMenuEntryTitle", "Blueprint Overview"), LOCTEXT("BlueprintMenuEntryToolTip", "Opens up an introductory overview of Blueprints."), FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.Tutorials"), FUIAction(FExecuteAction::CreateRaw(this, &FIntroTutorials::SummonBlueprintTutorialHome, PrimaryObject, true))); if(PrimaryObject != nullptr) { UBlueprint* BP = Cast<UBlueprint>(PrimaryObject); if(BP != nullptr) { UEnum* Enum = FindObject<UEnum>(ANY_PACKAGE, TEXT("EBlueprintType"), true); check(Enum); MenuBuilder.AddMenuEntry( FText::Format(LOCTEXT("BlueprintTutorialsMenuEntryTitle", "{0} Tutorial"), Enum->GetEnumText(BP->BlueprintType)), LOCTEXT("BlueprintTutorialsMenuEntryToolTip", "Opens up an introductory tutorial covering this particular part of the Blueprint editor."), FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.Tutorials"), FUIAction(FExecuteAction::CreateRaw(this, &FIntroTutorials::SummonBlueprintTutorialHome, PrimaryObject, false))); } } MenuBuilder.EndSection(); }
void USoundGroups::Initialize() const { for (int32 ProfileIndex = 0; ProfileIndex < SoundGroupProfiles.Num(); ++ProfileIndex) { SoundGroupMap.Add(SoundGroupProfiles[ProfileIndex].SoundGroup, SoundGroupProfiles[ProfileIndex]); } if (!SoundGroupMap.Find(SOUNDGROUP_Default)) { UE_LOG(LogAudio, Warning, TEXT("Missing default SoundGroup profile. Creating default with no decompression.")); SoundGroupMap.Add(SOUNDGROUP_Default, FSoundGroup()); } #if WITH_EDITOR UEnum* SoundGroupEnum = FindObjectChecked<UEnum>(NULL, TEXT("/Script/Engine.ESoundGroup")); for (const auto& It : SoundGroupMap) { if (It.Value.DisplayName.Len() > 0) { SoundGroupEnum->SetMetaData(TEXT("DisplayName"), *It.Value.DisplayName, It.Key); SoundGroupEnum->RemoveMetaData(TEXT("Hidden"), It.Key); } else { if (SoundGroupEnum->HasMetaData(TEXT("Hidden"), It.Key)) { UE_LOG(LogAudio, Warning, TEXT("Custom Game SoundGroup profile for %s defined but no display name supplied."), *SoundGroupEnum->GetEnumText(It.Key).ToString()); } SoundGroupEnum->RemoveMetaData(TEXT("Hidden"), It.Key); } } #endif }
void FEnvQueryTestDetails::BuildScoreClampingTypeValues(bool bBuildMinValues, TArray<FTextIntPair>& ClampTypeValues) const { UEnum* ScoringNormalizationEnum = FindObject<UEnum>(ANY_PACKAGE, TEXT("EEnvQueryTestClamping")); check(ScoringNormalizationEnum); ClampTypeValues.Reset(); ClampTypeValues.Add(FTextIntPair(ScoringNormalizationEnum->GetEnumText(EEnvQueryTestClamping::None), EEnvQueryTestClamping::None)); ClampTypeValues.Add(FTextIntPair(ScoringNormalizationEnum->GetEnumText(EEnvQueryTestClamping::SpecifiedValue), EEnvQueryTestClamping::SpecifiedValue)); if (IsFiltering()) { bool bSupportFilterThreshold = false; if (bBuildMinValues) { if (UsesFilterMin()) { bSupportFilterThreshold = true; } } else if (UsesFilterMax()) { bSupportFilterThreshold = true; } if (bSupportFilterThreshold) { ClampTypeValues.Add(FTextIntPair(ScoringNormalizationEnum->GetEnumText(EEnvQueryTestClamping::FilterThreshold), EEnvQueryTestClamping::FilterThreshold)); } } }
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 ); }
FORCEINLINE bool FCompareUObjectByPropertyAscending<UByteProperty>::ComparePropertyValue( const uint8& LhsValue, const uint8& RhsValue ) const { // Bytes are trivially sorted numerically UEnum* PropertyEnum = Property->GetIntPropertyEnum(); if( PropertyEnum == NULL ) { return LhsValue < RhsValue; } else { // But Enums are sorted alphabetically based on the full enum entry name - must be sure that values are within Enum bounds! bool bLhsEnumValid = LhsValue < PropertyEnum->NumEnums(); bool bRhsEnumValid = RhsValue < PropertyEnum->NumEnums(); if(bLhsEnumValid && bRhsEnumValid) { FName LhsEnumName( PropertyEnum->GetEnum( LhsValue ) ); FName RhsEnumName( PropertyEnum->GetEnum( RhsValue ) ); return LhsEnumName.Compare( RhsEnumName ) < 0; } else if(bLhsEnumValid) { return true; } else if(bRhsEnumValid) { return false; } else { return LhsValue < RhsValue; } } }
FString FAndroidTargetSettingsCustomization::OrientationToString(const EAndroidScreenOrientation::Type Orientation) { extern ANDROIDRUNTIMESETTINGS_API class UEnum* Z_Construct_UEnum_UAndroidRuntimeSettings_EAndroidScreenOrientation(); UEnum* Enum = Z_Construct_UEnum_UAndroidRuntimeSettings_EAndroidScreenOrientation(); check(Enum != nullptr); return Enum->GetMetaData(TEXT("ManifestValue"), (int32)Orientation); }
FString FAndroidTargetSettingsCustomization::DepthBufferPreferenceToString(const EAndroidDepthBufferPreference::Type DepthBufferPreference) { extern ANDROIDRUNTIMESETTINGS_API class UEnum* Z_Construct_UEnum_UAndroidRuntimeSettings_EAndroidDepthBufferPreference(); UEnum* Enum = Z_Construct_UEnum_UAndroidRuntimeSettings_EAndroidDepthBufferPreference(); check(Enum != nullptr); return Enum->GetMetaData(TEXT("ManifestValue"), (int32)DepthBufferPreference); }
FString UEnvQueryTest_Trace::GetDescriptionTitle() const { UEnum* ChannelEnum = FindObject<UEnum>(ANY_PACKAGE, TEXT("ETraceTypeQuery"), true); FString ChannelDesc = ChannelEnum->GetEnumString(TraceChannel); FString DirectionDesc = TraceToItem.IsNamedParam() ? FString::Printf(TEXT("%s, direction: %s"), *UEnvQueryTypes::DescribeContext(Context), *UEnvQueryTypes::DescribeBoolParam(TraceToItem)) : FString::Printf(TEXT("%s %s"), TraceToItem.Value ? TEXT("from") : TEXT("to"), *UEnvQueryTypes::DescribeContext(Context)); return FString::Printf(TEXT("%s: %s on %s"), *Super::GetDescriptionTitle(), *DirectionDesc, *ChannelDesc); }
void FTextureLODGroupLayout::GenerateHeaderRowContent(FDetailWidgetRow& NodeRow) { UEnum* TextureGroupEnum = FindObject<UEnum>(NULL, TEXT("/Script/Engine.TextureGroup")); const FString LODGroupName = TextureGroupEnum->GetMetaData(TEXT("DisplayName"), LodGroup->Group); NodeRow.NameContent() [ SNew(STextBlock) .Text(FText::FromString(LODGroupName)) .Font(IDetailLayoutBuilder::GetDetailFont()) ]; }
FText UEnvQueryTest_Trace::GetDescriptionTitle() const { UEnum* ChannelEnum = FindObject<UEnum>(ANY_PACKAGE, TEXT("ETraceTypeQuery"), true); FString ChannelDesc = ChannelEnum->GetEnumText(TraceData.TraceChannel).ToString(); FString DirectionDesc = TraceFromContext.IsDynamic() ? FString::Printf(TEXT("%s, direction: %s"), *UEnvQueryTypes::DescribeContext(Context).ToString(), *TraceFromContext.ToString()) : FString::Printf(TEXT("%s %s"), TraceFromContext.DefaultValue ? TEXT("from") : TEXT("to"), *UEnvQueryTypes::DescribeContext(Context).ToString()); return FText::FromString(FString::Printf(TEXT("%s: %s on %s"), *Super::GetDescriptionTitle().ToString(), *DirectionDesc, *ChannelDesc)); }
void UK2Node::PostReconstructNode() { if (!IsTemplate()) { // Make sure we're not dealing with a menu node UEdGraph* OuterGraph = GetGraph(); if( OuterGraph && OuterGraph->Schema ) { const UEdGraphSchema_K2* Schema = Cast<const UEdGraphSchema_K2>(GetSchema()); // fix up any pin data if it needs to for( auto PinIt = Pins.CreateIterator(); PinIt; ++PinIt ) { UEdGraphPin* CurrentPin = *PinIt; const FString& PinCategory = CurrentPin->PinType.PinCategory; // fix up enum names if it exists in enum redirects if (PinCategory == Schema->PC_Byte) { UEnum* EnumPtr = Cast<UEnum>(CurrentPin->PinType.PinSubCategoryObject.Get()); if (EnumPtr) { const FString& PinValue = CurrentPin->DefaultValue; // see if this enum is in EnumRedirects int32 EnumIndex = UEnum::FindEnumRedirects(EnumPtr, *PinValue); if (EnumIndex != INDEX_NONE) { FString EnumName = EnumPtr->GetEnumName(EnumIndex); // if the name does not match with pin value, override pin value if (EnumName != PinValue) { // I'm not marking package as dirty // as I know that's not going to work during serialize or post load CurrentPin->DefaultValue = EnumName; continue; } } } } else if (PinCategory == Schema->PC_Object) { UClass const* PinClass = Cast<UClass const>(CurrentPin->PinType.PinSubCategoryObject.Get()); if ((PinClass != nullptr) && PinClass->IsChildOf(UInterface::StaticClass())) { CurrentPin->PinType.PinCategory = Schema->PC_Interface; } } } } } }
UEnum* FEnumEditorUtils::CreateUserDefinedEnum(UObject* InParent, FName EnumName, EObjectFlags Flags) { ensure(0 != (RF_Public & Flags)); UEnum* Enum = NewObject<UUserDefinedEnum>(InParent, EnumName, Flags); if (NULL != Enum) { TArray<TPair<FName, int8>> EmptyNames; Enum->SetEnums(EmptyNames, UEnum::ECppForm::Namespaced); Enum->SetMetaData(TEXT("BlueprintType"), TEXT("true")); } return Enum; }
void FFeaturePackContentSource::HandleSuperSearchTextChanged(const FString& InText, TArray< TSharedPtr<FSearchEntry> >& OutSuggestions) { FString FeaturePackSearchCat = LOCTEXT("FeaturePackSearchCategory", "Feature Packs").ToString(); FString CurrentLanguage = FInternationalization::Get().GetCurrentCulture()->GetTwoLetterISOLanguageName(); FLocalizedText CurrentName = ChooseLocalizedText(LocalizedNames,CurrentLanguage); FLocalizedTextArray CurrentTagSet = ChooseLocalizedTextArray(LocalizedSearchTags,CurrentLanguage); FText AsText = FText::FromString(InText); TArray<FText> TagArray = CurrentTagSet.GetTags(); if (TagArray.Num() != 0) { UEnum* Enum = FindObjectChecked<UEnum>(ANY_PACKAGE, TEXT("EContentSourceCategory")); // Add a feature packs category for (int32 iTag = 0; iTag < TagArray.Num(); iTag++) { if (TagArray[iTag].EqualToCaseIgnored(AsText)) { // This will add the category if one doesnt exist TryAddFeaturePackCategory(FeaturePackSearchCat,OutSuggestions); TSharedPtr<FSearchEntry> FeaturePackEntry = MakeShareable(new FSearchEntry()); FeaturePackEntry->Title = FText::Format( LOCTEXT("FeaturePackSearchResult", "{0} ({1})"), CurrentName.GetText(), Enum->GetDisplayNameText((int32)Category)).ToString(); FeaturePackEntry->bCategory = false; OutSuggestions.Add(FeaturePackEntry); return; } } } }
void UPhysicsSettings::LoadSurfaceType() { // read "SurfaceType" defines and set meta data for the enum // find the enum UEnum * Enum = FindObject<UEnum>(ANY_PACKAGE, TEXT("EPhysicalSurface"), true); // we need this Enum check(Enum); const FString KeyName = TEXT("DisplayName"); const FString HiddenMeta = TEXT("Hidden"); const FString UnusedDisplayName = TEXT("Unused"); // remainders, set to be unused for(int32 EnumIndex=1; EnumIndex<Enum->NumEnums(); ++EnumIndex) { // if meta data isn't set yet, set name to "Unused" until we fix property window to handle this // make sure all hide and set unused first // if not hidden yet if(!Enum->HasMetaData(*HiddenMeta, EnumIndex)) { Enum->SetMetaData(*HiddenMeta, TEXT(""), EnumIndex); Enum->SetMetaData(*KeyName, *UnusedDisplayName, EnumIndex); } } for(auto Iter=PhysicalSurfaces.CreateConstIterator(); Iter; ++Iter) { // @todo only for editor Enum->SetMetaData(*KeyName, *Iter->Name.ToString(), Iter->Type); // also need to remove "Hidden" Enum->RemoveMetaData(*HiddenMeta, Iter->Type); } }
UEnum* UJavascriptLibrary::CreateEnum(UObject* Outer, FName Name, TArray<FName> DisplayNames) { UEnum* Enum = NewObject<UEnum>(Outer,Name,RF_Public); if (NULL != Enum) { TArray<TPair<FName, uint8>> Names; int32 Index = 0; for (auto DisplayName : DisplayNames) { Names.Add(TPairInitializer<FName, uint8>(DisplayName, Index)); Index++; } Enum->SetEnums(Names, UEnum::ECppForm::Namespaced); } return Enum; }
void UK2Node_EaseFunction::RefreshPinVisibility() { const auto EaseFuncPin = GetEaseFuncPin(); UEnum * Enum = FindObject<UEnum>(ANY_PACKAGE, TEXT("EEasingFunc"), true); check(Enum != NULL); const int32 NewEasingFunc = CanCustomizeCurve() ? Enum->GetValueByName(*EaseFuncPin->DefaultValue) : -1; // Early exit in case no changes are required const UEdGraphSchema_K2* K2Schema = Cast<const UEdGraphSchema_K2>(GetSchema()); UEdGraphPin* BlendExpPin = FindPinChecked(FEaseFunctionNodeHelper::GetBlendExpPinName()); if (NewEasingFunc == -1 || NewEasingFunc == EEasingFunc::EaseIn || NewEasingFunc == EEasingFunc::EaseOut || NewEasingFunc == EEasingFunc::EaseInOut) { // Show the BlendExpPin BlendExpPin->bHidden = false; } else { // Hide the BlendExpPin: BlendExpPin->BreakAllPinLinks(); BlendExpPin->bHidden = true; } UEdGraphPin* StepsPin = FindPinChecked(FEaseFunctionNodeHelper::GetStepsPinName()); if (NewEasingFunc == -1 || NewEasingFunc == EEasingFunc::Step) { // Show the Steps pin: StepsPin->bHidden = false; } else { // Hide the Steps pin: StepsPin->BreakAllPinLinks(); StepsPin->bHidden = true; } }
void FEnvQueryTestDetails::BuildScoreEquationValues() { UEnum* TestScoreEquationEnum = FindObject<UEnum>(ANY_PACKAGE, TEXT("EEnvTestScoreEquation")); check(TestScoreEquationEnum); ScoreEquationValues.Reset(); // Const scoring is always valid. But other equations are only valid if the score values can be other than boolean values. ScoreEquationValues.Add(FTextIntPair(TestScoreEquationEnum->GetEnumText(EEnvTestScoreEquation::Constant), EEnvTestScoreEquation::Constant)); const UEnvQueryTest* EditedTest = Cast<const UEnvQueryTest>(MyTest.Get()); if (EditedTest) { if (EditedTest->GetWorkOnFloatValues()) { ScoreEquationValues.Add(FTextIntPair(TestScoreEquationEnum->GetEnumText(EEnvTestScoreEquation::Linear), EEnvTestScoreEquation::Linear)); ScoreEquationValues.Add(FTextIntPair(TestScoreEquationEnum->GetEnumText(EEnvTestScoreEquation::Square), EEnvTestScoreEquation::Square)); ScoreEquationValues.Add(FTextIntPair(TestScoreEquationEnum->GetEnumText(EEnvTestScoreEquation::InverseLinear), EEnvTestScoreEquation::InverseLinear)); } } }
FORCEINLINE bool FCompareRowByColumnAscending<UByteProperty>::ComparePropertyValue( const TSharedPtr< IPropertyHandle >& LhsPropertyHandle, const TSharedPtr< IPropertyHandle >& RhsPropertyHandle ) const { // Get the basic uint8 values uint8 LhsValue; LhsPropertyHandle->GetValue( LhsValue ); uint8 RhsValue; RhsPropertyHandle->GetValue( RhsValue ); // Bytes are trivially sorted numerically UEnum* PropertyEnum = Property->GetIntPropertyEnum(); if( PropertyEnum == NULL ) { return LhsValue < RhsValue; } else { // But Enums are sorted alphabetically based on the full enum entry name - must be sure that values are within Enum bounds! bool bLhsEnumValid = LhsValue < PropertyEnum->NumEnums(); bool bRhsEnumValid = RhsValue < PropertyEnum->NumEnums(); if(bLhsEnumValid && bRhsEnumValid) { FName LhsEnumName( PropertyEnum->GetEnum( LhsValue ) ); FName RhsEnumName( PropertyEnum->GetEnum( RhsValue ) ); return LhsEnumName.Compare( RhsEnumName ) < 0; } else if(bLhsEnumValid) { return true; } else if(bRhsEnumValid) { return false; } else { return LhsValue < RhsValue; } } }
END_SLATE_FUNCTION_BUILD_OPTIMIZATION void FEnvQueryTestDetails::BuildFilterTestValues() { UEnum* TestConditionEnum = FindObject<UEnum>(ANY_PACKAGE, TEXT("EEnvTestFilterType")); check(TestConditionEnum); FilterTestValues.Reset(); const UEnvQueryTest* EditedTest = Cast<const UEnvQueryTest>(MyTest.Get()); if (EditedTest) { if (EditedTest->GetWorkOnFloatValues()) { FilterTestValues.Add(FTextIntPair(TestConditionEnum->GetEnumText(EEnvTestFilterType::Minimum), EEnvTestFilterType::Minimum)); FilterTestValues.Add(FTextIntPair(TestConditionEnum->GetEnumText(EEnvTestFilterType::Maximum), EEnvTestFilterType::Maximum)); FilterTestValues.Add(FTextIntPair(TestConditionEnum->GetEnumText(EEnvTestFilterType::Range), EEnvTestFilterType::Range)); } else { FilterTestValues.Add(FTextIntPair(TestConditionEnum->GetEnumText(EEnvTestFilterType::Match), EEnvTestFilterType::Match)); } } }
void UGatherTextFromMetaDataCommandlet::GatherTextFromUObject(UField* const Field) { const int32 MetaDataCount = 3; const FString MetaDataKeys[MetaDataCount] = { TEXT("ToolTip"), TEXT("DisplayName"), TEXT("Category") }; const FString AssociatedNamespaces[MetaDataCount] = { TEXT("UObjectToolTips"), TEXT("UObjectDisplayNames"), TEXT("UObjectCategories") }; // Gather for object. { for(int32 i = 0; i < MetaDataCount; ++i) { const FString& MetaDataValue = Field->GetMetaData(*MetaDataKeys[i]); if(!(MetaDataValue.IsEmpty())) { const FString Namespace = AssociatedNamespaces[i]; FLocItem LocItem(MetaDataValue); FContext Context; Context.Key = MetaDataKeys[i] == TEXT("Category") ? MetaDataValue : Field->GetFullGroupName(true) + TEXT(".") + Field->GetName(); Context.SourceLocation = TEXT("Run-time MetaData"); ManifestInfo->AddEntry(TEXT("EntryDescription"), Namespace, LocItem, Context); } } } // For enums, also gather for enum values. { UEnum* Enum = Cast<UEnum>(Field); if(Enum) { const int32 ValueCount = Enum->NumEnums(); for(int32 i = 0; i < ValueCount; ++i) { for(int32 j = 0; j < MetaDataCount; ++j) { const FString& MetaDataValue = Enum->GetMetaData(*MetaDataKeys[j], i); if(!(MetaDataValue.IsEmpty())) { const FString Namespace = AssociatedNamespaces[j]; FLocItem LocItem(MetaDataValue); FContext Context; Context.Key = MetaDataKeys[j] == TEXT("Category") ? MetaDataValue : Enum->GetFullGroupName(true) + TEXT(".") + Enum->GetName() + TEXT(".") + Enum->GetEnumName(i); Context.SourceLocation = TEXT("Run-time MetaData"); ManifestInfo->AddEntry(TEXT("EntryDescription"), Namespace, LocItem, Context); } } } } } }
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 ); }
const FSoundGroup& USoundGroups::GetSoundGroup(const ESoundGroup SoundGroup) const { // Initialize the settings if this gets called early enough to require it if (SoundGroupMap.Num() == 0) { Initialize(); } const FSoundGroup* SG = SoundGroupMap.Find(SoundGroup); if (SG == NULL) { UEnum* SoundGroupEnum = FindObjectChecked<UEnum>(NULL, TEXT("/Script/Engine.ESoundGroup")); UE_LOG(LogAudio, Warning, TEXT("Requested SoundGroup %s does not have defined profile. Using SOUNDGROUP_Default."), *SoundGroupEnum->GetEnumText(SoundGroup).ToString()); return SoundGroupMap.FindChecked(SOUNDGROUP_Default); } return *SG; }
void FFeaturePackContentSource::HandleActOnSearchText(TSharedPtr<FSearchEntry> SearchEntry) { if (SearchEntry.IsValid()) { if (SearchEntry->bCategory == false) { UEnum* Enum = FindObjectChecked<UEnum>(ANY_PACKAGE, TEXT("EContentSourceCategory")); FString CurrentLanguage = FInternationalization::Get().GetCurrentCulture()->GetTwoLetterISOLanguageName(); FLocalizedText CurrentName = ChooseLocalizedText(LocalizedNames,CurrentLanguage); FString MyTitle = FText::Format( LOCTEXT("FeaturePackSearchResult", "{0} ({1})"), CurrentName.GetText(), Enum->GetDisplayNameText((int32)Category)).ToString(); if (SearchEntry->Title == MyTitle) { IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>(TEXT("MainFrame")); IAddContentDialogModule& AddContentDialogModule = FModuleManager::LoadModuleChecked<IAddContentDialogModule>("AddContentDialog"); AddContentDialogModule.ShowDialog(MainFrameModule.GetParentWindow().ToSharedRef()); } } } }
void UCollisionProfile::LoadProfileConfig(bool bForceInit) { /** * This function loads all config data to memory * * 1. First it fixes the meta data for each custom channel name since those meta data is used for #2 * 2. Load Default Profile so that it can be used later * 3. Second it sets up Correct ResponseToChannel for all profiles * 4. It loads profile redirect data **/ // read "EngineTraceChanne" and "GameTraceChanne" and set meta data FConfigSection* Configs = GConfig->GetSectionPrivate( TEXT("/Script/Engine.CollisionProfile"), false, true, GEngineIni ); // before any op, verify if profiles contains invalid name - such as Custom profile name - remove all of them for (auto Iter=Profiles.CreateConstIterator(); Iter; ++Iter) { // make sure it doens't have any if (Iter->Name == CustomCollisionProfileName) { UE_LOG(LogCollisionProfile, Error, TEXT("Profiles contain invalid name : %s is reserved for internal use"), *CustomCollisionProfileName.ToString()); Profiles.RemoveAt(Iter.GetIndex()); } } // 1. First loads all meta data for custom channels // this can be used in #2, so had to fix up first // this is to replace ECollisionChannel's DisplayName to be defined by users FString EngineTraceChannel = TEXT("EngineTraceChannel"); FString GameTraceChannel = TEXT("GameTraceChannel"); // find the enum UEnum* Enum = FindObject<UEnum>(ANY_PACKAGE, TEXT("ECollisionChannel"), true); // we need this Enum check (Enum); UStruct* Struct = FCollisionResponseContainer::StaticStruct(); check (Struct); const FString KeyName = TEXT("DisplayName"); const FString TraceType = TEXT("TraceQuery"); const FString TraceValue = TEXT("1"); const FString HiddenMeta = TEXT("Hidden"); // need to initialize displaynames separate int32 NumEnum = Enum->NumEnums(); ChannelDisplayNames.Empty(NumEnum); ChannelDisplayNames.AddZeroed(NumEnum); TraceTypeMapping.Empty(); ObjectTypeMapping.Empty(); // first go through enum entry, and add suffix to displaynames int32 PrefixLen = FString(TEXT("ECC_")).Len(); // need to have mapping table between ECollisionChannel and EObjectTypeQuery/ETraceTypeQuery UEnum* ObjectTypeEnum = FindObject<UEnum>(ANY_PACKAGE, TEXT("EObjectTypeQuery"), true); UEnum* TraceTypeEnum = FindObject<UEnum>(ANY_PACKAGE, TEXT("ETraceTypeQuery"), true); check (ObjectTypeEnum && TraceTypeEnum); for ( int32 EnumIndex=0; EnumIndex<NumEnum; ++EnumIndex ) { FString EnumName = Enum->GetEnumName(EnumIndex); EnumName = EnumName.RightChop(PrefixLen); FName DisplayName = FName(*EnumName); if ( IS_VALID_COLLISIONCHANNEL(EnumIndex) ) { // verify if the Struct name matches // this is to avoid situations where they mismatch and causes random bugs UField* Field = FindField<UField>(Struct, DisplayName); if (!Field) { // error - this is bad. This means somebody changed variable name without changing channel enum UE_LOG(LogCollisionProfile, Error, TEXT("Variable (%s) isn't found for Channel (%s). \nPlease make sure you name matches between ECollisionChannel and FCollisionResponseContainer."), *DisplayName.ToString(), *EnumName); } #if WITH_EDITOR // clear displayname since we're setting it in below Enum->RemoveMetaData(*KeyName, EnumIndex); if (Enum->HasMetaData(*HiddenMeta, EnumIndex) == false) { Enum->SetMetaData(*HiddenMeta, NULL, EnumIndex); } #endif } else { // fix up FCollisionQueryFlag AllObjects flag, if trace type=1 ECollisionChannel CollisionChannel = (ECollisionChannel)EnumIndex; // for any engine level collision profile, we hard coded here // meta data doesn't work in cooked build, so we'll have to manually handle them if ((CollisionChannel == ECC_Visibility) || (CollisionChannel == ECC_Camera)) { // remove from object query flags FCollisionQueryFlag::Get().RemoveFromAllObjectsQueryFlag(CollisionChannel); TraceTypeMapping.Add(CollisionChannel); } else if ( CollisionChannel < ECC_OverlapAll_Deprecated ) { ObjectTypeMapping.Add(CollisionChannel); } } ChannelDisplayNames[EnumIndex] = DisplayName; } // Now Load Channel setups, and set display names if customized // also initialize DefaultResposneContainer with default response for each channel FCollisionResponseContainer::DefaultResponseContainer.SetAllChannels(ECR_Block); for (auto Iter=DefaultChannelResponses.CreateConstIterator(); Iter; ++Iter) { const FCustomChannelSetup& CustomChannel = *Iter; int32 EnumIndex = CustomChannel.Channel; // make sure it is the range of channels we allow to change if ( IS_VALID_COLLISIONCHANNEL(EnumIndex) ) { if ( CustomChannel.Name != NAME_None ) { // before you set meta data, you'll have to save this value to modify // ECollisionResponseContainer variables meta data FString VariableName = ChannelDisplayNames[EnumIndex].ToString(); FString DisplayValue = CustomChannel.Name.ToString(); // also has to set this for internal use ChannelDisplayNames[EnumIndex] = FName(*DisplayValue); #if WITH_EDITOR // set displayvalue for this enum entry Enum->SetMetaData(*KeyName, *DisplayValue, EnumIndex); // also need to remove "Hidden" Enum->RemoveMetaData(*HiddenMeta, EnumIndex); #endif // now add MetaData type for trace type if it does if (CustomChannel.bTraceType) { #if WITH_EDITOR // add to enum Enum->SetMetaData(*TraceType, *TraceValue, EnumIndex); #endif // remove from all object queries FCollisionQueryFlag::Get().RemoveFromAllObjectsQueryFlag(CustomChannel.Channel); TraceTypeMapping.Add(CustomChannel.Channel); } // if it has display value else { #if WITH_EDITOR // add to enum Enum->RemoveMetaData(*TraceType, EnumIndex); #endif ObjectTypeMapping.Add(CustomChannel.Channel); if (CustomChannel.bStaticObject) { // add to static object FCollisionQueryFlag::Get().AddToAllStaticObjectsQueryFlag(CustomChannel.Channel); } } #if WITH_EDITOR // now enum is fixed, so find member variable for the field UField* Field = FindField<UField>(Struct, FName(*VariableName)); // I verified up in the class, this can't happen check (Field); Field->SetMetaData(*KeyName, *DisplayValue); #endif } else { // missing name UE_LOG(LogCollisionProfile, Warning, TEXT("Name can't be empty for Channel (%d) "), EnumIndex ); } // allow it to set default response FCollisionResponseContainer::DefaultResponseContainer.SetResponse((ECollisionChannel) EnumIndex, CustomChannel.DefaultResponse); } else { // you can't customize those channels UE_LOG(LogCollisionProfile, Warning, TEXT("Default Setup doesn't allow for predefined engine channels (%d) "), EnumIndex); } } #if WITH_EDITOR // now propagate all changes to the channels to EObjectTypeQuery and ETraceTypeQuery for blueprint accessibility // this code is to show in editor more friendly, so it doesn't have to be set if it's not for editor int32 ObjectTypeEnumIndex = 0; int32 TraceTypeEnumIndex = 0; // first go through fill up ObjectType Enum for ( int32 EnumIndex=0; EnumIndex<NumEnum; ++EnumIndex ) { // if not hidden const FString& Hidden = Enum->GetMetaData(*HiddenMeta, EnumIndex); if ( Hidden.IsEmpty() ) { const FString& DisplayName = Enum->GetMetaData(*KeyName, EnumIndex); if ( !DisplayName.IsEmpty() ) { // find out trace type or object type if (Enum->GetMetaData(*TraceType, EnumIndex) == TraceValue) { TraceTypeEnum->RemoveMetaData(*HiddenMeta, TraceTypeEnumIndex); TraceTypeEnum->SetMetaData(*KeyName, *DisplayName, TraceTypeEnumIndex); ++TraceTypeEnumIndex; } else { ObjectTypeEnum->RemoveMetaData(*HiddenMeta, ObjectTypeEnumIndex); ObjectTypeEnum->SetMetaData(*KeyName, *DisplayName, ObjectTypeEnumIndex); ++ObjectTypeEnumIndex; } } } } // make sure TraceTypeEnumIndex matches TraceTypeMapping check (TraceTypeMapping.Num() == TraceTypeEnumIndex); check (ObjectTypeMapping.Num() == ObjectTypeEnumIndex); #endif // collision redirector has to be loaded before profile CollisionChannelRedirectsMap.Empty(); for(auto Iter = CollisionChannelRedirects.CreateConstIterator(); Iter; ++Iter) { FName OldName = Iter->OldName; FName NewName = Iter->NewName; // at least we need to have OldName if(OldName!= NAME_None && NewName != NAME_None) { // add to pair CollisionChannelRedirectsMap.Add(OldName, NewName); } else { // print error UE_LOG(LogCollisionProfile, Warning, TEXT("CollisionChannel Redirects : Name Can't be none (%s: %s)"), *OldName.ToString(), *NewName.ToString()); } } // 2. Second loads all set up back to ResponseToChannels // this does a lot of iteration, but this only happens once loaded, so it's better to be convenient than efficient // fill up Profiles data FillProfileData(Profiles, Enum, KeyName, EditProfiles); // 3. It loads redirect data - now time to load profile redirect ProfileRedirectsMap.Empty(); // handle profile redirect here for(auto Iter = ProfileRedirects.CreateConstIterator(); Iter; ++Iter) { FName OldName = Iter->OldName; FName NewName = Iter->NewName; // at least we need to have OldName if(OldName!= NAME_None && NewName != NAME_None) { FCollisionResponseTemplate Template; // make sure the template exists if(FindProfileData(Profiles, NewName, Template)) { // add to pair ProfileRedirectsMap.Add(OldName, NewName); } else { // print error UE_LOG(LogCollisionProfile, Warning, TEXT("ProfileRedirect (%s : %s) - New Name (\'%s\') isn't found "), *OldName.ToString(), *NewName.ToString(), *NewName.ToString()); } } } #if WITH_EDITOR if (bForceInit) { // go through objects, and see if we can reinitialize profile for(TObjectIterator<UPrimitiveComponent> PrimIt; PrimIt; ++PrimIt) { PrimIt->UpdateCollisionProfile(); } } #endif }
void UGatherTextFromMetaDataCommandlet::GatherTextFromUObject(UField* const Field, const FGatherParameters& Arguments) { // Gather for object. { if( !Field->HasMetaData( TEXT("DisplayName") ) ) { Field->SetMetaData( TEXT("DisplayName"), *FName::NameToDisplayString( Field->GetName(), Field->IsA( UBoolProperty::StaticClass() ) ) ); } for(int32 i = 0; i < Arguments.InputKeys.Num(); ++i) { FFormatNamedArguments PatternArguments; PatternArguments.Add( TEXT("FieldPath"), FText::FromString( Field->GetFullGroupName(false) ) ); if( Field->HasMetaData( *Arguments.InputKeys[i] ) ) { const FString& MetaDataValue = Field->GetMetaData(*Arguments.InputKeys[i]); if( !MetaDataValue.IsEmpty() ) { PatternArguments.Add( TEXT("MetaDataValue"), FText::FromString(MetaDataValue) ); const FString Namespace = Arguments.OutputNamespaces[i]; FLocItem LocItem(MetaDataValue); FManifestContext Context; Context.Key = FText::Format(Arguments.OutputKeys[i], PatternArguments).ToString(); Context.SourceLocation = FString::Printf(TEXT("From metadata for key %s of member %s in %s"), *Arguments.InputKeys[i], *Field->GetName(), *Field->GetFullGroupName(true)); GatherManifestHelper->AddSourceText(Namespace, LocItem, Context); } } } } // For enums, also gather for enum values. { UEnum* Enum = Cast<UEnum>(Field); if(Enum) { const int32 ValueCount = Enum->NumEnums(); for(int32 i = 0; i < ValueCount; ++i) { if( !Enum->HasMetaData(TEXT("DisplayName"), i) ) { Enum->SetMetaData(TEXT("DisplayName"), *FName::NameToDisplayString(Enum->GetEnumName(i), false), i); } for(int32 j = 0; j < Arguments.InputKeys.Num(); ++j) { FFormatNamedArguments PatternArguments; PatternArguments.Add( TEXT("FieldPath"), FText::FromString( Enum->GetFullGroupName(false) + TEXT(".") + Enum->GetEnumName(i) ) ); if( Enum->HasMetaData(*Arguments.InputKeys[j], i) ) { const FString& MetaDataValue = Enum->GetMetaData(*Arguments.InputKeys[j], i); if( !MetaDataValue.IsEmpty() ) { PatternArguments.Add( TEXT("MetaDataValue"), FText::FromString(MetaDataValue) ); const FString Namespace = Arguments.OutputNamespaces[j]; FLocItem LocItem(MetaDataValue); FManifestContext Context; Context.Key = FText::Format(Arguments.OutputKeys[j], PatternArguments).ToString(); Context.SourceLocation = FString::Printf(TEXT("From metadata for key %s of enum value %s of enum %s in %s"), *Arguments.InputKeys[j], *Enum->GetEnumName(i), *Enum->GetName(), *Enum->GetFullGroupName(true)); GatherManifestHelper->AddSourceText(Namespace, LocItem, Context); } } } } } } }
void FRCPassPostProcessVisualizeShadingModels::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessVisualizeShadingModels); const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); const FSceneView& View = Context.View; const FViewInfo& ViewInfo = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); FIntRect SrcRect = View.ViewRect; FIntRect DestRect = View.ViewRect; FIntPoint SrcSize = InputDesc->Extent; const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the view family's render target/viewport. SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef()); Context.SetViewportAndCallRHI(DestRect); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap()); TShaderMapRef<FPostProcessVisualizeShadingModelsPS> PixelShader(Context.GetShaderMap()); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetPS(Context, ((FViewInfo&)View).ShadingModelMaskInView); // Draw a quad mapping scene color to the view's render target DrawRectangle( Context.RHICmdList, DestRect.Min.X, DestRect.Min.Y, DestRect.Width(), DestRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestRect.Size(), SrcSize, *VertexShader, EDRF_UseTriangleOptimization); FRenderTargetTemp TempRenderTarget(View, (const FTexture2DRHIRef&)DestRenderTarget.TargetableTexture); FCanvas Canvas(&TempRenderTarget, NULL, 0, 0, 0, Context.GetFeatureLevel()); float X = 30; float Y = 28; const float YStep = 14; const float ColumnWidth = 250; FString Line; Canvas.DrawShadowedString( X, Y += YStep, TEXT("Visualize ShadingModels (mostly to track down bugs)"), GetStatsFont(), FLinearColor(1, 1, 1)); Y = 160 - YStep - 4; uint32 Value = ((FViewInfo&)View).ShadingModelMaskInView; Line = FString::Printf(TEXT("View.ShadingModelMaskInView = 0x%x"), Value); Canvas.DrawShadowedString( X, Y, *Line, GetStatsFont(), FLinearColor(0.5f, 0.5f, 0.5f)); Y += YStep; UEnum* Enum = FindObject<UEnum>(NULL, TEXT("Engine.EMaterialShadingModel")); check(Enum); Y += 5; for(uint32 i = 0; i < MSM_MAX; ++i) { FString Name = Enum->GetEnumName(i); Line = FString::Printf(TEXT("%d. %s"), i, *Name); bool bThere = (Value & (1 << i)) != 0; Canvas.DrawShadowedString(X + 30, Y, *Line, GetStatsFont(), bThere ? FLinearColor(1, 1, 1) : FLinearColor(0, 0, 0) ); Y += 20; } Line = FString::Printf(TEXT("(On CPU, based on what gets rendered)")); Canvas.DrawShadowedString( X, Y, *Line, GetStatsFont(), FLinearColor(0.5f, 0.5f, 0.5f)); Y += YStep; Canvas.Flush_RenderThread(Context.RHICmdList); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); // AdjustGBufferRefCount(1) call is done in constructor FSceneRenderTargets::Get(Context.RHICmdList).AdjustGBufferRefCount(Context.RHICmdList, -1); }
virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override { // Cast the node and get all the input pins UK2Node_Select* SelectNode = Cast<UK2Node_Select>(Node); TArray<UEdGraphPin*> OptionPins; SelectNode->GetOptionPins(OptionPins); UEdGraphPin* IndexPin = SelectNode->GetIndexPin(); // Get the kismet term for the (Condition or Index) that will determine which option to use UEdGraphPin* PinToTry = FEdGraphUtilities::GetNetFromPin(IndexPin); FBPTerminal** ConditionTerm = Context.NetMap.Find(PinToTry); // Get the kismet term for the return value UEdGraphPin* ReturnPin = SelectNode->GetReturnValuePin(); FBPTerminal** ReturnTerm = Context.NetMap.Find(ReturnPin); // Don't proceed if there is no return value or there is no selection if (ConditionTerm != NULL && ReturnTerm != NULL) { FName ConditionalFunctionName = ""; UClass* ConditionalFunctionClass = NULL; SelectNode->GetConditionalFunction(ConditionalFunctionName, &ConditionalFunctionClass); UFunction* ConditionFunction = FindField<UFunction>(ConditionalFunctionClass, ConditionalFunctionName); // Find the local boolean for use in the equality call function below (BoolTerm = result of EqualEqual_IntInt or NotEqual_BoolBool) FBPTerminal* BoolTerm = BoolTermMap.FindRef(SelectNode); // We need to keep a pointer to the previous IfNot statement so it can be linked to the next conditional statement FBlueprintCompiledStatement* PrevIfNotStatement = NULL; // Keep an array of all the unconditional goto statements so we can clean up their jumps after the noop statement is created TArray<FBlueprintCompiledStatement*> GotoStatementList; // Loop through all the options for (int32 OptionIdx = 0; OptionIdx < OptionPins.Num(); OptionIdx++) { // Create a CallFunction statement with the condition function from the Select class FBlueprintCompiledStatement& Statement = Context.AppendStatementForNode(Node); Statement.Type = KCST_CallFunction; Statement.FunctionToCall = ConditionFunction; Statement.FunctionContext = NULL; Statement.bIsParentContext = false; // BoolTerm will be the return value of the condition statement Statement.LHS = BoolTerm; // The condition passed into the Select node Statement.RHS.Add(*ConditionTerm); // Create a local int for use in the equality call function below (LiteralTerm = the right hand side of the EqualEqual_IntInt or NotEqual_BoolBool statement) FBPTerminal* LiteralTerm = Context.CreateLocalTerminal(ETerminalSpecification::TS_Literal); LiteralTerm->bIsLiteral = true; LiteralTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_Int; LiteralTerm->Name = FString::Printf(TEXT("%d"), OptionIdx); Statement.RHS.Add(LiteralTerm); // If there is a previous IfNot statement, hook this one to that one for jumping if (PrevIfNotStatement) { Statement.bIsJumpTarget = true; PrevIfNotStatement->TargetLabel = &Statement; } // Create a GotoIfNot statement using the BoolTerm from above as the condition FBlueprintCompiledStatement* IfNotStatement = &Context.AppendStatementForNode(Node); IfNotStatement->Type = KCST_GotoIfNot; IfNotStatement->LHS = BoolTerm; // Create an assignment statement FBlueprintCompiledStatement& AssignStatement = Context.AppendStatementForNode(Node); AssignStatement.Type = KCST_Assignment; AssignStatement.LHS = *ReturnTerm; // Get the kismet term from the option pin UEdGraphPin* OptionPinToTry = FEdGraphUtilities::GetNetFromPin(OptionPins[OptionIdx]); FBPTerminal** OptionTerm = Context.NetMap.Find(OptionPinToTry); if (!OptionTerm) { Context.MessageLog.Error(*LOCTEXT("Error_UnregisterOptionPin", "Unregister option pin @@").ToString(), OptionPins[OptionIdx]); return; } AssignStatement.RHS.Add(*OptionTerm); // Create an unconditional goto to exit the node FBlueprintCompiledStatement& GotoStatement = Context.AppendStatementForNode(Node); GotoStatement.Type = KCST_UnconditionalGoto; GotoStatementList.Add(&GotoStatement); // If this is the last IfNot statement, hook the jump to an error message if (OptionIdx == OptionPins.Num() - 1) { // Create a CallFunction statement for doing a print string of our error message FBlueprintCompiledStatement& PrintStatement = Context.AppendStatementForNode(Node); PrintStatement.Type = KCST_CallFunction; PrintStatement.bIsJumpTarget = true; FName PrintStringFunctionName = ""; UClass* PrintStringFunctionClass = NULL; SelectNode->GetPrintStringFunction(PrintStringFunctionName, &PrintStringFunctionClass); UFunction* PrintFunction = FindField<UFunction>(PrintStringFunctionClass, PrintStringFunctionName); PrintStatement.FunctionToCall = PrintFunction; PrintStatement.FunctionContext = NULL; PrintStatement.bIsParentContext = false; // Create a local int for use in the equality call function below (LiteralTerm = the right hand side of the EqualEqual_IntInt or NotEqual_BoolBool statement) FBPTerminal* LiteralStringTerm = Context.CreateLocalTerminal(ETerminalSpecification::TS_Literal); LiteralStringTerm->bIsLiteral = true; LiteralStringTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_String; FString SelectionNodeType(TEXT("NONE")); if (IndexPin) { UEnum* EnumObject = Cast<UEnum>(IndexPin->PinType.PinSubCategoryObject.Get()); if (EnumObject != NULL) { SelectionNodeType = EnumObject->GetName(); } else { // Not an enum, so just use the basic type SelectionNodeType = IndexPin->PinType.PinCategory; } } const UEdGraph* OwningGraph = Context.MessageLog.FindSourceObjectTypeChecked<UEdGraph>( SelectNode->GetGraph() ); LiteralStringTerm->Name = FString::Printf(*LOCTEXT("SelectNodeIndexWarning", "Graph %s: Selection Node of type %s failed! Out of bounds indexing of the options. There are only %d options available.").ToString(), (OwningGraph) ? *OwningGraph->GetFullName() : TEXT("NONE"), *SelectionNodeType, OptionPins.Num()); PrintStatement.RHS.Add(LiteralStringTerm); // Hook the IfNot statement's jump target to this statement IfNotStatement->TargetLabel = &PrintStatement; } PrevIfNotStatement = IfNotStatement; } // Create a noop to jump to so the unconditional goto statements can exit the node after successful assignment FBlueprintCompiledStatement& NopStatement = Context.AppendStatementForNode(Node); NopStatement.Type = KCST_Nop; NopStatement.bIsJumpTarget = true; // Loop through the unconditional goto statements and fix their jump targets for (auto It = GotoStatementList.CreateConstIterator(); It; It++) { (*It)->TargetLabel = &NopStatement; } } }