FLinearColor SPropertyEditorColor::OnGetColor() const
{
	const TSharedRef< FPropertyNode > PropertyNode = PropertyEditor->GetPropertyNode();
	const UProperty* Property = PropertyEditor->GetProperty();
	check(Property);

	FLinearColor Color;

	FReadAddressList ReadAddresses;
	PropertyNode->GetReadAddress( false, ReadAddresses, false );

	if( ReadAddresses.Num() ) 
	{
		const uint8* Addr = ReadAddresses.GetAddress(0);
		if( Addr )
		{
			if( Cast<const UStructProperty>(Property)->Struct->GetFName() == NAME_Color )
			{
				Color = (*(FColor*)Addr).ReinterpretAsLinear();
			}
			else
			{
				check( Cast<const UStructProperty>(Property)->Struct->GetFName() == NAME_LinearColor );
				Color = *(FLinearColor*)Addr;
			}
		}
	}

	return Color;
}
/**
* Creates the color picker window for this property view.
*
* @param Node				The slate property node to edit.
* @param bUseAlpha			Whether or not alpha is supported
*/
void SDetailsViewBase::CreateColorPickerWindow(const TSharedRef< FPropertyEditor >& PropertyEditor, bool bUseAlpha)
{
	const TSharedRef< FPropertyNode > PinnedColorPropertyNode = PropertyEditor->GetPropertyNode();
	ColorPropertyNode = PinnedColorPropertyNode;

	UProperty* Property = PinnedColorPropertyNode->GetProperty();
	check(Property);

	FReadAddressList ReadAddresses;
	PinnedColorPropertyNode->GetReadAddress(false, ReadAddresses, false);

	TArray<FLinearColor*> LinearColor;
	TArray<FColor*> DWORDColor;
	for (int32 ColorIndex = 0; ColorIndex < ReadAddresses.Num(); ++ColorIndex)
	{
		const uint8* Addr = ReadAddresses.GetAddress(ColorIndex);
		if (Addr)
		{
			if (Cast<UStructProperty>(Property)->Struct->GetFName() == NAME_Color)
			{
				DWORDColor.Add((FColor*)Addr);
			}
			else
			{
				check(Cast<UStructProperty>(Property)->Struct->GetFName() == NAME_LinearColor);
				LinearColor.Add((FLinearColor*)Addr);
			}
		}
	}

	bHasOpenColorPicker = true;

	FColorPickerArgs PickerArgs;
	PickerArgs.ParentWidget = AsShared();
	PickerArgs.bUseAlpha = bUseAlpha;
	PickerArgs.DisplayGamma = TAttribute<float>::Create(TAttribute<float>::FGetter::CreateUObject(GEngine, &UEngine::GetDisplayGamma));
	PickerArgs.ColorArray = &DWORDColor;
	PickerArgs.LinearColorArray = &LinearColor;
	PickerArgs.OnColorCommitted = FOnLinearColorValueChanged::CreateSP(this, &SDetailsViewBase::SetColorPropertyFromColorPicker);
	PickerArgs.OnColorPickerWindowClosed = FOnWindowClosed::CreateSP(this, &SDetailsViewBase::OnColorPickerWindowClosed);

	OpenColorPicker(PickerArgs);
}
void SSingleProperty::CreateColorPickerWindow( const TSharedRef< class FPropertyEditor >& PropertyEditor, bool bUseAlpha )
{
	if( HasValidProperty() )
	{
		auto Node = PropertyEditor->GetPropertyNode();
		check( &Node.Get() == ValueNode.Get() );
		UProperty* Property = Node->GetProperty();
		check(Property);

		FReadAddressList ReadAddresses;
		Node->GetReadAddress( false, ReadAddresses, false );

		TArray<FLinearColor*> LinearColor;
		TArray<FColor*> DWORDColor;
		if( ReadAddresses.Num() ) 
		{
			const uint8* Addr = ReadAddresses.GetAddress(0);
			if( Addr )
			{
				if( Cast<UStructProperty>(Property)->Struct->GetFName() == NAME_Color )
				{
					DWORDColor.Add((FColor*)Addr);
				}
				else
				{
					check( Cast<UStructProperty>(Property)->Struct->GetFName() == NAME_LinearColor );
					LinearColor.Add((FLinearColor*)Addr);
				}
			}
		}

		FColorPickerArgs PickerArgs;
		PickerArgs.ParentWidget = AsShared();
		PickerArgs.bUseAlpha = bUseAlpha;
		PickerArgs.DisplayGamma = TAttribute<float>::Create( TAttribute<float>::FGetter::CreateUObject(GEngine, &UEngine::GetDisplayGamma) );
		PickerArgs.ColorArray = &DWORDColor;
		PickerArgs.LinearColorArray = &LinearColor;
		PickerArgs.OnColorCommitted = FOnLinearColorValueChanged::CreateSP( this, &SSingleProperty::SetColorPropertyFromColorPicker);

		OpenColorPicker(PickerArgs);
	}
}
void SPropertyEditorColor::OnColorPickerCancelled( FLinearColor OriginalColor )
{
	const TSharedRef< FPropertyNode > PropertyNode = PropertyEditor->GetPropertyNode();

	UProperty* Property = PropertyNode->GetProperty();
	check(Property);

	FReadAddressList ReadAddresses;
	PropertyNode->GetReadAddress( false, ReadAddresses, false );

	if( ReadAddresses.Num() ) 
	{
		check( OriginalColors.Num() == ReadAddresses.Num() );
		PropertyNode->NotifyPreChange(Property, PropertyUtilities->GetNotifyHook());

		for( int32 AddrIndex = 0; AddrIndex < ReadAddresses.Num(); ++AddrIndex )
		{
			const uint8* Addr = ReadAddresses.GetAddress(AddrIndex);
			if( Addr )
			{
				if( Cast<UStructProperty>(Property)->Struct->GetFName() == NAME_Color )
				{
					*(FColor*)Addr = OriginalColors[AddrIndex].ToFColor(false);
				}
				else
				{
					check( Cast<UStructProperty>(Property)->Struct->GetFName() == NAME_LinearColor );
					*(FLinearColor*)Addr = OriginalColors[AddrIndex];
				}
			}
		}

		FPropertyChangedEvent ChangeEvent(Property, EPropertyChangeType::ValueSet);
		PropertyNode->NotifyPostChange( ChangeEvent, PropertyUtilities->GetNotifyHook() );
	}

	OriginalColors.Empty();
}
void SPropertyEditorColor::SetColor(FLinearColor NewColor)
{
	const TSharedRef< FPropertyNode > PropertyNode = PropertyEditor->GetPropertyNode();

	UProperty* Property = PropertyNode->GetProperty();
	check(Property);
	
	FReadAddressList ReadAddresses;
	PropertyNode->GetReadAddress( false, ReadAddresses, false );

	if( ReadAddresses.Num() ) 
	{
		GEditor->BeginTransaction( NSLOCTEXT("UnrealEd", "SetColorProperty", "Set Color Property") );

		PropertyNode->NotifyPreChange(Property, PropertyUtilities->GetNotifyHook());
		for( int32 AddrIndex = 0; AddrIndex <  ReadAddresses.Num(); ++AddrIndex )
		{
			const uint8* Addr = ReadAddresses.GetAddress(AddrIndex);
			if( Addr )
			{
				if( Cast<UStructProperty>(Property)->Struct->GetFName() == NAME_Color )
				{
					*(FColor*)Addr = NewColor.ToFColor(false);
				}
				else
				{
					check( Cast<UStructProperty>(Property)->Struct->GetFName() == NAME_LinearColor );
					*(FLinearColor*)Addr = NewColor;
				}
			}
		}

		FPropertyChangedEvent ChangeEvent(Property, EPropertyChangeType::ValueSet);
		PropertyNode->NotifyPostChange( ChangeEvent, PropertyUtilities->GetNotifyHook() );

		GEditor->EndTransaction();		
	}
}
void SPropertyEditorColor::CreateColorPickerWindow(const TSharedRef< class FPropertyEditor >& InPropertyEditor, bool bUseAlpha, bool bOnlyRefreshOnOk)
{
	const TSharedRef< FPropertyNode > PropertyNode = InPropertyEditor->GetPropertyNode();

	UProperty* Property = PropertyNode->GetProperty();
	check(Property);

	FReadAddressList ReadAddresses;
	PropertyNode->GetReadAddress( false, ReadAddresses, false );

	FLinearColor InitialColor = FLinearColor(ForceInit);
	if( ReadAddresses.Num() )
	{
		OriginalColors.Empty( ReadAddresses.Num() );
		OriginalColors.AddUninitialized( ReadAddresses.Num() );

		// Store off the original colors in the case that the user cancels the color picker. We'll revert to the original colors in that case
		for( int32 AddrIndex = 0; AddrIndex <  ReadAddresses.Num(); ++AddrIndex )
		{
		
			const uint8* Addr = ReadAddresses.GetAddress(AddrIndex);
			if( Addr )
			{
				if( Cast<UStructProperty>(Property)->Struct->GetFName() == NAME_Color )
				{
					OriginalColors[AddrIndex] = ((FColor*)Addr)->ReinterpretAsLinear();
				}
				else
				{
					check( Cast<UStructProperty>(Property)->Struct->GetFName() == NAME_LinearColor );
					OriginalColors[AddrIndex] = *(FLinearColor*)Addr;
				}
			}
		}

		// Only one color can be the initial color.  Just use the first color property
		InitialColor = OriginalColors[0];

		FColorPickerArgs PickerArgs;
		PickerArgs.bOnlyRefreshOnMouseUp = true;
		PickerArgs.ParentWidget = AsShared();
		PickerArgs.bUseAlpha = bUseAlpha;
		PickerArgs.bOnlyRefreshOnOk = bOnlyRefreshOnOk;
		PickerArgs.DisplayGamma = TAttribute<float>::Create( TAttribute<float>::FGetter::CreateUObject(GEngine, &UEngine::GetDisplayGamma) );
		PickerArgs.OnColorCommitted = FOnLinearColorValueChanged::CreateSP( this, &SPropertyEditorColor::SetColor);
		PickerArgs.OnColorPickerCancelled = FOnColorPickerCancelled::CreateSP( this, &SPropertyEditorColor::OnColorPickerCancelled );
		PickerArgs.InitialColorOverride = InitialColor;

		OpenColorPicker(PickerArgs);
	}
	

}
Example #7
0
void FPropertyEditor::SyncToObjectsInNode( const TWeakPtr< FPropertyNode >& WeakPropertyNode )
{
#if WITH_EDITOR

	if ( !GUnrealEd )
	{
		return;
	}

	TSharedPtr< FPropertyNode > PropertyNode = WeakPropertyNode.Pin();
	check(PropertyNode.IsValid());
	UProperty* NodeProperty = PropertyNode->GetProperty();

	UObjectPropertyBase* ObjectProperty = Cast<UObjectPropertyBase>( NodeProperty );
	UInterfaceProperty* IntProp = Cast<UInterfaceProperty>( NodeProperty );
	{
		UClass* PropertyClass = UObject::StaticClass();
		if( ObjectProperty )
		{
			PropertyClass = ObjectProperty->PropertyClass;
		}
		else if( IntProp )
		{
			PropertyClass = IntProp->InterfaceClass;
		}

		// Get a list of addresses for objects handled by the property window.
		FReadAddressList ReadAddresses;
		PropertyNode->GetReadAddress( !!PropertyNode->HasNodeFlags(EPropertyNodeFlags::SingleSelectOnly), ReadAddresses, false );

		// GetReadAddresses will only provide a list of addresses if the property was properly formed, objects were selected, and only one object was selected if the node has the SingleSelectOnly flag.
		// If a list of addresses is provided, GetReadAddress may still return false but we can operate on the property addresses even if they have different values.
		check( ReadAddresses.Num() > 0 );

		// Create a list of object names.
		TArray<FString> ObjectNames;
		ObjectNames.Empty( ReadAddresses.Num() );

		// Copy each object's object property name off into the name list.
		for ( int32 AddrIndex = 0 ; AddrIndex < ReadAddresses.Num() ; ++AddrIndex )
		{
			new( ObjectNames ) FString();
			uint8* Address = ReadAddresses.GetAddress(AddrIndex);
			if( Address )
			{
				NodeProperty->ExportText_Direct(ObjectNames[AddrIndex], Address, Address, NULL, PPF_Localized );
			}
		}


		// Create a list of objects to sync the generic browser to.
		TArray<UObject*> Objects;
		for ( int32 ObjectIndex = 0 ; ObjectIndex < ObjectNames.Num() ; ++ObjectIndex )
		{

			UObject* Package = ANY_PACKAGE;
			if( ObjectNames[ObjectIndex].Contains( TEXT(".")) )
			{
				// Formatted text string, use the exact path instead of any package
				Package = NULL;
			}

			UObject* Object = StaticFindObject( PropertyClass, Package, *ObjectNames[ObjectIndex] );
			if( !Object && Package != ANY_PACKAGE )
			{
				Object = StaticLoadObject(PropertyClass, Package, *ObjectNames[ObjectIndex]);
			}
			if ( Object )
			{
				// If the selected object is a blueprint generated class, then browsing to it in the content browser should instead point to the blueprint
				// Note: This code needs to change once classes are the top level asset in the content browser and/or blueprint classes are displayed in the content browser
				if (UClass* ObjectAsClass = Cast<UClass>(Object))
				{
					if (ObjectAsClass->ClassGeneratedBy != NULL)
					{
						Object = ObjectAsClass->ClassGeneratedBy;
					}
				}

				Objects.Add( Object );
			}
		}

		// If a single actor is selected, sync to its location in the level editor viewport instead of the content browser.
		if( Objects.Num() == 1 && Objects[0]->IsA(AActor::StaticClass()) )
		{
			TArray<AActor*> Actors;
			Actors.Add(Cast<AActor>(Objects[0]));

			GEditor->SelectNone(/*bNoteSelectionChange=*/false, /*bDeselectBSPSurfs=*/true);
			GEditor->SelectActor(Actors[0], /*InSelected=*/true, /*bNotify=*/true, /*bSelectEvenIfHidden=*/true);

			// Jump to the location of the actor
			GEditor->MoveViewportCamerasToActor( Actors, /*bActiveViewportOnly=*/false );
		}
		else if ( Objects.Num() > 0 )
		{
			GEditor->SyncBrowserToObjects(Objects);
		}
	}

#endif
}