void FSpriteDetailsCustomization::BuildCollisionSection(IDetailCategoryBuilder& CollisionCategory, IDetailLayoutBuilder& DetailLayout) { TSharedPtr<IPropertyHandle> SpriteCollisionDomainProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UPaperSprite, SpriteCollisionDomain)); CollisionCategory.HeaderContent ( SNew(SBox) .HAlign(HAlign_Right) [ SNew(SHorizontalBox) +SHorizontalBox::Slot() .Padding(FMargin(5.0f, 0.0f)) .AutoWidth() [ SNew(STextBlock) .Font(FEditorStyle::GetFontStyle("TinyText")) .Text(this, &FSpriteDetailsCustomization::GetCollisionHeaderContentText, SpriteCollisionDomainProperty) ] ] ); TAttribute<EVisibility> ParticipatesInPhysics = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP( this, &FSpriteDetailsCustomization::AnyPhysicsMode, SpriteCollisionDomainProperty)); TAttribute<EVisibility> ParticipatesInPhysics3D = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FSpriteDetailsCustomization::PhysicsModeMatches, SpriteCollisionDomainProperty, ESpriteCollisionMode::Use3DPhysics)); TAttribute<EVisibility> HideWhenInRenderingMode = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FSpriteDetailsCustomization::EditorModeIsNot, ESpriteEditorMode::EditRenderingGeomMode)); TAttribute<EVisibility> ShowWhenInRenderingMode = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FSpriteDetailsCustomization::EditorModeMatches, ESpriteEditorMode::EditRenderingGeomMode)); static const FText EditCollisionInCollisionMode = LOCTEXT("CollisionPropertiesHiddenInRenderingMode", "Switch to 'Edit Collsion' mode\nto edit Collision settings"); CollisionCategory.AddCustomRow(EditCollisionInCollisionMode) .Visibility(ShowWhenInRenderingMode) .WholeRowContent() .HAlign(HAlign_Center) [ SNew(STextBlock) .Font(DetailLayout.GetDetailFontItalic()) .Justification(ETextJustify::Center) .Text(EditCollisionInCollisionMode) ]; CollisionCategory.AddProperty(SpriteCollisionDomainProperty).Visibility(HideWhenInRenderingMode); // Add the collision geometry mode into the parent container (renamed) { // Restrict the diced value TSharedPtr<FPropertyRestriction> PreventDicedRestriction = MakeShareable(new FPropertyRestriction(LOCTEXT("CollisionGeometryDoesNotSupportDiced", "Collision geometry can not be set to Diced"))); const UEnum* const SpritePolygonModeEnum = FindObject<UEnum>(ANY_PACKAGE, TEXT("ESpritePolygonMode")); PreventDicedRestriction->AddDisabledValue(SpritePolygonModeEnum->GetNameStringByValue((uint8)ESpritePolygonMode::Diced)); // Find and add the property const FString CollisionGeometryTypePropertyPath = FString::Printf(TEXT("%s.%s"), GET_MEMBER_NAME_STRING_CHECKED(UPaperSprite, CollisionGeometry), GET_MEMBER_NAME_STRING_CHECKED(FSpriteGeometryCollection, GeometryType)); TSharedPtr<IPropertyHandle> CollisionGeometryTypeProperty = DetailLayout.GetProperty(*CollisionGeometryTypePropertyPath); CollisionGeometryTypeProperty->AddRestriction(PreventDicedRestriction.ToSharedRef()); CollisionCategory.AddProperty(CollisionGeometryTypeProperty) .DisplayName(LOCTEXT("CollisionGeometryType", "Collision Geometry Type")) .Visibility(ParticipatesInPhysics); } // Show the collision thickness only in 3D mode CollisionCategory.AddProperty( DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UPaperSprite, CollisionThickness)) ) .Visibility(ParticipatesInPhysics3D); // Show the default body instance (and only it) from the body setup (if it exists) DetailLayout.HideProperty("BodySetup"); IDetailPropertyRow& BodySetupDefaultInstance = CollisionCategory.AddProperty("BodySetup.DefaultInstance"); TArray<TWeakObjectPtr<UObject>> SpritesBeingEdited; DetailLayout.GetObjectsBeingCustomized(/*out*/ SpritesBeingEdited); TArray<UObject*> BodySetupList; for (auto WeakSpritePtr : SpritesBeingEdited) { if (UPaperSprite* Sprite = Cast<UPaperSprite>(WeakSpritePtr.Get())) { if (UBodySetup* BodySetup = Sprite->BodySetup) { BodySetupList.Add(BodySetup); } } } if (BodySetupList.Num() > 0) { IDetailPropertyRow* DefaultInstanceRow = CollisionCategory.AddExternalObjectProperty(BodySetupList, GET_MEMBER_NAME_CHECKED(UBodySetup, DefaultInstance)); if (DefaultInstanceRow != nullptr) { DefaultInstanceRow->Visibility(ParticipatesInPhysics); } } // Show the collision geometry when not None CollisionCategory.AddProperty(DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UPaperSprite, CollisionGeometry))) .Visibility(ParticipatesInPhysics); // Add the collision polygons into advanced (renamed) const FString CollisionGeometryPolygonsPropertyPath = FString::Printf(TEXT("%s.%s"), GET_MEMBER_NAME_STRING_CHECKED(UPaperSprite, CollisionGeometry), GET_MEMBER_NAME_STRING_CHECKED(FSpriteGeometryCollection, Shapes)); CollisionCategory.AddProperty(DetailLayout.GetProperty(*CollisionGeometryPolygonsPropertyPath), EPropertyLocation::Advanced) .DisplayName(LOCTEXT("CollisionShapes", "Collision Shapes")) .Visibility(ParticipatesInPhysics); }