void FSpriteDetailsCustomization::BuildCollisionSection(IDetailCategoryBuilder& CollisionCategory, IDetailLayoutBuilder& DetailLayout) { TSharedPtr<IPropertyHandle> SpriteCollisionDomainProperty = DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UPaperSprite, SpriteCollisionDomain)); 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> ParticipatesInPhysics2D = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FSpriteDetailsCustomization::PhysicsModeMatches, SpriteCollisionDomainProperty, ESpriteCollisionMode::Use2DPhysics)); CollisionCategory.AddProperty(SpriteCollisionDomainProperty); // Add a warning bar about 2D collision being experimental FText WarningFor2D = LOCTEXT("Experimental2DPhysicsWarning", "2D collision support is *experimental*"); FText TooltipFor2D = LOCTEXT("Experimental2DPhysicsWarningTooltip", "2D collision support is *experimental* and should not be relied on yet.\n\nRigid body collision detection and response works, but there are only precompiled libraries for Windows currently.\n\nRaycasts are partially supported (and need to be enabled in project settings), but queries, sweeps, or overlap tests are not implemented yet."); GenerateWarningRow(CollisionCategory, /*bExperimental=*/ true, WarningFor2D, TooltipFor2D, TEXT("Shared/Editors/SpriteEditor"), TEXT("CollisionDomain2DWarning")) .Visibility(ParticipatesInPhysics2D); // Add a warning bar if 2D collision queries aren't enabled TAttribute<EVisibility> WarnAbout2DQueriesBeingDisabledVisibility = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FSpriteDetailsCustomization::Get2DPhysicsNotEnabledWarningVisibility, SpriteCollisionDomainProperty)); FText QueryWarningFor2D = LOCTEXT("Query2DPhysicsWarning", "2D collision queries are disabled"); FText QueryTooltipFor2D = LOCTEXT("Query2DPhysicsWarningTooltip", "You can enable 2D queries in Project Settings..Physics by setting bEnable2DPhysics to true, otherwise only collision detection and response will work.\n\nNote: Only raycasts are partially supported; other queries, sweeps, and overlap tests are not implemented yet."); GenerateWarningRow(CollisionCategory, /*bExperimental=*/ false, QueryWarningFor2D, QueryTooltipFor2D, TEXT("Shared/Editors/SpriteEditor"), TEXT("Disabled2DCollisionQueriesWarning")) .Visibility(WarnAbout2DQueriesBeingDisabledVisibility); // 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"))); PreventDicedRestriction->AddValue(TEXT("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(FSpritePolygonCollection, 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 geometry when not None CollisionCategory.AddProperty( DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UPaperSprite, CollisionGeometry)) ) .Visibility(ParticipatesInPhysics); // Show the collision thickness only in 3D mode CollisionCategory.AddProperty( DetailLayout.GetProperty(GET_MEMBER_NAME_CHECKED(UPaperSprite, CollisionThickness)) ) .Visibility(ParticipatesInPhysics3D); // 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(FSpritePolygonCollection, Polygons)); CollisionCategory.AddProperty(DetailLayout.GetProperty(*CollisionGeometryPolygonsPropertyPath), EPropertyLocation::Advanced) .DisplayName(LOCTEXT("CollisionPolygons", "Collision Polygons")) .Visibility(ParticipatesInPhysics); // 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.AddExternalProperty(BodySetupList, GET_MEMBER_NAME_CHECKED(UBodySetup, DefaultInstance)); if (DefaultInstanceRow != nullptr) { DefaultInstanceRow->Visibility(ParticipatesInPhysics); } } }
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> ParticipatesInPhysics2D = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FSpriteDetailsCustomization::PhysicsModeMatches, SpriteCollisionDomainProperty, ESpriteCollisionMode::Use2DPhysics)); 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 a warning bar about 2D collision being experimental FText WarningFor2D = LOCTEXT("Experimental2DPhysicsWarning", "2D collision support is *experimental*"); FText TooltipFor2D = LOCTEXT("Experimental2DPhysicsWarningTooltip", "2D collision support is *experimental* and should not be relied on yet.\n\nRigid body collision detection and response works, but there are only precompiled libraries for Windows currently.\n\nRaycasts are partially supported (and need to be enabled in project settings), but queries, sweeps, or overlap tests are not implemented yet."); GenerateWarningRow(CollisionCategory, /*bExperimental=*/ true, WarningFor2D, TooltipFor2D, TEXT("Shared/Editors/SpriteEditor"), TEXT("CollisionDomain2DWarning")) .Visibility(ParticipatesInPhysics2D); // Add a warning bar if 2D collision queries aren't enabled TAttribute<EVisibility> WarnAbout2DQueriesBeingDisabledVisibility = TAttribute<EVisibility>::Create(TAttribute<EVisibility>::FGetter::CreateSP(this, &FSpriteDetailsCustomization::Get2DPhysicsNotEnabledWarningVisibility, SpriteCollisionDomainProperty)); FText QueryWarningFor2D = LOCTEXT("Query2DPhysicsWarning", "2D collision queries are disabled"); FText QueryTooltipFor2D = LOCTEXT("Query2DPhysicsWarningTooltip", "You can enable 2D queries in Project Settings..Physics by setting bEnable2DPhysics to true, otherwise only collision detection and response will work.\n\nNote: Only raycasts are partially supported; other queries, sweeps, and overlap tests are not implemented yet."); GenerateWarningRow(CollisionCategory, /*bExperimental=*/ false, QueryWarningFor2D, QueryTooltipFor2D, TEXT("Shared/Editors/SpriteEditor"), TEXT("Disabled2DCollisionQueriesWarning")) .Visibility(WarnAbout2DQueriesBeingDisabledVisibility); // 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->GetEnumNameStringByValue((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.AddExternalProperty(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); }