FReply FKismetVariableDragDropAction::DroppedOnCategory(FText Category) { UE_LOG(LogTemp, Log, TEXT("Dropped %s on Category %s"), *VariableName.ToString(), *Category.ToString()); UBlueprint* BP = NULL; if(VariableSource.Get()->IsA(UFunction::StaticClass())) { BP = UBlueprint::GetBlueprintFromClass(Cast<UClass>(VariableSource.Get()->GetOuter())); } else { BP = UBlueprint::GetBlueprintFromClass(Cast<UClass>(VariableSource.Get())); } if(BP != NULL) { // Check this is actually a different category FText CurrentCategory = FBlueprintEditorUtils::GetBlueprintVariableCategory(BP, VariableName, GetLocalVariableScope()); if(!Category.EqualTo(CurrentCategory)) { FBlueprintEditorUtils::SetBlueprintVariableCategory(BP, VariableName, GetLocalVariableScope(), Category, false); } } return FReply::Handled(); }
FReply FKismetVariableDragDropAction::DroppedOnAction(TSharedRef<FEdGraphSchemaAction> Action) { if(Action->GetTypeId() == FEdGraphSchemaAction_K2Var::StaticGetTypeId()) { FEdGraphSchemaAction_K2Var* VarAction = (FEdGraphSchemaAction_K2Var*)&Action.Get(); // Only let you drag and drop if variables are from same BP class, and not onto itself UBlueprint* BP = UBlueprint::GetBlueprintFromClass(Cast<UClass>(VariableSource.Get())); FName TargetVarName = VarAction->GetVariableName(); if( (BP != NULL) && (VariableName != TargetVarName) && (VariableSource == VarAction->GetVariableClass()) ) { bool bMoved = FBlueprintEditorUtils::MoveVariableBeforeVariable(BP, VariableName, TargetVarName, true); // If we moved successfully if(bMoved) { // Change category of var to match the one we dragged on to as well FText MovedVarCategory = FBlueprintEditorUtils::GetBlueprintVariableCategory(BP, VariableName, GetLocalVariableScope()); FText TargetVarCategory = FBlueprintEditorUtils::GetBlueprintVariableCategory(BP, TargetVarName, GetLocalVariableScope()); if(!MovedVarCategory.EqualTo(TargetVarCategory)) { FBlueprintEditorUtils::SetBlueprintVariableCategory(BP, VariableName, GetLocalVariableScope(), TargetVarCategory, true); } // Update Blueprint after changes so they reflect in My Blueprint tab. FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(BP); } } return FReply::Handled(); } return FReply::Unhandled(); }
void UMovieSceneNameableTrack::SetDisplayName(const FText& NewDisplayName) { if (NewDisplayName.EqualTo(DisplayName)) { return; } SetFlags(RF_Transactional); Modify(); DisplayName = NewDisplayName; }
FText FCinematicOptionsCustomization::GetCurrentMatineeName() const { FText SettingName; Matinee->GetValueAsDisplayText(SettingName); for (TObjectIterator<AMatineeActor> It; It; ++It) { AMatineeActor* MatineeActor = *It; if (SettingName.EqualTo(FText::FromString(MatineeActor->GetName()))) { return SettingName; } } Matinee->SetValueFromFormattedString(FString("None")); return FText::FromString("None"); }
bool UKismetTextLibrary::EqualEqual_TextText(const FText& A, const FText& B) { return A.EqualTo( B ); }
bool UVMReflection::ExecuteUnitTest() { bool bSuccess = true; TMap<FString, bool> TestResults; /** * Reflection functionality unit tests */ // Reflecting casting error reporting { UVMTestClassA* TestObjA = NewObject<UVMTestClassA>(); UVMTestClassB* TestObjB = NewObject<UVMTestClassB>(); TestObjA->AObjectRef = TestObjB; bool bOriginalError = false; (void)(UObject*)(FVMReflection(TestObjA)->*"AObjectRef", &bOriginalError); bool bError = false; (FString)(FVMReflection(TestObjA)->*"AObjectRef", &bError); TestResults.Add(TEXT("Reflection casting error"), (!bOriginalError && bError)); } /** * Casting operator unit tests */ // UObject reflection and casting { UObject* TargetResult = AActor::StaticClass(); UVMTestClassA* TestObjA = NewObject<UVMTestClassA>(); UVMTestClassB* TestObjB = NewObject<UVMTestClassB>(); TestObjA->AObjectRef = TestObjB; TestObjB->BObjectRef = TargetResult; bool bError = false; UObject* Result = (UObject*)(FVMReflection(TestObjA)->*"AObjectRef"->*"BObjectRef", &bError); TestResults.Add(TEXT("UObject Reflection"), (!bError && Result != NULL && Result == TargetResult)); } // UObject property writing { UObject* TargetResult = AActor::StaticClass(); UVMTestClassA* TestObjA = NewObject<UVMTestClassA>(); UVMTestClassB* TestObjB = NewObject<UVMTestClassB>(); TestObjA->AObjectRef = TestObjB; bool bError = false; UObject** Result = (UObject**)(FVMReflection(TestObjA)->*"AObjectRef", &bError); if (!bError && Result != NULL) { *Result = TargetResult; } TestResults.Add(TEXT("UObject Writing"), (!bError && TestObjA->AObjectRef == TargetResult)); } // @todo #JohnB_VMRefl: Add a test for UObject** casting, i.e. writable object property references, now that it is supported // Byte property reading { uint8 TargetResult = 128; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->ByteProp = TargetResult; } bool bError = false; uint8 Result = (uint8)(FVMReflection(TestObj)->*"ByteProp", &bError); TestResults.Add(TEXT("Byte Reading"), (!bError && Result == TargetResult)); } // Byte property writing { uint8 TargetResult = 64; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->ByteProp = 128; bool bError = false; uint8* Result = (uint8*)(FVMReflection(TestObj)->*"ByteProp", &bError); if (!bError && Result != NULL) { *Result = TargetResult; } TestResults.Add(TEXT("Byte Writing"), (!bError && TestObj->ByteProp == TargetResult)); } // uint16 property reading { uint16 TargetResult = 512; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->UInt16Prop = TargetResult; } bool bError = false; uint16 Result = (uint16)(FVMReflection(TestObj)->*"UInt16Prop", &bError); TestResults.Add(TEXT("uint16 Reading"), (!bError && Result == TargetResult)); } // uint16 property writing { uint16 TargetResult = 1024; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->UInt16Prop = 128; bool bError = false; uint16* Result = (uint16*)(FVMReflection(TestObj)->*"UInt16Prop", &bError); if (!bError && Result != NULL) { *Result = TargetResult; } TestResults.Add(TEXT("uint16 Writing"), (!bError && TestObj->UInt16Prop == TargetResult)); } // uint16 Byte property upcast reading { uint16 TargetResult = 128; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->ByteProp = (uint8)TargetResult; } bool bError = false; uint16 Result = (uint16)(FVMReflection(TestObj)->*"ByteProp", &bError); TestResults.Add(TEXT("uint16 Byte upcast Reading"), (!bError && Result == TargetResult)); } // uint32 property reading { uint32 TargetResult = 131070; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->UInt32Prop = TargetResult; } bool bError = false; uint32 Result = (uint32)(FVMReflection(TestObj)->*"UInt32Prop", &bError); TestResults.Add(TEXT("uint32 Reading"), (!bError && Result == TargetResult)); } // uint32 property writing { uint32 TargetResult = 262140; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->UInt32Prop = 128; bool bError = false; uint32* Result = (uint32*)(FVMReflection(TestObj)->*"UInt32Prop", &bError); if (!bError && Result != NULL) { *Result = TargetResult; } TestResults.Add(TEXT("uint32 Writing"), (!bError && TestObj->UInt32Prop == TargetResult)); } // uint32 Byte property upcast reading { uint32 TargetResult = 128; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->ByteProp = (uint8)TargetResult; } bool bError = false; uint32 Result = (uint32)(FVMReflection(TestObj)->*"ByteProp", &bError); TestResults.Add(TEXT("uint32 Byte upcast Reading"), (!bError && Result == TargetResult)); } // uint32 uint16 property upcast reading { uint32 TargetResult = 1024; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->UInt16Prop = (uint16)TargetResult; } bool bError = false; uint32 Result = (uint32)(FVMReflection(TestObj)->*"UInt16Prop", &bError); TestResults.Add(TEXT("uint32 uint16 upcast Reading"), (!bError && Result == TargetResult)); } // uint64 property reading { uint64 TargetResult = 8589934591ull; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->UInt64Prop = TargetResult; } bool bError = false; uint64 Result = (uint64)(FVMReflection(TestObj)->*"UInt64Prop", &bError); TestResults.Add(TEXT("uint64 Reading"), (!bError && Result == TargetResult)); } // uint64 property writing { uint64 TargetResult = 17179869182ull; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->UInt64Prop = 128; bool bError = false; uint64* Result = (uint64*)(FVMReflection(TestObj)->*"UInt64Prop", &bError); if (!bError && Result != NULL) { *Result = TargetResult; } TestResults.Add(TEXT("uint64 Writing"), (!bError && TestObj->UInt64Prop == TargetResult)); } // uint64 Byte property upcast reading { uint64 TargetResult = 128; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->ByteProp = (uint8)TargetResult; } bool bError = false; uint64 Result = (uint64)(FVMReflection(TestObj)->*"ByteProp", &bError); TestResults.Add(TEXT("uint64 Byte upcast Reading"), (!bError && Result == TargetResult)); } // uint64 uint16 property upcast reading { uint64 TargetResult = 1024; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->UInt16Prop = (uint16)TargetResult; } bool bError = false; uint64 Result = (uint64)(FVMReflection(TestObj)->*"UInt16Prop", &bError); TestResults.Add(TEXT("uint64 uint16 upcast Reading"), (!bError && Result == TargetResult)); } // uint64 uint32 property upcast reading { uint64 TargetResult = 2147483647; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->UInt32Prop = (uint32)TargetResult; } bool bError = false; uint64 Result = (uint64)(FVMReflection(TestObj)->*"UInt32Prop", &bError); TestResults.Add(TEXT("uint64 uint32 upcast Reading"), (!bError && Result == TargetResult)); } // int8 property reading { int8 TargetResult = -128; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->Int8Prop = TargetResult; } bool bError = false; int8 Result = (int8)(FVMReflection(TestObj)->*"Int8Prop", &bError); TestResults.Add(TEXT("int8 Reading"), (!bError && Result == TargetResult)); } // int8 property writing { int8 TargetResult = -64; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->Int8Prop = 127; bool bError = false; int8* Result = (int8*)(FVMReflection(TestObj)->*"Int8Prop", &bError); if (!bError && Result != NULL) { *Result = TargetResult; } TestResults.Add(TEXT("int8 Writing"), (!bError && TestObj->Int8Prop == TargetResult)); } // int16 property reading { int16 TargetResult = -512; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->Int16Prop = TargetResult; } bool bError = false; int16 Result = (int16)(FVMReflection(TestObj)->*"Int16Prop", &bError); TestResults.Add(TEXT("int16 Reading"), (!bError && Result == TargetResult)); } // int16 property writing { int16 TargetResult = -1024; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->Int16Prop = 128; bool bError = false; int16* Result = (int16*)(FVMReflection(TestObj)->*"Int16Prop", &bError); if (!bError && Result != NULL) { *Result = TargetResult; } TestResults.Add(TEXT("int16 Writing"), (!bError && TestObj->Int16Prop == TargetResult)); } // int16 int8 property upcast reading { int16 TargetResult = -64; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->Int8Prop = (int8)TargetResult; } bool bError = false; int16 Result = (int16)(FVMReflection(TestObj)->*"Int8Prop", &bError); TestResults.Add(TEXT("int16 int8 upcast Reading"), (!bError && Result == TargetResult)); } // int32 property reading { int32 TargetResult = -131070; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->Int32Prop = TargetResult; } bool bError = false; int32 Result = (int32)(FVMReflection(TestObj)->*"Int32Prop", &bError); TestResults.Add(TEXT("int32 Reading"), (!bError && Result == TargetResult)); } // int32 property writing { int32 TargetResult = -131070; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->Int32Prop = 128; bool bError = false; int32* Result = (int32*)(FVMReflection(TestObj)->*"Int32Prop", &bError); if (!bError && Result != NULL) { *Result = TargetResult; } TestResults.Add(TEXT("int32 Writing"), (!bError && TestObj->Int32Prop == TargetResult)); } // int32 int8 property upcast reading { int32 TargetResult = -64; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->Int8Prop = (int8)TargetResult; } bool bError = false; int32 Result = (int32)(FVMReflection(TestObj)->*"Int8Prop", &bError); TestResults.Add(TEXT("int32 int8 upcast Reading"), (!bError && Result == TargetResult)); } // int32 int16 property upcast reading { int32 TargetResult = -1024; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->Int16Prop = (int16)TargetResult; } bool bError = false; int32 Result = (int32)(FVMReflection(TestObj)->*"Int16Prop", &bError); TestResults.Add(TEXT("int32 int16 upcast Reading"), (!bError && Result == TargetResult)); } // int64 property reading { int64 TargetResult = -8589934591ll; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->Int64Prop = TargetResult; } bool bError = false; int64 Result = (int64)(FVMReflection(TestObj)->*"Int64Prop", &bError); TestResults.Add(TEXT("int64 Reading"), (!bError && Result == TargetResult)); } // int64 property writing { int64 TargetResult = -8589934591ll; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->Int64Prop = 128; bool bError = false; int64* Result = (int64*)(FVMReflection(TestObj)->*"Int64Prop", &bError); if (!bError && Result != NULL) { *Result = TargetResult; } TestResults.Add(TEXT("int64 Writing"), (!bError && TestObj->Int64Prop == TargetResult)); } // int64 int8 property upcast reading { int64 TargetResult = -64; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->Int8Prop = (int8)TargetResult; } bool bError = false; int64 Result = (int64)(FVMReflection(TestObj)->*"Int8Prop", &bError); TestResults.Add(TEXT("int64 int8 upcast Reading"), (!bError && Result == TargetResult)); } // int64 int16 property upcast reading { int64 TargetResult = -1024; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->Int16Prop = (int16)TargetResult; } bool bError = false; int64 Result = (int64)(FVMReflection(TestObj)->*"Int16Prop", &bError); TestResults.Add(TEXT("int64 int16 upcast Reading"), (!bError && Result == TargetResult)); } // int64 int32 property upcast reading { int64 TargetResult = -1073741823; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->Int32Prop = (int32)TargetResult; } bool bError = false; int64 Result = (int64)(FVMReflection(TestObj)->*"Int32Prop", &bError); TestResults.Add(TEXT("int64 int32 upcast Reading"), (!bError && Result == TargetResult)); } // Float property reading { float TargetResult = 12.8f; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->FloatProp = TargetResult; } bool bError = false; float Result = (float)(FVMReflection(TestObj)->*"FloatProp", &bError); TestResults.Add(TEXT("Float Reading"), (!bError && Result == TargetResult)); } // Float property writing { float TargetResult = 6.4f; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->FloatProp = 12.8f; bool bError = false; float* Result = (float*)(FVMReflection(TestObj)->*"FloatProp", &bError); if (!bError && Result != NULL) { *Result = TargetResult; } TestResults.Add(TEXT("Float Writing"), (!bError && TestObj->FloatProp == TargetResult)); } // Double property reading { double TargetResult = 12.8; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DoubleProp = TargetResult; } bool bError = false; double Result = (double)(FVMReflection(TestObj)->*"DoubleProp", &bError); TestResults.Add(TEXT("Double Reading"), (!bError && Result == TargetResult)); } // Double property writing { double TargetResult = 6.4; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->DoubleProp = 12.8; bool bError = false; double* Result = (double*)(FVMReflection(TestObj)->*"DoubleProp", &bError); if (!bError && Result != NULL) { *Result = TargetResult; } TestResults.Add(TEXT("Double Writing"), (!bError && TestObj->DoubleProp == TargetResult)); } // Double Float property upcast reading { double TargetResult = (double)12.8f; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->FloatProp = (float)TargetResult; } bool bError = false; double Result = (double)(FVMReflection(TestObj)->*"FloatProp", &bError); TestResults.Add(TEXT("Double Float upcast Reading"), (!bError && Result == TargetResult)); } // Bool property reading { bool TargetResults[5] = {false, true, false, false, true}; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->bBoolPropA = TargetResults[0]; TestObj->bBoolPropB = TargetResults[1]; TestObj->bBoolPropC = TargetResults[2]; TestObj->bBoolPropD = TargetResults[3]; TestObj->bBoolPropE = TargetResults[4]; } bool bError = false; bool Results[5]; Results[0] = (bool)(FVMReflection(TestObj)->*"bBoolPropA", &bError); Results[1] = !(bError || !((bool)(FVMReflection(TestObj)->*"bBoolPropB", &bError))); Results[2] = !(bError || !((bool)(FVMReflection(TestObj)->*"bBoolPropC", &bError))); Results[3] = !(bError || !((bool)(FVMReflection(TestObj)->*"bBoolPropD", &bError))); Results[4] = !(bError || !((bool)(FVMReflection(TestObj)->*"bBoolPropE", &bError))); TestResults.Add(TEXT("Bool reading"), (!bError && Results[0] == TargetResults[0] && Results[1] == TargetResults[1] && Results[2] == TargetResults[2] && Results[3] == TargetResults[3] && Results[4] == TargetResults[4])); } // Name property reading { FName TargetResult = NAME_BeaconNetDriver; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->NameProp = TargetResult; } bool bError = false; FName Result = (FName)(FVMReflection(TestObj)->*"NameProp", &bError); TestResults.Add(TEXT("Name Reading"), (!bError && Result == TargetResult)); } // Name property writing { FName TargetResult = NAME_Camera; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->NameProp = NAME_Cylinder; bool bError = false; FName* Result = (FName*)(FVMReflection(TestObj)->*"NameProp", &bError); if (!bError && Result != NULL) { *Result = TargetResult; } TestResults.Add(TEXT("Name Writing"), (!bError && TestObj->NameProp == TargetResult)); } // FString property reading { FString TargetResult = TEXT("TargetResult"); UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->StringProp = TargetResult; } bool bError = false; FString Result = (FString)(FVMReflection(TestObj)->*"StringProp", &bError); TestResults.Add(TEXT("FString Reading"), (!bError && Result == TargetResult)); } // FString property writing { FString TargetResult = TEXT("Expected"); UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->StringProp = TEXT("NotExpected"); bool bError = false; FString* Result = (FString*)(FVMReflection(TestObj)->*"StringProp", &bError); if (!bError && Result != NULL) { *Result = TargetResult; } TestResults.Add(TEXT("FString Writing"), (!bError && TestObj->StringProp == TargetResult)); } // FText property reading { FText TargetResult = FText::FromString(TEXT("TargetResult")); UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->TextProp = TargetResult; } bool bError = false; FText Result = (FText)(FVMReflection(TestObj)->*"TextProp", &bError); TestResults.Add(TEXT("FText Reading"), (!bError && Result.EqualTo(TargetResult))); } // FText property writing { FText TargetResult = FText::FromString(TEXT("Expected")); UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->TextProp = FText::FromString(TEXT("NotExpected")); bool bError = false; FText* Result = (FText*)(FVMReflection(TestObj)->*"TextProp", &bError); if (!bError && Result != NULL) { *Result = TargetResult; } TestResults.Add(TEXT("FText Writing"), (!bError && TestObj->TextProp.EqualTo(TargetResult))); } /** * Array unit tests */ // Bad static array access (no element selected) { UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); bool bError = false; (void)(uint8)((FVMReflection(TestObj)->*"BytePropArray")["uint8"], &bError); TestResults.Add(TEXT("Bad static array access (no element)"), bError); } // Bad static array access (no type verification specified) { UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); bool bError = false; (void)(uint8)(FVMReflection(TestObj)->*"BytePropArray", &bError); TestResults.Add(TEXT("Bad static array access (no type verification)"), bError); } // Static array reading { uint8 TargetResults[4] = {128, 64, 32, 16}; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->BytePropArray[0] = TargetResults[0]; TestObj->BytePropArray[1] = TargetResults[1]; TestObj->BytePropArray[2] = TargetResults[2]; TestObj->BytePropArray[3] = TargetResults[3]; } bool bError[4] = {false, false, false, false}; uint8 Results[4]; Results[0] = (uint8)((FVMReflection(TestObj)->*"BytePropArray")["uint8"][0], &bError[0]); Results[1] = (uint8)((FVMReflection(TestObj)->*"BytePropArray")["uint8"][1], &bError[1]); Results[2] = (uint8)((FVMReflection(TestObj)->*"BytePropArray")["uint8"][2], &bError[2]); Results[3] = (uint8)((FVMReflection(TestObj)->*"BytePropArray")["uint8"][3], &bError[3]); TestResults.Add(TEXT("Static Array Reading"), (!bError[0] && Results[0] == TargetResults[0]) && (!bError[1] && Results[1] == TargetResults[1]) && (!bError[2] && Results[2] == TargetResults[2]) && (!bError[3] && Results[3] == TargetResults[3])); } // Static array writing { uint8 TargetResults[4] = {31, 15, 24, 47}; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->BytePropArray[0] = 128; TestObj->BytePropArray[1] = 128; TestObj->BytePropArray[2] = 128; TestObj->BytePropArray[3] = 128; bool bError[4] = {false, false, false, false}; uint8* Results[4]; Results[0] = (uint8*)((FVMReflection(TestObj)->*"BytePropArray")["uint8"][0], &bError[0]); Results[1] = (uint8*)((FVMReflection(TestObj)->*"BytePropArray")["uint8"][1], &bError[1]); Results[2] = (uint8*)((FVMReflection(TestObj)->*"BytePropArray")["uint8"][2], &bError[2]); Results[3] = (uint8*)((FVMReflection(TestObj)->*"BytePropArray")["uint8"][3], &bError[3]); for (int32 i=0; i<ARRAY_COUNT(Results); i++) { if (!bError[i] && Results[i] != NULL) { *Results[i] = TargetResults[i]; } } TestResults.Add(TEXT("Static Array Writing"), (!bError[0] && TestObj->BytePropArray[0] == TargetResults[0]) && (!bError[1] && TestObj->BytePropArray[1] == TargetResults[1]) && (!bError[2] && TestObj->BytePropArray[2] == TargetResults[2]) && (!bError[3] && TestObj->BytePropArray[3] == TargetResults[3])); } // Static object array reflection { UObject* TargetResults[2] = {UObject::StaticClass(), AActor::StaticClass()}; UVMTestClassA* TestObjA = NewObject<UVMTestClassA>(); UVMTestClassB* TestObjB[2] = {NewObject<UVMTestClassB>(), NewObject<UVMTestClassB>()}; if (TestObjA != NULL) { TestObjA->ObjectPropArray[0] = TestObjB[0]; TestObjA->ObjectPropArray[1] = TestObjB[1]; TestObjB[0]->BObjectRef = TargetResults[0]; TestObjB[1]->BObjectRef = TargetResults[1]; } bool bError[2] = {false, false}; UObject* Results[2]; Results[0] = (UObject*)((FVMReflection(TestObjA)->*"ObjectPropArray")["UObject*"][0]->*"BObjectRef", &bError[0]); Results[1] = (UObject*)((FVMReflection(TestObjA)->*"ObjectPropArray")["UObject*"][1]->*"BObjectRef", &bError[1]); TestResults.Add(TEXT("Static Object Array Reflection"), (!bError[0] && Results[0] == TargetResults[0]) && (!bError[1] && Results[1] == TargetResults[1])); } // Bad dynamic array access (no element selected) { UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); bool bError = false; (void)(uint8)((FVMReflection(TestObj)->*"DynBytePropArray")["uint8"], &bError); TestResults.Add(TEXT("Bad dynamic array access (no element)"), bError); } // Bad dynamic array access (no type verification) { UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); bool bError = false; (void)(uint8)(FVMReflection(TestObj)->*"DynBytePropArray", &bError); TestResults.Add(TEXT("Bad dynamic array access (no type verification)"), bError); } // Dynamic array reading { uint8 TargetResults[4] = {128, 64, 32, 16}; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynBytePropArray.Empty(); TestObj->DynBytePropArray.AddZeroed(4); TestObj->DynBytePropArray[0] = TargetResults[0]; TestObj->DynBytePropArray[1] = TargetResults[1]; TestObj->DynBytePropArray[2] = TargetResults[2]; TestObj->DynBytePropArray[3] = TargetResults[3]; } bool bError[4] = {false, false, false, false}; uint8 Results[4]; Results[0] = (uint8)((FVMReflection(TestObj)->*"DynBytePropArray")["uint8"][0], &bError[0]); Results[1] = (uint8)((FVMReflection(TestObj)->*"DynBytePropArray")["uint8"][1], &bError[1]); Results[2] = (uint8)((FVMReflection(TestObj)->*"DynBytePropArray")["uint8"][2], &bError[2]); Results[3] = (uint8)((FVMReflection(TestObj)->*"DynBytePropArray")["uint8"][3], &bError[3]); TestResults.Add(TEXT("Dynamic Array Reading"), (!bError[0] && Results[0] == TargetResults[0]) && (!bError[1] && Results[1] == TargetResults[1]) && (!bError[2] && Results[2] == TargetResults[2]) && (!bError[3] && Results[3] == TargetResults[3])); } // Dynamic array writing { uint8 TargetResults[4] = {31, 15, 24, 47}; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->DynBytePropArray.Empty(); TestObj->DynBytePropArray.AddZeroed(4); TestObj->DynBytePropArray[0] = 128; TestObj->DynBytePropArray[1] = 128; TestObj->DynBytePropArray[2] = 128; TestObj->DynBytePropArray[3] = 128; bool bError[4] = {false, false, false, false}; uint8* Results[4]; Results[0] = (uint8*)((FVMReflection(TestObj)->*"DynBytePropArray")["uint8"][0], &bError[0]); Results[1] = (uint8*)((FVMReflection(TestObj)->*"DynBytePropArray")["uint8"][1], &bError[1]); Results[2] = (uint8*)((FVMReflection(TestObj)->*"DynBytePropArray")["uint8"][2], &bError[2]); Results[3] = (uint8*)((FVMReflection(TestObj)->*"DynBytePropArray")["uint8"][3], &bError[3]); for (int32 i=0; i<ARRAY_COUNT(Results); i++) { if (!bError[i] && Results[i] != NULL) { *Results[i] = TargetResults[i]; } } TestResults.Add(TEXT("Dynamic Array Writing"), (!bError[0] && TestObj->DynBytePropArray[0] == TargetResults[0]) && (!bError[1] && TestObj->DynBytePropArray[1] == TargetResults[1]) && (!bError[2] && TestObj->DynBytePropArray[2] == TargetResults[2]) && (!bError[3] && TestObj->DynBytePropArray[3] == TargetResults[3])); } // Dynamic bool array reading { bool TargetResults[4] = {true, false, false, true}; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynBoolPropArray.Empty(); TestObj->DynBoolPropArray.AddZeroed(4); TestObj->DynBoolPropArray[0] = TargetResults[0]; TestObj->DynBoolPropArray[1] = TargetResults[1]; TestObj->DynBoolPropArray[2] = TargetResults[2]; TestObj->DynBoolPropArray[3] = TargetResults[3]; } bool bError[4] = {false, false, false, false}; bool Results[4]; Results[0] = (bool)((FVMReflection(TestObj)->*"DynBoolPropArray")["bool"][0], &bError[0]); Results[1] = (bool)((FVMReflection(TestObj)->*"DynBoolPropArray")["bool"][1], &bError[1]); Results[2] = (bool)((FVMReflection(TestObj)->*"DynBoolPropArray")["bool"][2], &bError[2]); Results[3] = (bool)((FVMReflection(TestObj)->*"DynBoolPropArray")["bool"][3], &bError[3]); TestResults.Add(TEXT("Dynamic Bool Array Reading"), (!bError[0] && Results[0] == TargetResults[0]) && (!bError[1] && Results[1] == TargetResults[1]) && (!bError[2] && Results[2] == TargetResults[2]) && (!bError[3] && Results[3] == TargetResults[3])); } // Dynamic object array reflection { UObject* TargetResults[2] = {UObject::StaticClass(), AActor::StaticClass()}; UVMTestClassA* TestObjA = NewObject<UVMTestClassA>(); UVMTestClassB* TestObjB[2] = {NewObject<UVMTestClassB>(), NewObject<UVMTestClassB>()}; if (TestObjA != NULL) { TestObjA->DynObjectPropArray.Empty(); TestObjA->DynObjectPropArray.AddZeroed(2); TestObjA->DynObjectPropArray[0] = TestObjB[0]; TestObjA->DynObjectPropArray[1] = TestObjB[1]; TestObjB[0]->BObjectRef = TargetResults[0]; TestObjB[1]->BObjectRef = TargetResults[1]; } bool bError[2] = {false, false}; UObject* Results[2]; Results[0] = (UObject*)((FVMReflection(TestObjA)->*"DynObjectPropArray")["UObject*"][0]->*"BObjectRef", &bError[0]); Results[1] = (UObject*)((FVMReflection(TestObjA)->*"DynObjectPropArray")["UObject*"][1]->*"BObjectRef", &bError[1]); TestResults.Add(TEXT("Dynamic Object Array Reflection"), (!bError[0] && Results[0] == TargetResults[0]) && (!bError[1] && Results[1] == TargetResults[1])); } // Dynamic array type verification (bool) { bool TargetResult = true; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynBoolPropArray.Empty(); TestObj->DynBoolPropArray.AddZeroed(1); TestObj->DynBoolPropArray[0] = TargetResult; } bool bError = false; bool Result; Result = (bool)((FVMReflection(TestObj)->*"DynBoolPropArray")["bool"][0], &bError); TestResults.Add(TEXT("Dynamic Array Type Verify (bool)"), (!bError && Result == TargetResult)); } // Dynamic array type verification (FName) { FName TargetResult = NAME_Camera; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynNamePropArray.Empty(); TestObj->DynNamePropArray.AddZeroed(1); TestObj->DynNamePropArray[0] = TargetResult; } bool bError = false; FName Result; Result = (FName)((FVMReflection(TestObj)->*"DynNamePropArray")["FName"][0], &bError); TestResults.Add(TEXT("Dynamic Array Type Verify (FName)"), (!bError && Result == TargetResult)); } // Dynamic array type verification (byte) { uint8 TargetResult = 92; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynBytePropArray.Empty(); TestObj->DynBytePropArray.AddZeroed(1); TestObj->DynBytePropArray[0] = TargetResult; } bool bError = false; uint8 Result; Result = (uint8)((FVMReflection(TestObj)->*"DynBytePropArray")["uint8"][0], &bError); TestResults.Add(TEXT("Dynamic Array Type Verify (byte)"), (!bError && Result == TargetResult)); } // Dynamic array type verification (double) { double TargetResult = 9.2; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynDoublePropArray.Empty(); TestObj->DynDoublePropArray.AddZeroed(1); TestObj->DynDoublePropArray[0] = TargetResult; } bool bError = false; double Result; Result = (double)((FVMReflection(TestObj)->*"DynDoublePropArray")["double"][0], &bError); TestResults.Add(TEXT("Dynamic Array Type Verify (double)"), (!bError && Result == TargetResult)); } // Dynamic array type verification (float) { float TargetResult = 8.4f; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynFloatPropArray.Empty(); TestObj->DynFloatPropArray.AddZeroed(1); TestObj->DynFloatPropArray[0] = TargetResult; } bool bError = false; float Result; Result = (float)((FVMReflection(TestObj)->*"DynFloatPropArray")["float"][0], &bError); TestResults.Add(TEXT("Dynamic Array Type Verify (float)"), (!bError && Result == TargetResult)); } // Dynamic array type verification (int16) { int16 TargetResult = 512; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynInt16PropArray.Empty(); TestObj->DynInt16PropArray.AddZeroed(1); TestObj->DynInt16PropArray[0] = TargetResult; } bool bError = false; int16 Result; Result = (int16)((FVMReflection(TestObj)->*"DynInt16PropArray")["int16"][0], &bError); TestResults.Add(TEXT("Dynamic Array Type Verify (int16)"), (!bError && Result == TargetResult)); } // Dynamic array type verification (int64) { int64 TargetResult = 982987423; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynInt64PropArray.Empty(); TestObj->DynInt64PropArray.AddZeroed(1); TestObj->DynInt64PropArray[0] = TargetResult; } bool bError = false; int64 Result; Result = (int64)((FVMReflection(TestObj)->*"DynInt64PropArray")["int64"][0], &bError); TestResults.Add(TEXT("Dynamic Array Type Verify (int64)"), (!bError && Result == TargetResult)); } // Dynamic array type verification (int8) { int8 TargetResult = 42; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynInt8PropArray.Empty(); TestObj->DynInt8PropArray.AddZeroed(1); TestObj->DynInt8PropArray[0] = TargetResult; } bool bError = false; int8 Result; Result = (int8)((FVMReflection(TestObj)->*"DynInt8PropArray")["int8"][0], &bError); TestResults.Add(TEXT("Dynamic Array Type Verify (int8)"), (!bError && Result == TargetResult)); } // Dynamic array type verification (int32) { int32 TargetResult = 65538; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynIntPropArray.Empty(); TestObj->DynIntPropArray.AddZeroed(1); TestObj->DynIntPropArray[0] = TargetResult; } bool bError = false; int32 Result; Result = (int32)((FVMReflection(TestObj)->*"DynIntPropArray")["int32"][0], &bError); TestResults.Add(TEXT("Dynamic Array Type Verify (int32)"), (!bError && Result == TargetResult)); } // Dynamic array type verification (uint16) { uint16 TargetResult = 1024; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynUInt16PropArray.Empty(); TestObj->DynUInt16PropArray.AddZeroed(1); TestObj->DynUInt16PropArray[0] = TargetResult; } bool bError = false; uint16 Result; Result = (uint16)((FVMReflection(TestObj)->*"DynUInt16PropArray")["uint16"][0], &bError); TestResults.Add(TEXT("Dynamic Array Type Verify (uint16)"), (!bError && Result == TargetResult)); } // Dynamic array type verification (uint32) { uint32 TargetResult = 65539; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynUIntPropArray.Empty(); TestObj->DynUIntPropArray.AddZeroed(1); TestObj->DynUIntPropArray[0] = TargetResult; } bool bError = false; uint32 Result; Result = (uint32)((FVMReflection(TestObj)->*"DynUIntPropArray")["uint32"][0], &bError); TestResults.Add(TEXT("Dynamic Array Type Verify (uint32)"), (!bError && Result == TargetResult)); } // Dynamic array type verification (uint64) { uint64 TargetResult = 89389732783ULL; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynUInt64PropArray.Empty(); TestObj->DynUInt64PropArray.AddZeroed(1); TestObj->DynUInt64PropArray[0] = TargetResult; } bool bError = false; uint64 Result; Result = (uint64)((FVMReflection(TestObj)->*"DynUInt64PropArray")["uint64"][0], &bError); TestResults.Add(TEXT("Dynamic Array Type Verify (uint64)"), (!bError && Result == TargetResult)); } // Dynamic array type verification (UObject*) { UObject* TargetResult = AActor::StaticClass(); UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynObjectPropArray.Empty(); TestObj->DynObjectPropArray.AddZeroed(1); TestObj->DynObjectPropArray[0] = TargetResult; } bool bError = false; UObject* Result; Result = (UObject*)((FVMReflection(TestObj)->*"DynObjectPropArray")["UObject*"][0], &bError); TestResults.Add(TEXT("Dynamic Array Type Verify (UObject*)"), (!bError && Result == TargetResult)); } // Dynamic array type verification (FString) { FString TargetResult = TEXT("blah"); UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynStringPropArray.Empty(); TestObj->DynStringPropArray.AddZeroed(1); TestObj->DynStringPropArray[0] = TargetResult; } bool bError = false; FString Result; Result = (FString)((FVMReflection(TestObj)->*"DynStringPropArray")["FString"][0], &bError); TestResults.Add(TEXT("Dynamic Array Type Verify (FString)"), (!bError && Result == TargetResult)); } // Dynamic array type verification (FText) { FText TargetResult = FText::FromString(TEXT("Blahd")); UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynTextPropArray.Empty(); TestObj->DynTextPropArray.AddZeroed(1); TestObj->DynTextPropArray[0] = TargetResult; } bool bError = false; FText Result; Result = (FText)((FVMReflection(TestObj)->*"DynTextPropArray")["FText"][0], &bError); TestResults.Add(TEXT("Dynamic Array Type Verify (FText)"), (!bError && Result.EqualTo(TargetResult))); } // Dynamic array type verification (UClass*) { UClass* TargetResult = AActor::StaticClass(); UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynClassPropArray.Empty(); TestObj->DynClassPropArray.AddZeroed(1); TestObj->DynClassPropArray[0] = TargetResult; } bool bError = false; UClass* Result; Result = (UClass*)(UObject*)((FVMReflection(TestObj)->*"DynClassPropArray")["UClass*"][0], &bError); TestResults.Add(TEXT("Dynamic Array Type Verify (UClass*)"), (!bError && Result == TargetResult)); } // Dynamic array type verification (APawn*) { APawn* TargetResult = (APawn*)GetDefault<ADefaultPawn>(); UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynPawnPropArray.Empty(); TestObj->DynPawnPropArray.AddZeroed(1); TestObj->DynPawnPropArray[0] = TargetResult; } bool bError = false; APawn* Result; Result = (APawn*)(UObject*)((FVMReflection(TestObj)->*"DynPawnPropArray")["APawn*"][0], &bError); TestResults.Add(TEXT("Dynamic Array Type Verify (APawn*)"), (!bError && Result == TargetResult)); } // Dynamic array adding { uint8 TargetResults[8] = {4, 45, 31, 67, 99, 104, 192, 30}; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->DynBytePropArray.Empty(); bool bError; TArray<uint8>* ArrayRef = (TArray<uint8>*)(FScriptArray*)((FVMReflection(TestObj)->*"DynBytePropArray")["uint8"], &bError); if (!bError && ArrayRef != NULL) { TArray<uint8>& TargetArray = *ArrayRef; TargetArray.AddZeroed(8); TargetArray[0] = TargetResults[0]; TargetArray[1] = TargetResults[1]; TargetArray[2] = TargetResults[2]; TargetArray[3] = TargetResults[3]; TargetArray[4] = TargetResults[4]; TargetArray[5] = TargetResults[5]; TargetArray[6] = TargetResults[6]; TargetArray[7] = TargetResults[7]; } TestResults.Add(TEXT("Dynamic Array Adding"), !bError && TestObj->DynBytePropArray.Num() == 8 && (TestObj->DynBytePropArray[0] == TargetResults[0]) && (TestObj->DynBytePropArray[1] == TargetResults[1]) && (TestObj->DynBytePropArray[2] == TargetResults[2]) && (TestObj->DynBytePropArray[3] == TargetResults[3]) && (TestObj->DynBytePropArray[4] == TargetResults[4]) && (TestObj->DynBytePropArray[5] == TargetResults[5]) && (TestObj->DynBytePropArray[6] == TargetResults[6]) && (TestObj->DynBytePropArray[7] == TargetResults[7])); } // Struct property reading { float TargetResult = 12.8f; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->StructProp.X = TargetResult; } bool bError = false; float Result = (float)(FVMReflection(TestObj)->*"StructProp"->*"X", &bError); TestResults.Add(TEXT("Struct Reading"), (!bError && Result == TargetResult)); } // Struct property writing { float TargetResult = 6.4f; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->StructProp.Y = 12.8f; bool bError = false; float* Result = (float*)(FVMReflection(TestObj)->*"StructProp"->*"Y", &bError); if (!bError && Result != NULL) { *Result = TargetResult; } TestResults.Add(TEXT("Struct Writing"), (!bError && TestObj->StructProp.Y == TargetResult)); } // Struct property casting { float TargetResult = 12.8f; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->StructProp.X = 0.f; } bool bError = false; FVector* StructRef = (FVector*)(void*)((FVMReflection(TestObj)->*"StructProp")["FVector"], &bError); if (!bError && StructRef != NULL) { StructRef->X = TargetResult; } TestResults.Add(TEXT("Struct Casting"), (!bError && TestObj->StructProp.X == TargetResult)); } // Struct static array reading { float TargetResult[2] = {12.8f, 83.2f}; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->StructPropArray[0].X = TargetResult[0]; TestObj->StructPropArray[1].X = TargetResult[1]; } bool bError[2] = {false, false}; float Results[2]; Results[0] = (float)((FVMReflection(TestObj)->*"StructPropArray")["FVector"][0]->*"X", &bError[0]); Results[1] = (float)((FVMReflection(TestObj)->*"StructPropArray")["FVector"][1]->*"X", &bError[1]); TestResults.Add(TEXT("Struct Static Array Reading"), (!bError[0] && Results[0] == TargetResult[0]) && (!bError[1] && Results[1] == TargetResult[1])); } // Struct static array writing { float TargetResult[2] = {6.4f, 82.3f}; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->StructPropArray[0].Y = 12.8f; TestObj->StructPropArray[1].Y = 12.8f; bool bError[2] = {false, false}; float* Results[2]; Results[0] = (float*)((FVMReflection(TestObj)->*"StructPropArray")["FVector"][0]->*"Y", &bError[0]); Results[1] = (float*)((FVMReflection(TestObj)->*"StructPropArray")["FVector"][1]->*"Y", &bError[1]); if (!bError[0] && !bError[1] && Results[0] != NULL && Results[1] != NULL) { *Results[0] = TargetResult[0]; *Results[1] = TargetResult[1]; } TestResults.Add(TEXT("Struct Static Array Writing"), (!bError[0] && TestObj->StructPropArray[0].Y == TargetResult[0]) && (!bError[1] && TestObj->StructPropArray[1].Y == TargetResult[1])); } // Struct static array casting { float TargetResult = 12.8f; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->StructPropArray[1].X = 0.f; } bool bError = false; FVector* StructRef = (FVector*)(void*)((FVMReflection(TestObj)->*"StructPropArray")["FVector"][1], &bError); if (!bError && StructRef != NULL) { StructRef->X = TargetResult; } TestResults.Add(TEXT("Struct Static Array Casting"), (!bError && TestObj->StructPropArray[1].X == TargetResult)); } // Struct dynamic array reading { float TargetResult[2] = {12.8f, 83.2f}; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynStructPropArray.Empty(); TestObj->DynStructPropArray.AddZeroed(2); TestObj->DynStructPropArray[0].X = TargetResult[0]; TestObj->DynStructPropArray[1].X = TargetResult[1]; } bool bError[2] = {false, false}; float Results[2]; Results[0] = (float)((FVMReflection(TestObj)->*"DynStructPropArray")["FVector"][0]->*"X", &bError[0]); Results[1] = (float)((FVMReflection(TestObj)->*"DynStructPropArray")["FVector"][1]->*"X", &bError[1]); TestResults.Add(TEXT("Struct Dynamic Array Reading"), (!bError[0] && Results[0] == TargetResult[0]) && (!bError[1] && Results[1] == TargetResult[1])); } // Struct dynamic array writing { float TargetResult[2] = {6.4f, 82.3f}; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); TestObj->DynStructPropArray.Empty(); TestObj->DynStructPropArray.AddZeroed(2); TestObj->DynStructPropArray[0].Y = 12.8f; TestObj->DynStructPropArray[1].Y = 12.8f; bool bError[2] = {false, false}; float* Results[2]; Results[0] = (float*)((FVMReflection(TestObj)->*"DynStructPropArray")["FVector"][0]->*"Y", &bError[0]); Results[1] = (float*)((FVMReflection(TestObj)->*"DynStructPropArray")["FVector"][1]->*"Y", &bError[1]); if (!bError[0] && !bError[1] && Results[0] != NULL && Results[1] != NULL) { *Results[0] = TargetResult[0]; *Results[1] = TargetResult[1]; } TestResults.Add(TEXT("Struct Dynamic Array Writing"), (!bError[0] && TestObj->DynStructPropArray[0].Y == TargetResult[0]) && (!bError[1] && TestObj->DynStructPropArray[1].Y == TargetResult[1])); } // Struct dynamic array casting { float TargetResult = 12.8f; UVMTestClassA* TestObj = NewObject<UVMTestClassA>(); if (TestObj != NULL) { TestObj->DynStructPropArray.Empty(); TestObj->DynStructPropArray.AddZeroed(2); TestObj->DynStructPropArray[1].X = 0.f; } bool bError = false; FVector* StructRef = (FVector*)(void*)((FVMReflection(TestObj)->*"DynStructPropArray")["FVector"][1], &bError); if (!bError && StructRef != NULL) { StructRef->X = TargetResult; } TestResults.Add(TEXT("Struct Dynamic Array Casting"), (!bError && TestObj->DynStructPropArray[1].X == TargetResult)); } // Verify the results for (TMap<FString, bool>::TConstIterator It(TestResults); It; ++It) { UNIT_LOG(ELogType::StatusImportant, TEXT("Test '%s' returned: %s"), *It.Key(), (It.Value() ? TEXT("Success") : TEXT("FAIL"))); if (!It.Value()) { VerificationState = EUnitTestVerification::VerifiedNeedsUpdate; } } if (VerificationState == EUnitTestVerification::Unverified) { VerificationState = EUnitTestVerification::VerifiedFixed; } return bSuccess; }
void FKismetVariableDragDropAction::HoverTargetChanged() { UProperty* VariableProperty = GetVariableProperty(); if (VariableProperty == nullptr) { return; } FString VariableString = VariableName.ToString(); // Icon/text to draw on tooltip FSlateColor IconColor = FLinearColor::White; const FSlateBrush* StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error")); FText Message = LOCTEXT("InvalidDropTarget", "Invalid drop target!"); UEdGraphPin* PinUnderCursor = GetHoveredPin(); bool bCanMakeSetter = true; bool bBadSchema = false; bool bBadGraph = false; UEdGraph* HoveredGraph = GetHoveredGraph(); if (HoveredGraph) { if (Cast<const UEdGraphSchema_K2>(HoveredGraph->GetSchema()) == NULL) { bBadSchema = true; } else if(!CanVariableBeDropped(VariableProperty, *HoveredGraph)) { bBadGraph = true; } UStruct* Outer = CastChecked<UStruct>(VariableProperty->GetOuter()); FNodeConstructionParams NewNodeParams; NewNodeParams.VariableName = VariableName; const UBlueprint* DropOnBlueprint = FBlueprintEditorUtils::FindBlueprintForGraph(HoveredGraph); NewNodeParams.Graph = HoveredGraph; NewNodeParams.VariableSource = Outer; bCanMakeSetter = CanExecuteMakeSetter(NewNodeParams, VariableProperty); } UEdGraphNode* VarNodeUnderCursor = Cast<UK2Node_Variable>(GetHoveredNode()); if (bBadSchema) { StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error")); Message = LOCTEXT("CannotCreateInThisSchema", "Cannot access variables in this type of graph"); } else if(bBadGraph) { FFormatNamedArguments Args; Args.Add(TEXT("VariableName"), FText::FromString(VariableString)); Args.Add(TEXT("Scope"), FText::FromString(HoveredGraph->GetName())); StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error")); if(IsFromBlueprint(FBlueprintEditorUtils::FindBlueprintForGraph(HoveredGraph)) && VariableProperty->GetOuter()->IsA(UFunction::StaticClass())) { Message = FText::Format( LOCTEXT("IncorrectGraphForLocalVariable_Error", "Cannot place local variable '{VariableName}' in external scope '{Scope}'"), Args); } else { Message = FText::Format( LOCTEXT("IncorrectGraphForVariable_Error", "Cannot place variable '{VariableName}' in external scope '{Scope}'"), Args); } } else if (PinUnderCursor != NULL) { FFormatNamedArguments Args; Args.Add(TEXT("PinUnderCursor"), FText::FromString(PinUnderCursor->PinName)); Args.Add(TEXT("VariableName"), FText::FromString(VariableString)); if(CanVariableBeDropped(VariableProperty, *PinUnderCursor->GetOwningNode()->GetGraph())) { const UEdGraphSchema_K2* Schema = CastChecked<const UEdGraphSchema_K2>(PinUnderCursor->GetSchema()); const bool bIsRead = PinUnderCursor->Direction == EGPD_Input; const UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForNode(PinUnderCursor->GetOwningNode()); const bool bReadOnlyProperty = FBlueprintEditorUtils::IsPropertyReadOnlyInCurrentBlueprint(Blueprint, VariableProperty); const bool bCanWriteIfNeeded = bIsRead || !bReadOnlyProperty; FEdGraphPinType VariablePinType; Schema->ConvertPropertyToPinType(VariableProperty, VariablePinType); const bool bTypeMatch = Schema->ArePinTypesCompatible(VariablePinType, PinUnderCursor->PinType); Args.Add(TEXT("PinUnderCursor"), FText::FromString(PinUnderCursor->PinName)); if (bTypeMatch && bCanWriteIfNeeded) { StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.OK")); if (bIsRead) { Message = FText::Format(LOCTEXT("MakeThisEqualThat_PinEqualVariableName", "Make {PinUnderCursor} = {VariableName}"), Args); } else { Message = FText::Format(LOCTEXT("MakeThisEqualThat_VariableNameEqualPin", "Make {VariableName} = {PinUnderCursor}"), Args); } } else { StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error")); if (!bCanWriteIfNeeded) { Message = FText::Format(LOCTEXT("ReadOnlyVar_Error", "Cannot write to read-only variable '{VariableName}'"), Args); } else { Message = FText::Format(LOCTEXT("NotCompatible_Error", "The type of '{VariableName}' is not compatible with {PinUnderCursor}"), Args); } } } else { Args.Add(TEXT("Scope"), FText::FromString(PinUnderCursor->GetOwningNode()->GetGraph()->GetName())); StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error")); Message = FText::Format( LOCTEXT("IncorrectGraphForPin_Error", "Cannot place local variable '{VariableName}' in external scope '{Scope}'"), Args); } } else if (VarNodeUnderCursor != NULL) { FFormatNamedArguments Args; Args.Add(TEXT("VariableName"), FText::FromString(VariableString)); if(CanVariableBeDropped(VariableProperty, *VarNodeUnderCursor->GetGraph())) { const bool bIsRead = VarNodeUnderCursor->IsA(UK2Node_VariableGet::StaticClass()); const UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForNode(VarNodeUnderCursor); const bool bReadOnlyProperty = FBlueprintEditorUtils::IsPropertyReadOnlyInCurrentBlueprint(Blueprint, VariableProperty); const bool bCanWriteIfNeeded = bIsRead || !bReadOnlyProperty; if (bCanWriteIfNeeded) { Args.Add(TEXT("ReadOrWrite"), bIsRead ? LOCTEXT("Read", "read") : LOCTEXT("Write", "write")); if(WillBreakLinks(VarNodeUnderCursor, VariableProperty)) { StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.OKWarn")); Message = FText::Format( LOCTEXT("ChangeNodeToWarnBreakLinks", "Change node to {ReadOrWrite} '{VariableName}', WARNING this will break links!"), Args); } else { StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.OK")); Message = FText::Format( LOCTEXT("ChangeNodeTo", "Change node to {ReadOrWrite} '{VariableName}'"), Args); } } else { StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error")); Message = FText::Format( LOCTEXT("ReadOnlyVar_Error", "Cannot write to read-only variable '{VariableName}'"), Args); } } else { Args.Add(TEXT("Scope"), FText::FromString(VarNodeUnderCursor->GetGraph()->GetName())); StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error")); Message = FText::Format( LOCTEXT("IncorrectGraphForNodeReplace_Error", "Cannot replace node with local variable '{VariableName}' in external scope '{Scope}'"), Args); } } else if (!HoveredCategoryName.IsEmpty()) { // Find Blueprint that made this class and get category of variable FText Category; UBlueprint* Blueprint; // Find the Blueprint for this property if(Cast<UFunction>(VariableSource.Get())) { Blueprint = UBlueprint::GetBlueprintFromClass(Cast<UClass>(VariableSource->GetOuter())); } else { Blueprint = UBlueprint::GetBlueprintFromClass(Cast<UClass>(VariableSource.Get())); } if(Blueprint != NULL) { Category = FBlueprintEditorUtils::GetBlueprintVariableCategory(Blueprint, VariableProperty->GetFName(), GetLocalVariableScope() ); } // See if class is native UClass* OuterClass = Cast<UClass>(VariableProperty->GetOuter()); if(OuterClass || Cast<UFunction>(VariableProperty->GetOuter())) { const bool bIsNativeVar = (OuterClass && OuterClass->ClassGeneratedBy == NULL); FFormatNamedArguments Args; Args.Add(TEXT("VariableName"), FText::FromString(VariableString)); Args.Add(TEXT("HoveredCategoryName"), HoveredCategoryName); if (bIsNativeVar) { StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error")); Message = FText::Format( LOCTEXT("ChangingCatagoryNotThisVar", "Cannot change category for variable '{VariableName}'"), Args ); } else if (Category.EqualTo(HoveredCategoryName)) { StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error")); Message = FText::Format( LOCTEXT("ChangingCatagoryAlreadyIn", "Variable '{VariableName}' is already in category '{HoveredCategoryName}'"), Args ); } else { StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.OK")); Message = FText::Format( LOCTEXT("ChangingCatagoryOk", "Move variable '{VariableName}' to category '{HoveredCategoryName}'"), Args ); } } } else if (HoveredAction.IsValid()) { if(HoveredAction.Pin()->GetTypeId() == FEdGraphSchemaAction_K2Var::StaticGetTypeId()) { FEdGraphSchemaAction_K2Var* VarAction = (FEdGraphSchemaAction_K2Var*)HoveredAction.Pin().Get(); FName TargetVarName = VarAction->GetVariableName(); // Needs to have a valid index to move it (this excludes variables added through other means, like timelines/components int32 MoveVarIndex = INDEX_NONE; int32 TargetVarIndex = INDEX_NONE; UBlueprint* Blueprint = UBlueprint::GetBlueprintFromClass(Cast<UClass>(VariableSource.Get())); if(Blueprint != NULL) { MoveVarIndex = FBlueprintEditorUtils::FindNewVariableIndex(Blueprint, VariableName); TargetVarIndex = FBlueprintEditorUtils::FindNewVariableIndex(Blueprint, TargetVarName); } FFormatNamedArguments Args; Args.Add(TEXT("VariableName"), FText::FromString(VariableString)); Args.Add(TEXT("TargetVarName"), FText::FromName(TargetVarName)); if(MoveVarIndex == INDEX_NONE) { StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error")); Message = FText::Format( LOCTEXT("MoveVarDiffClass", "Cannot reorder variable '{VariableName}'."), Args ); } else if(TargetVarIndex == INDEX_NONE) { StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error")); Message = FText::Format( LOCTEXT("MoveVarOther", "Cannot reorder variable '{VariableName}' before '{TargetVarName}'."), Args ); } else if(VariableName == TargetVarName) { StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error")); Message = FText::Format( LOCTEXT("MoveVarYourself", "Cannot reorder variable '{VariableName}' before itself."), Args ); } else { StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.OK")); Message = FText::Format( LOCTEXT("MoveVarOK", "Reorder variable '{VariableName}' before '{TargetVarName}'"), Args ); } } } else if (bAltDrag && !bCanMakeSetter) { FFormatNamedArguments Args; Args.Add(TEXT("VariableName"), FText::FromString(VariableString)); StatusSymbol = FEditorStyle::GetBrush(TEXT("Graph.ConnectorFeedback.Error")); Message = FText::Format(LOCTEXT("CannotPlaceSetter", "Variable '{VariableName}' is readonly, you cannot set this variable."), Args); } // Draw variable icon else { StatusSymbol = FBlueprintEditor::GetVarIconAndColor(VariableSource.Get(), VariableName, IconColor); Message = FText::FromString(VariableString); } SetSimpleFeedbackMessage(StatusSymbol, IconColor, Message); }