void SDetailsViewBase::SetColorPropertyFromColorPicker(FLinearColor NewColor) { const TSharedPtr< FPropertyNode > PinnedColorPropertyNode = ColorPropertyNode.Pin(); if (ensure(PinnedColorPropertyNode.IsValid())) { UProperty* Property = PinnedColorPropertyNode->GetProperty(); check(Property); FObjectPropertyNode* ObjectNode = PinnedColorPropertyNode->FindObjectItemParent(); if (ObjectNode && ObjectNode->GetNumObjects()) { FScopedTransaction Transaction(NSLOCTEXT("UnrealEd", "SetColorProperty", "Set Color Property")); PinnedColorPropertyNode->NotifyPreChange(Property, GetNotifyHook()); FPropertyChangedEvent ChangeEvent(Property, EPropertyChangeType::ValueSet); PinnedColorPropertyNode->NotifyPostChange(ChangeEvent, GetNotifyHook()); } } }
void FDetailLayoutBuilderImpl::GetObjectsBeingCustomized( TArray< TWeakObjectPtr<UObject> >& OutObjects ) const { OutObjects.Empty(); // The class to find properties in defaults to the class currently being customized FName ClassName = CurrentCustomizationClass ? CurrentCustomizationClass->GetFName() : NAME_None; if( ClassName != NAME_None && CurrentCustomizationVariableName != NAME_None ) { // If this fails there are no properties associated with the class name provided FClassInstanceToPropertyMap* ClassInstanceToPropertyMapPtr = PropertyMap.Find( ClassName ); if( ClassInstanceToPropertyMapPtr ) { FClassInstanceToPropertyMap& ClassInstanceToPropertyMap = *ClassInstanceToPropertyMapPtr; FPropertyNodeMap* PropertyNodeMapPtr = ClassInstanceToPropertyMap.Find( CurrentCustomizationVariableName ); if( PropertyNodeMapPtr ) { FPropertyNodeMap& PropertyNodeMap = *PropertyNodeMapPtr; FObjectPropertyNode* ParentObjectProperty = PropertyNodeMap.ParentProperty ? PropertyNodeMap.ParentProperty->AsObjectNode() : NULL; if (ParentObjectProperty) { for (int32 ObjectIndex = 0; ObjectIndex < ParentObjectProperty->GetNumObjects(); ++ObjectIndex) { OutObjects.Add(ParentObjectProperty->GetUObject(ObjectIndex)); } } } } } else { OutObjects = DetailsView.GetSelectedObjects(); } }
void SDetailsView::SetObjectArrayPrivate(const TArray< TWeakObjectPtr< UObject > >& InObjects) { double StartTime = FPlatformTime::Seconds(); PreSetObject(InObjects.Num()); // Selected actors for building SelectedActorInfo TArray<AActor*> SelectedRawActors; bViewingClassDefaultObject = InObjects.Num() > 0 ? true : false; bool bOwnedByLockedLevel = false; for( int32 ObjectIndex = 0 ; ObjectIndex < InObjects.Num(); ++ObjectIndex ) { TWeakObjectPtr< UObject > Object = InObjects[ObjectIndex]; if( Object.IsValid() ) { bViewingClassDefaultObject &= Object->HasAnyFlags( RF_ClassDefaultObject ); if(DetailsViewArgs.bAllowMultipleTopLevelObjects) { check(RootPropertyNodes.Num() == InObjects.Num()); RootPropertyNodes[ObjectIndex]->AsObjectNode()->AddObject( Object.Get() ); } else { RootPropertyNodes[0]->AsObjectNode()->AddObject( Object.Get() ); } SelectedObjects.Add( Object ); AActor* Actor = Cast<AActor>( Object.Get() ); if( Actor ) { SelectedActors.Add( Actor ); SelectedRawActors.Add( Actor ); } } } if( InObjects.Num() == 0 ) { // Unlock the view automatically if we are viewing nothing bIsLocked = false; } // Selection changed, refresh the detail area if ( DetailsViewArgs.NameAreaSettings != FDetailsViewArgs::ActorsUseNameArea && DetailsViewArgs.NameAreaSettings != FDetailsViewArgs::ComponentsAndActorsUseNameArea ) { NameArea->Refresh( SelectedObjects ); } else { NameArea->Refresh( SelectedActors, SelectedObjects, DetailsViewArgs.NameAreaSettings ); } // When selection changes rebuild information about the selection SelectedActorInfo = AssetSelectionUtils::BuildSelectedActorInfo( SelectedRawActors ); // @todo Slate Property Window //SetFlags(EPropertyWindowFlags::ReadOnly, bOwnedByLockedLevel); PostSetObject(); // Set the title of the window based on the objects we are viewing // Or call the delegate for handling when the title changed FString Title; if( GetNumObjects() == 0 ) { Title = NSLOCTEXT("PropertyView", "NothingSelectedTitle", "Nothing selected").ToString(); } else if( GetNumObjects() == 1 && RootPropertyNodes[0]->AsObjectNode()->GetNumObjects() > 0) { // if the object is the default metaobject for a UClass, use the UClass's name instead UObject* Object = RootPropertyNodes[0]->AsObjectNode()->GetUObject(0); FString ObjectName = Object->GetName(); if ( Object->GetClass()->GetDefaultObject() == Object ) { ObjectName = Object->GetClass()->GetName(); } else { // Is this an actor? If so, it might have a friendly name to display const AActor* Actor = Cast<const AActor >( Object ); if( Actor != nullptr) { // Use the friendly label for this actor ObjectName = Actor->GetActorLabel(); } } Title = ObjectName; } else if(DetailsViewArgs.bAllowMultipleTopLevelObjects) { Title = FString::Printf(*NSLOCTEXT("PropertyView", "MultipleToLevelObjectsSelected", "%i selected").ToString(), GetNumObjects()); } else { FObjectPropertyNode* RootPropertyNode = RootPropertyNodes[0]->AsObjectNode(); Title = FString::Printf( *NSLOCTEXT("PropertyView", "MultipleSelected", "%s (%i selected)").ToString(), *RootPropertyNode->GetObjectBaseClass()->GetName(), RootPropertyNode->GetNumObjects() ); } OnObjectArrayChanged.ExecuteIfBound(Title, InObjects); double ElapsedTime = FPlatformTime::Seconds() - StartTime; }
bool SDetailsView::ShouldSetNewObjects(const TArray< TWeakObjectPtr< UObject > >& InObjects) const { bool bShouldSetObjects = false; const bool bHadBSPBrushSelected = SelectedActorInfo.bHaveBSPBrush; if( bHadBSPBrushSelected == true ) { // If a BSP brush was selected we need to refresh because surface could have been selected and the object set not updated bShouldSetObjects = true; } else if( InObjects.Num() != GetNumObjects() ) { // If the object arrays differ in size then at least one object is different so we must reset bShouldSetObjects = true; } else if(InObjects.Num() == 0) { // User is likely resetting details panel bShouldSetObjects = true; } else { // Check to see if the objects passed in are different. If not we do not need to set anything TSet< TWeakObjectPtr< UObject > > NewObjects; NewObjects.Append(InObjects); if(DetailsViewArgs.bAllowMultipleTopLevelObjects) { // For multiple top level node support, if the single object in each node is not found in the new object set // then we need to refresh for(int32 RootNodeIndex = 0; RootNodeIndex < RootPropertyNodes.Num(); ++RootNodeIndex) { FObjectPropertyNode* RootPropertyNode = RootPropertyNodes[RootNodeIndex]->AsObjectNode(); if(RootPropertyNode && RootPropertyNode->GetNumObjects() > 0) { if(!NewObjects.Contains(RootPropertyNode->GetUObject(0))) { bShouldSetObjects = true; break; } } else { bShouldSetObjects = true; break; } } } else { ensure(RootPropertyNodes.Num() == 1); FObjectPropertyNode* RootPropertyNode = RootPropertyNodes[0]->AsObjectNode(); if( RootPropertyNode ) { for(TPropObjectIterator Itor(RootPropertyNode->ObjectIterator()); Itor; ++Itor) { TWeakObjectPtr<UObject> Object = *Itor; if(Object.IsValid() && !NewObjects.Contains(Object)) { // An existing object is not in the list of new objects to set bShouldSetObjects = true; break; } else if(!Object.IsValid()) { // An existing object is invalid bShouldSetObjects = true; break; } } } else { bShouldSetObjects = true; } } } if (!bShouldSetObjects && AssetSelectionUtils::IsAnySurfaceSelected(nullptr)) { bShouldSetObjects = true; } return bShouldSetObjects; }