예제 #1
0
bool FPropertyEditor::GetEditConditionPropertyAddress( UBoolProperty*& ConditionProperty, FPropertyNode& InPropertyNode, TArray<FPropertyConditionInfo>& ConditionPropertyAddresses )
{
	bool bResult = false;
	bool bNegate = false;
	UBoolProperty* EditConditionProperty = PropertyCustomizationHelpers::GetEditConditionProperty(InPropertyNode.GetProperty(), bNegate);
	if ( EditConditionProperty != NULL )
	{
		FPropertyNode* ParentNode = InPropertyNode.GetParentNode();
		check(ParentNode);

		UProperty* Property = InPropertyNode.GetProperty();
		if (Property)
		{
			bool bStaticArray = (Property->ArrayDim > 1) && (InPropertyNode.GetArrayIndex() != INDEX_NONE);
			if (bStaticArray)
			{
				//in the case of conditional static arrays, we have to go up one more level to get the proper parent struct.
				ParentNode = ParentNode->GetParentNode();
				check(ParentNode);
			}
		}

		auto ComplexParentNode = ParentNode->FindComplexParent();
		if (ComplexParentNode)
		{
			for (int32 Index = 0; Index < ComplexParentNode->GetInstancesNum(); ++Index)
			{
				TWeakObjectPtr<UObject> Object = ComplexParentNode->GetInstanceAsUObject(Index);

			if( Object.IsValid() )
			{
				UObject* Obj = Object.Get();

				// Get the address corresponding to the base of this property (i.e. if a struct property, set BaseOffset to the address of value for the whole struct)
				uint8* BaseOffset = ParentNode->GetValueAddress((uint8*)Obj);
				check(BaseOffset != NULL);

				FPropertyConditionInfo NewCondition;
				// now calculate the address of the property value being used as the condition and add it to the array.
				NewCondition.Address = EditConditionProperty->ContainerPtrToValuePtr<uint8>(BaseOffset);
				NewCondition.bNegateValue = bNegate;
				ConditionPropertyAddresses.Add(NewCondition);
				bResult = true;
			}
		}
	}
	}

	if ( bResult )
	{
		// set the output variable
		ConditionProperty = EditConditionProperty;
	}

	return bResult;
}
예제 #2
0
bool FObjectPropertyNode::GetReadAddressUncached(FPropertyNode& InNode,
											   bool InRequiresSingleSelection,
											   FReadAddressListData& OutAddresses,
											   bool bComparePropertyContents,
											   bool bObjectForceCompare,
											   bool bArrayPropertiesCanDifferInSize) const
{
	// Are any objects selected for property editing?
	if( !GetNumObjects())
	{
		return false;
	}

	UProperty* InItemProperty = InNode.GetProperty();
	// Is there a InItemProperty bound to the InItemProperty window?
	if( !InItemProperty )
	{
		return false;
	}

	// Requesting a single selection?
	if( InRequiresSingleSelection && GetNumObjects() > 1)
	{
		// Fail: we're editing properties for multiple objects.
		return false;
	}

	//assume all properties are the same unless proven otherwise
	bool bAllTheSame = true;

	//////////////////////////////////////////

	// If this item is the child of an array, return NULL if there is a different number
	// of items in the array in different objects, when multi-selecting.

	if( Cast<UArrayProperty>(InItemProperty->GetOuter()) )
	{
		FPropertyNode* ParentNode = InNode.GetParentNode();
		check(ParentNode);
		const UObject* TempObject = GetUObject(0);
		if( TempObject )
		{
			uint8* BaseAddr = ParentNode->GetValueBaseAddress( (uint8*)TempObject );
			if( BaseAddr )
			{
				const int32 Num = FScriptArrayHelper::Num(BaseAddr);
				for( int32 ObjIndex = 1 ; ObjIndex < GetNumObjects(); ObjIndex++ )
				{
					TempObject = GetUObject(ObjIndex);
					BaseAddr = ParentNode->GetValueBaseAddress( (uint8*)TempObject );

					if( BaseAddr && Num != FScriptArrayHelper::Num( BaseAddr ) )
					{
						bAllTheSame = false;
					}
				}
			}
		}
	}

	uint8* Base = GetUObject(0) ? InNode.GetValueBaseAddress( (uint8*)(GetUObject(0)) ) : NULL;
	if (Base)
	{
		// If the item is an array itself, return NULL if there are a different number of
		// items in the array in different objects, when multi-selecting.

		if( Cast<UArrayProperty>(InItemProperty) )
		{
			// This flag is an override for array properties which want to display e.g. the "Clear" and "Empty"
			// buttons, even though the array properties may differ in the number of elements.
			if ( !bArrayPropertiesCanDifferInSize )
			{
				const UObject* TempObject = GetUObject(0);
				int32 const Num = FScriptArrayHelper::Num(InNode.GetValueBaseAddress( (uint8*)TempObject));
				for( int32 ObjIndex = 1 ; ObjIndex < GetNumObjects() ; ObjIndex++ )
				{
					TempObject = GetUObject(ObjIndex);
					if( TempObject && Num != FScriptArrayHelper::Num(InNode.GetValueBaseAddress((uint8*)TempObject)) )
					{
						bAllTheSame = false;
					}
				}
			}
		}
		else
		{
			if ( bComparePropertyContents || !Cast<UObjectPropertyBase>(InItemProperty) || bObjectForceCompare )
			{
				// Make sure the value of this InItemProperty is the same in all selected objects.
				for( int32 ObjIndex = 1 ; ObjIndex < GetNumObjects() ; ObjIndex++ )
				{
					const UObject* TempObject = GetUObject(ObjIndex);
					if( !InItemProperty->Identical( Base, InNode.GetValueBaseAddress( (uint8*)TempObject ) ) )
					{
						bAllTheSame = false;
					}
				}
			}
			else
			{
				if ( Cast<UObjectPropertyBase>(InItemProperty) )
				{
					// We don't want to exactly compare component properties.  However, we
					// need to be sure that all references are either valid or invalid.

					// If BaseObj is NON-NULL, all other objects' properties should also be non-NULL.
					// If BaseObj is NULL, all other objects' properties should also be NULL.
					UObject* BaseObj = Cast<UObjectPropertyBase>(InItemProperty)->GetObjectPropertyValue(Base);

					for( int32 ObjIndex = 1 ; ObjIndex < GetNumObjects() ; ObjIndex++ )
					{
						const UObject* TempObject = GetUObject(ObjIndex);
						UObject* CurObj = Cast<UObjectPropertyBase>(InItemProperty)->GetObjectPropertyValue(InNode.GetValueBaseAddress( (uint8*)TempObject ));
						if (   ( !BaseObj && CurObj )			// BaseObj is NULL, but this InItemProperty is non-NULL!
							|| ( BaseObj && !CurObj ) )			// BaseObj is non-NULL, but this InItemProperty is NULL!
						{

							bAllTheSame = false;
						}
					}
				}
			}
		}
	}

	// Write addresses to the output.
	for ( int32 ObjIndex = 0 ; ObjIndex < GetNumObjects(); ++ObjIndex )
	{
		const UObject* TempObject = GetUObject(ObjIndex);
		if( TempObject )
		{
			OutAddresses.Add( TempObject, InNode.GetValueBaseAddress( (uint8*)(TempObject) ) );
		}
	}

	// Everything checked out and we have usable addresses.
	return bAllTheSame;
}