bool UObjectPropertyBase::NetSerializeItem( FArchive& Ar, UPackageMap* Map, void* Data, TArray<uint8> * MetaData ) const { UObject* Object = GetObjectPropertyValue(Data); bool Result = Map->SerializeObject( Ar, PropertyClass, Object ); SetObjectPropertyValue(Data, Object); return Result; }
const TCHAR* UClassProperty::ImportText_Internal( const TCHAR* Buffer, void* Data, int32 PortFlags, UObject* Parent, FOutputDevice* ErrorText ) const { const TCHAR* Result = UObjectProperty::ImportText_Internal( Buffer, Data, PortFlags, Parent, ErrorText ); if( Result ) { CheckValidObject(Data); if (UClass* AssignedPropertyClass = dynamic_cast<UClass*>(GetObjectPropertyValue(Data))) { #if USE_CIRCULAR_DEPENDENCY_LOAD_DEFERRING FLinkerLoad* PropertyLinker = GetLinker(); bool const bIsDeferringValueLoad = ((PropertyLinker == nullptr) || (PropertyLinker->LoadFlags & LOAD_DeferDependencyLoads)) && Cast<ULinkerPlaceholderClass>(MetaClass); #if USE_DEFERRED_DEPENDENCY_CHECK_VERIFICATION_TESTS check(bIsDeferringValueLoad || !Cast<ULinkerPlaceholderClass>(MetaClass)); #endif // USE_DEFERRED_DEPENDENCY_CHECK_VERIFICATION_TESTS #else // USE_CIRCULAR_DEPENDENCY_LOAD_DEFERRING bool const bIsDeferringValueLoad = false; #endif // USE_CIRCULAR_DEPENDENCY_LOAD_DEFERRING // Validate metaclass. if ((!AssignedPropertyClass->IsChildOf(MetaClass)) && !bIsDeferringValueLoad) { // the object we imported doesn't implement our interface class ErrorText->Logf(TEXT("Invalid object '%s' specified for property '%s'"), *AssignedPropertyClass->GetFullName(), *GetName()); SetObjectPropertyValue(Data, NULL); Result = NULL; } } } return Result; }
void UObjectProperty::SerializeItem( FArchive& Ar, void* Value, int32 MaxReadBytes, void const* Defaults ) const { UObject* ObjectValue = GetObjectPropertyValue(Value); Ar << ObjectValue; UObject* CurrentValue = GetObjectPropertyValue(Value); if (ObjectValue != CurrentValue) { #if USE_CIRCULAR_DEPENDENCY_LOAD_DEFERRING if (ULinkerPlaceholderExportObject* PlaceholderVal = Cast<ULinkerPlaceholderExportObject>(ObjectValue)) { PlaceholderVal->AddReferencingProperty(this); } // NOTE: we don't remove this from CurrentValue if it is a // ULinkerPlaceholderExportObject; this is because this property // could be an array inner, and another member of that array (also // referenced through this property)... if this becomes a problem, // then we could inc/decrement a ref count per referencing property // // @TODO: if this becomes problematic (because ObjectValue doesn't match // this property's PropertyClass), then we could spawn another // placeholder object (of PropertyClass's type), or use null; but // we'd have to modify ULinkerPlaceholderExportObject::ReplaceReferencingObjectValues() // to accommodate this (as it depends on finding itself as the set value) #endif // USE_CIRCULAR_DEPENDENCY_LOAD_DEFERRING SetObjectPropertyValue(Value, ObjectValue); CheckValidObject(Value); } }
const TCHAR* UObjectPropertyBase::ImportText_Internal( const TCHAR* InBuffer, void* Data, int32 PortFlags, UObject* Parent, FOutputDevice* ErrorText ) const { const TCHAR* Buffer = InBuffer; UObject* Result = NULL; bool bOk = ParseObjectPropertyValue(this, Parent, PropertyClass, PortFlags, Buffer, Result); SetObjectPropertyValue(Data, Result); return Buffer; }
void UClassProperty::CheckValidObject(void* Value) const { #if WITH_EDITOR // Ugly hack to replace Blueprint references with Class references. struct FReplaceBlueprintWithClassHelper { bool bShouldReplace; UClass* BlueprintClass; UClassProperty* BPGeneratedClassProp; FReplaceBlueprintWithClassHelper() : bShouldReplace(false), BlueprintClass(NULL), BPGeneratedClassProp(NULL) { GConfig->GetBool(TEXT("EditoronlyBP"), TEXT("bReplaceBlueprintWithClass"), bShouldReplace, GEditorIni); if (bShouldReplace) { BlueprintClass = FindObject<UClass>(NULL, TEXT("/Script/Engine.Blueprint")); ensure(BlueprintClass); BPGeneratedClassProp = BlueprintClass ? FindField<UClassProperty>(BlueprintClass, TEXT("GeneratedClass")) : NULL; ensure(BPGeneratedClassProp); } } bool CanReplace() const { return bShouldReplace && BlueprintClass && BPGeneratedClassProp; } }; static FReplaceBlueprintWithClassHelper Helper; const UObject* Object = GetObjectPropertyValue(Value); Super::CheckValidObject(Value); const UObject* CurrentObject = GetObjectPropertyValue(Value); if (Helper.CanReplace() && !CurrentObject && Object && Object->IsA(Helper.BlueprintClass) && (UObject::StaticClass() == MetaClass)) { UObject* RecoveredObject = Helper.BPGeneratedClassProp->GetPropertyValue_InContainer(Object); SetObjectPropertyValue(Value, RecoveredObject); UE_LOG(LogProperty, Log, TEXT("Blueprint '%s' is replaced with class '%s' in property '%s'"), *Object->GetFullName(), *RecoveredObject->GetFullName(), *GetFullName()); } #else // WITH_EDITOR Super::CheckValidObject(Value); #endif // WITH_EDITOR }
void UObjectPropertyBase::InstanceSubobjects(void* Data, void const* DefaultData, UObject* Owner, FObjectInstancingGraph* InstanceGraph ) { for ( int32 ArrayIndex = 0; ArrayIndex < ArrayDim; ArrayIndex++ ) { UObject* CurrentValue = GetObjectPropertyValue((uint8*)Data + ArrayIndex * ElementSize); if ( CurrentValue ) { UObject *SubobjectTemplate = DefaultData ? GetObjectPropertyValue((uint8*)DefaultData + ArrayIndex * ElementSize): NULL; UObject* NewValue = InstanceGraph->InstancePropertyValue(SubobjectTemplate, CurrentValue, Owner, HasAnyPropertyFlags(CPF_Transient), HasAnyPropertyFlags(CPF_InstancedReference)); SetObjectPropertyValue((uint8*)Data + ArrayIndex * ElementSize, NewValue); } } }
const TCHAR* UClassProperty::ImportText_Internal( const TCHAR* Buffer, void* Data, int32 PortFlags, UObject* Parent, FOutputDevice* ErrorText ) const { const TCHAR* Result = UObjectProperty::ImportText_Internal( Buffer, Data, PortFlags, Parent, ErrorText ); if( Result ) { // Validate metaclass. UClass* C = (UClass*)GetObjectPropertyValue(Data); if (C && (!dynamic_cast<UClass*>(C) || !C->IsChildOf(MetaClass))) { // the object we imported doesn't implement our interface class ErrorText->Logf(TEXT("Invalid object '%s' specified for property '%s'"), *C->GetFullName(), *GetName()); SetObjectPropertyValue(Data, NULL); Result = NULL; } } return Result; }
void UObjectPropertyBase::CheckValidObject(void* Value) const { UObject *Object = GetObjectPropertyValue(Value); if (Object) { // // here we want to make sure the the object value still matches the // object type expected by the property... UClass* ObjectClass = Object->GetClass(); // we could be in the middle of replacing references to the // PropertyClass itself (in the middle of an FArchiveReplaceObjectRef // pass)... if this is the case, then we might have already replaced // the object's class, but not the PropertyClass yet (or vise-versa)... // so we use this to ensure, in that situation, that we don't clear the // object value (if CLASS_NewerVersionExists is set, then we are likely // in the middle of an FArchiveReplaceObjectRef pass) bool bIsReplacingClassRefs = PropertyClass && PropertyClass->HasAnyClassFlags(CLASS_NewerVersionExists) != ObjectClass->HasAnyClassFlags(CLASS_NewerVersionExists); #if USE_CIRCULAR_DEPENDENCY_LOAD_DEFERRING FLinkerLoad* PropertyLinker = GetLinker(); bool const bIsDeferringValueLoad = ((PropertyLinker == nullptr) || (PropertyLinker->LoadFlags & LOAD_DeferDependencyLoads)) && (Object->IsA<ULinkerPlaceholderExportObject>() || Object->IsA<ULinkerPlaceholderClass>()); #if USE_DEFERRED_DEPENDENCY_CHECK_VERIFICATION_TESTS check( bIsDeferringValueLoad || (!Object->IsA<ULinkerPlaceholderExportObject>() && !Object->IsA<ULinkerPlaceholderClass>()) ); #endif // USE_DEFERRED_DEPENDENCY_CHECK_VERIFICATION_TESTS #else // USE_CIRCULAR_DEPENDENCY_LOAD_DEFERRING bool const bIsDeferringValueLoad = false; #endif // USE_CIRCULAR_DEPENDENCY_LOAD_DEFERRING if ((PropertyClass != nullptr) && !ObjectClass->IsChildOf(PropertyClass) && !bIsReplacingClassRefs && !bIsDeferringValueLoad) { UE_LOG(LogProperty, Warning, TEXT("Serialized %s for a property of %s. Reference will be NULLed.\n Property = %s\n Item = %s"), *Object->GetClass()->GetFullName(), *PropertyClass->GetFullName(), *GetFullName(), *Object->GetFullName() ); SetObjectPropertyValue(Value, NULL); } } }