bool FModuleDescriptor::ReadArray(const FJsonObject& Object, const TCHAR* Name, TArray<FModuleDescriptor>& OutModules, FText& OutFailReason) { bool bResult = true; TSharedPtr<FJsonValue> ModulesArrayValue = Object.TryGetField(Name); if(ModulesArrayValue.IsValid() && ModulesArrayValue->Type == EJson::Array) { const TArray< TSharedPtr< FJsonValue > >& ModulesArray = ModulesArrayValue->AsArray(); for(int Idx = 0; Idx < ModulesArray.Num(); Idx++) { const TSharedPtr<FJsonValue>& ModuleValue = ModulesArray[Idx]; if(ModuleValue.IsValid() && ModuleValue->Type == EJson::Object) { FModuleDescriptor Descriptor; if(Descriptor.Read(*ModuleValue->AsObject().Get(), OutFailReason)) { OutModules.Add(Descriptor); } else { bResult = false; } } else { OutFailReason = LOCTEXT( "ModuleWithInvalidModulesArray", "The 'Modules' array has invalid contents and was not able to be loaded." ); bResult = false; } } } return bResult; }
void FVehicleTransmissionDataCustomization::EmptyGears(TSharedRef<IPropertyHandle> StructPropertyHandle) { TSharedPtr<IPropertyHandle> GearsHandle = StructPropertyHandle->GetChildHandle("ForwardGears"); if (GearsHandle->IsValidHandle()) { TSharedPtr<IPropertyHandleArray> GearsArray = GearsHandle->AsArray(); GearsArray->EmptyArray(); } }
void FInputAxisMappingCustomizationExtended::RemoveAxisMappingButton_OnClick() { if (AxisMappingHandle->IsValidHandle()) { const TSharedPtr<IPropertyHandle> ParentHandle = AxisMappingHandle->GetParentHandle(); const TSharedPtr<IPropertyHandleArray> ParentArrayHandle = ParentHandle->AsArray(); ParentArrayHandle->DeleteItem(AxisMappingHandle->GetIndexInArray()); } }
FReply FDialogueWaveDetails::AddDialogueContextMapping_OnClicked() { const TSharedPtr<IPropertyHandle> ContextMappingsPropertyHandle = DetailLayoutBuilder->GetProperty("ContextMappings", UDialogueWave::StaticClass()); const TSharedPtr<IPropertyHandleArray> ContextMappingsPropertyArrayHandle = ContextMappingsPropertyHandle->AsArray(); ContextMappingsPropertyArrayHandle->AddItem(); DetailLayoutBuilder->ForceRefreshDetails(); return FReply::Handled(); }
void FVehicleTransmissionDataCustomization::RemoveGear(TSharedRef<IPropertyHandle> GearHandle) { if (GearHandle->IsValidHandle()) { const TSharedPtr<IPropertyHandle> ParentHandle = GearHandle->GetParentHandle(); const TSharedPtr<IPropertyHandleArray> ParentArrayHandle = ParentHandle->AsArray(); ParentArrayHandle->DeleteItem(GearHandle->GetIndexInArray()); } }
bool FJsonObjectConverter::JsonValueToUProperty(TSharedPtr<FJsonValue> JsonValue, UProperty* Property, void* OutValue, int64 CheckFlags, int64 SkipFlags) { if (!JsonValue.IsValid()) { UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Invalid value JSON key")); return false; } bool bArrayProperty = Property->IsA<UArrayProperty>(); bool bJsonArray = JsonValue->Type == EJson::Array; if (!bJsonArray) { if (bArrayProperty) { UE_LOG(LogJson, Error, TEXT("JsonValueToUProperty - Attempted to import TArray from non-array JSON key")); return false; } if (Property->ArrayDim != 1) { UE_LOG(LogJson, Warning, TEXT("Ignoring excess properties when deserializing %s"), *Property->GetName()); } return ConvertScalarJsonValueToUProperty(JsonValue, Property, OutValue, CheckFlags, SkipFlags); } // In practice, the ArrayDim == 1 check ought to be redundant, since nested arrays of UPropertys are not supported if (bArrayProperty && Property->ArrayDim == 1) { // Read into TArray return ConvertScalarJsonValueToUProperty(JsonValue, Property, OutValue, CheckFlags, SkipFlags); } // We're deserializing a JSON array const auto& ArrayValue = JsonValue->AsArray(); if (Property->ArrayDim < ArrayValue.Num()) { UE_LOG(LogJson, Warning, TEXT("Ignoring excess properties when deserializing %s"), *Property->GetName()); } // Read into native array int ItemsToRead = FMath::Clamp(ArrayValue.Num(), 0, Property->ArrayDim); for (int Index = 0; Index != ItemsToRead; ++Index) { if (!ConvertScalarJsonValueToUProperty(ArrayValue[Index], Property, (char*)OutValue + Index * Property->ElementSize, CheckFlags, SkipFlags)) { return false; } } return true; }
void UVaRestJsonObject::SetArrayField(const FString& FieldName, const TArray<UVaRestJsonValue*>& InArray) { if (!JsonObj.IsValid()) { return; } TArray< TSharedPtr<FJsonValue> > ValArray; // Process input array and COPY original values for (auto InVal : InArray) { TSharedPtr<FJsonValue> JsonVal = InVal->GetRootValue(); switch (InVal->GetType()) { case EVaJson::None: break; case EVaJson::Null: ValArray.Add(MakeShareable(new FJsonValueNull())); break; case EVaJson::String: ValArray.Add(MakeShareable(new FJsonValueString(JsonVal->AsString()))); break; case EVaJson::Number: ValArray.Add(MakeShareable(new FJsonValueNumber(JsonVal->AsNumber()))); break; case EVaJson::Boolean: ValArray.Add(MakeShareable(new FJsonValueBoolean(JsonVal->AsBool()))); break; case EVaJson::Array: ValArray.Add(MakeShareable(new FJsonValueArray(JsonVal->AsArray()))); break; case EVaJson::Object: ValArray.Add(MakeShareable(new FJsonValueObject(JsonVal->AsObject()))); break; default: break; } } JsonObj->SetArrayField(FieldName, ValArray); }
void CopyJsonValueToWriter( JsonWriter &Json, const FString& ValueName, const TSharedPtr<FJsonValue>& JsonValue ) { if ( JsonValue->Type == EJson::String ) { Json->WriteValue( ValueName, JsonValue->AsString() ); } else if ( JsonValue->Type == EJson::Array ) { if (ValueName.IsEmpty()) { Json->WriteArrayStart(); } else { Json->WriteArrayStart(ValueName); } const TArray<TSharedPtr<FJsonValue>>& Array = JsonValue->AsArray(); for ( const auto& ArrayValue : Array ) { CopyJsonValueToWriter(Json, FString(), ArrayValue); } Json->WriteArrayEnd(); } else if ( JsonValue->Type == EJson::Object ) { if (ValueName.IsEmpty()) { Json->WriteObjectStart(); } else { Json->WriteObjectStart(ValueName); } const TSharedPtr<FJsonObject>& Object = JsonValue->AsObject(); for ( const auto& ObjectProperty : Object->Values) { CopyJsonValueToWriter(Json, ObjectProperty.Key, ObjectProperty.Value ); } Json->WriteObjectEnd(); } else { UE_LOG(LogChunkManifestGenerator, Warning, TEXT("Unrecognized json value type %d in object %s"), *UEnum::GetValueAsString(TEXT("Json.EJson"), JsonValue->Type), *ValueName) } }
void SLocalizationDashboardTargetRow::Delete() { static bool IsExecuting = false; if (!IsExecuting) { TGuardValue<bool> ReentranceGuard(IsExecuting, true); ULocalizationTarget* const LocalizationTarget = GetTarget(); if (LocalizationTarget) { FText TitleText; FText MessageText; // Setup dialog for deleting target. const FText FormatPattern = NSLOCTEXT("LocalizationDashboard", "DeleteTargetConfirmationDialogMessage", "This action can not be undone and data will be permanently lost. Are you sure you would like to delete {TargetName}?"); FFormatNamedArguments Arguments; Arguments.Add(TEXT("TargetName"), FText::FromString(LocalizationTarget->Settings.Name)); MessageText = FText::Format(FormatPattern, Arguments); TitleText = NSLOCTEXT("LocalizationDashboard", "DeleteTargetConfirmationDialogTitle", "Confirm Target Deletion"); switch(FMessageDialog::Open(EAppMsgType::OkCancel, MessageText, &TitleText)) { case EAppReturnType::Ok: { LocalizationTarget->Settings.DeleteFiles(); // Close target editor. if (TargetEditorDockTab.IsValid()) { const TSharedPtr<SDockTab> OldTargetEditorTab = TargetEditorDockTab.Pin(); OldTargetEditorTab->RequestCloseTab(); } // Remove this element from the parent array. const TSharedPtr<IPropertyHandle> ParentPropertyHandle = TargetObjectPropertyHandle->GetParentHandle(); if (ParentPropertyHandle.IsValid() && ParentPropertyHandle->IsValidHandle()) { const TSharedPtr<IPropertyHandleArray> ParentArrayPropertyHandle = ParentPropertyHandle->AsArray(); if (ParentArrayPropertyHandle.IsValid()) { ParentArrayPropertyHandle->DeleteItem(TargetObjectPropertyHandle->GetIndexInArray()); } } } break; } } } }
void FDialogueContextMappingNodeBuilder::RemoveContextButton_OnClick() { if( ContextMappingPropertyHandle->IsValidHandle() ) { const TSharedPtr<IPropertyHandle> ParentHandle = ContextMappingPropertyHandle->GetParentHandle(); const TSharedPtr<IPropertyHandleArray> ParentArrayHandle = ParentHandle->AsArray(); uint32 ContextCount; ParentArrayHandle->GetNumElements(ContextCount); if( ContextCount != 1 ) // Mustn't remove the only context. { ParentArrayHandle->DeleteItem( ContextMappingPropertyHandle->GetIndexInArray() ); DetailLayoutBuilder->ForceRefreshDetails(); } } }
void FDialogueContextMappingNodeBuilder::GenerateHeaderRowContent( FDetailWidgetRow& NodeRow ) { if( ContextMappingPropertyHandle->IsValidHandle() ) { const TSharedPtr<IPropertyHandle> ContextPropertyHandle = ContextMappingPropertyHandle->GetChildHandle("Context"); if( ContextPropertyHandle->IsValidHandle() ) { const TSharedPtr<IPropertyHandle> SpeakerPropertyHandle = ContextPropertyHandle->GetChildHandle("Speaker"); const TSharedPtr<IPropertyHandle> TargetsPropertyHandle = ContextPropertyHandle->GetChildHandle("Targets"); const TSharedPtr<IPropertyHandle> ParentHandle = ContextMappingPropertyHandle->GetParentHandle(); const TSharedPtr<IPropertyHandleArray> ParentArrayHandle = ParentHandle->AsArray(); uint32 ContextCount; ParentArrayHandle->GetNumElements(ContextCount); TSharedRef<SWidget> ClearButton = PropertyCustomizationHelpers::MakeDeleteButton( FSimpleDelegate::CreateSP( this, &FDialogueContextMappingNodeBuilder::RemoveContextButton_OnClick), ContextCount > 1 ? LOCTEXT("RemoveContextToolTip", "Remove context.") : LOCTEXT("RemoveContextDisabledToolTip", "Cannot remove context - a dialogue wave must have at least one context."), ContextCount > 1 ); NodeRow [ SNew( SHorizontalBox ) +SHorizontalBox::Slot() .FillWidth(1.0f) [ SNew( SBorder ) .BorderImage( FEditorStyle::GetBrush("DialogueWaveDetails.HeaderBorder") ) [ SNew( SDialogueContextHeaderWidget, ContextPropertyHandle.ToSharedRef(), DetailLayoutBuilder->GetThumbnailPool().ToSharedRef() ) ] ] +SHorizontalBox::Slot() .Padding(2.0f) .HAlign(HAlign_Center) .VAlign(VAlign_Center) .AutoWidth() [ ClearButton ] ]; } } }
void FDialogueWaveDetails::CustomizeDetails( class IDetailLayoutBuilder& DetailBuilder ) { DetailLayoutBuilder = &DetailBuilder; IDetailCategoryBuilder& ContextMappingsDetailCategoryBuilder = DetailBuilder.EditCategory("DialogueContexts"); // Add Context Button ContextMappingsDetailCategoryBuilder.AddCustomRow( LOCTEXT("AddDialogueContext", "Add Dialogue Context") ) [ SNew( SBox ) .Padding(2.0f) .VAlign(VAlign_Center) .HAlign(HAlign_Center) [ SNew( SButton ) .Text( LOCTEXT("AddDialogueContext", "Add Dialogue Context") ) .ToolTipText( LOCTEXT("AddDialogueContextToolTip", "Adds a new context for dialogue based on speakers, those spoken to, and the associated soundwave.") ) .OnClicked( FOnClicked::CreateSP( this, &FDialogueWaveDetails::AddDialogueContextMapping_OnClicked ) ) ] ]; // Individual Context Mappings const TSharedPtr<IPropertyHandle> ContextMappingsPropertyHandle = DetailLayoutBuilder->GetProperty("ContextMappings", UDialogueWave::StaticClass()); ContextMappingsPropertyHandle->MarkHiddenByCustomization(); const TSharedPtr<IPropertyHandleArray> ContextMappingsPropertyArrayHandle = ContextMappingsPropertyHandle->AsArray(); uint32 DialogueContextMappingCount; ContextMappingsPropertyArrayHandle->GetNumElements( DialogueContextMappingCount ); for(uint32 j = 0; j < DialogueContextMappingCount; ++j) { const TSharedPtr<IPropertyHandle> ChildContextMappingPropertyHandle = ContextMappingsPropertyArrayHandle->GetElement(j); const TSharedRef<FDialogueContextMappingNodeBuilder> DialogueContextMapping = MakeShareable( new FDialogueContextMappingNodeBuilder( DetailLayoutBuilder, ChildContextMappingPropertyHandle ) ); ContextMappingsDetailCategoryBuilder.AddCustomBuilder(DialogueContextMapping); } }
// @TODO LSwift: Perhaps replace FromBlob and ToBlob usage with hexadecimal notation instead bool FBuildPatchAppManifest::DeserializeFromJSON( const FString& JSONInput ) { bool bSuccess = true; TSharedPtr<FJsonObject> JSONManifestObject; TSharedRef<TJsonReader<TCHAR>> Reader = TJsonReaderFactory<TCHAR>::Create(JSONInput); // Clear current data DestroyData(); // Attempt to deserialize JSON if (!FJsonSerializer::Deserialize(Reader, JSONManifestObject) || !JSONManifestObject.IsValid()) { return false; } // Store a list of all data GUID for later use TSet<FGuid> AllDataGuids; // Get the values map TMap<FString, TSharedPtr<FJsonValue>>& JsonValueMap = JSONManifestObject->Values; // Manifest version did not always exist int32 ManifestFileVersionInt = 0; TSharedPtr<FJsonValue> JsonManifestFileVersion = JsonValueMap.FindRef(TEXT("ManifestFileVersion")); if (JsonManifestFileVersion.IsValid() && FromStringBlob(JsonManifestFileVersion->AsString(), ManifestFileVersionInt)) { Data->ManifestFileVersion = static_cast<EBuildPatchAppManifestVersion::Type>(ManifestFileVersionInt); } else { // Then we presume version just before we started outputting the version Data->ManifestFileVersion = static_cast<EBuildPatchAppManifestVersion::Type>(EBuildPatchAppManifestVersion::StartStoringVersion - 1); } // Get the app and version strings TSharedPtr< FJsonValue > JsonAppID = JsonValueMap.FindRef( TEXT("AppID") ); TSharedPtr< FJsonValue > JsonAppNameString = JsonValueMap.FindRef( TEXT("AppNameString") ); TSharedPtr< FJsonValue > JsonBuildVersionString = JsonValueMap.FindRef( TEXT("BuildVersionString") ); TSharedPtr< FJsonValue > JsonLaunchExe = JsonValueMap.FindRef( TEXT("LaunchExeString") ); TSharedPtr< FJsonValue > JsonLaunchCommand = JsonValueMap.FindRef( TEXT("LaunchCommand") ); TSharedPtr< FJsonValue > JsonPrereqName = JsonValueMap.FindRef( TEXT("PrereqName") ); TSharedPtr< FJsonValue > JsonPrereqPath = JsonValueMap.FindRef( TEXT("PrereqPath") ); TSharedPtr< FJsonValue > JsonPrereqArgs = JsonValueMap.FindRef( TEXT("PrereqArgs") ); bSuccess = bSuccess && JsonAppID.IsValid(); if( bSuccess ) { bSuccess = bSuccess && FromStringBlob( JsonAppID->AsString(), Data->AppID ); } bSuccess = bSuccess && JsonAppNameString.IsValid(); if( bSuccess ) { Data->AppName = JsonAppNameString->AsString(); } bSuccess = bSuccess && JsonBuildVersionString.IsValid(); if( bSuccess ) { Data->BuildVersion = JsonBuildVersionString->AsString(); } bSuccess = bSuccess && JsonLaunchExe.IsValid(); if( bSuccess ) { Data->LaunchExe = JsonLaunchExe->AsString(); } bSuccess = bSuccess && JsonLaunchCommand.IsValid(); if( bSuccess ) { Data->LaunchCommand = JsonLaunchCommand->AsString(); } // Get the prerequisites installer info. These are optional entries. Data->PrereqName = JsonPrereqName.IsValid() ? JsonPrereqName->AsString() : FString(); Data->PrereqPath = JsonPrereqPath.IsValid() ? JsonPrereqPath->AsString() : FString(); Data->PrereqArgs = JsonPrereqArgs.IsValid() ? JsonPrereqArgs->AsString() : FString(); // Get the FileManifestList TSharedPtr<FJsonValue> JsonFileManifestList = JsonValueMap.FindRef(TEXT("FileManifestList")); bSuccess = bSuccess && JsonFileManifestList.IsValid(); if( bSuccess ) { TArray<TSharedPtr<FJsonValue>> JsonFileManifestArray = JsonFileManifestList->AsArray(); for (auto JsonFileManifestIt = JsonFileManifestArray.CreateConstIterator(); JsonFileManifestIt && bSuccess; ++JsonFileManifestIt) { TSharedPtr<FJsonObject> JsonFileManifest = (*JsonFileManifestIt)->AsObject(); const int32 FileIndex = Data->FileManifestList.Add(FFileManifestData()); FFileManifestData& FileManifest = Data->FileManifestList[FileIndex]; FileManifest.Filename = JsonFileManifest->GetStringField(TEXT("Filename")); bSuccess = bSuccess && FString::ToBlob(JsonFileManifest->GetStringField(TEXT("FileHash")), FileManifest.FileHash.Hash, FSHA1::DigestSize); TArray<TSharedPtr<FJsonValue>> JsonChunkPartArray = JsonFileManifest->GetArrayField(TEXT("FileChunkParts")); for (auto JsonChunkPartIt = JsonChunkPartArray.CreateConstIterator(); JsonChunkPartIt && bSuccess; ++JsonChunkPartIt) { const int32 ChunkIndex = FileManifest.FileChunkParts.Add(FChunkPartData()); FChunkPartData& FileChunkPart = FileManifest.FileChunkParts[ChunkIndex]; TSharedPtr<FJsonObject> JsonChunkPart = (*JsonChunkPartIt)->AsObject(); bSuccess = bSuccess && FGuid::Parse(JsonChunkPart->GetStringField(TEXT("Guid")), FileChunkPart.Guid); bSuccess = bSuccess && FromStringBlob(JsonChunkPart->GetStringField(TEXT("Offset")), FileChunkPart.Offset); bSuccess = bSuccess && FromStringBlob(JsonChunkPart->GetStringField(TEXT("Size")), FileChunkPart.Size); AllDataGuids.Add(FileChunkPart.Guid); } FileManifest.bIsUnixExecutable = JsonFileManifest->HasField(TEXT("bIsUnixExecutable")) && JsonFileManifest->GetBoolField(TEXT("bIsUnixExecutable")); FileManifest.bIsReadOnly = JsonFileManifest->HasField(TEXT("bIsReadOnly")) && JsonFileManifest->GetBoolField(TEXT("bIsReadOnly")); FileManifest.bIsCompressed = JsonFileManifest->HasField(TEXT("bIsCompressed")) && JsonFileManifest->GetBoolField(TEXT("bIsCompressed")); FileManifest.SymlinkTarget = JsonFileManifest->HasField(TEXT("SymlinkTarget")) ? JsonFileManifest->GetStringField(TEXT("SymlinkTarget")) : TEXT(""); FileManifest.Init(); } } Data->FileManifestList.Sort(); for (auto& FileManifest : Data->FileManifestList) { FileManifestLookup.Add(FileManifest.Filename, &FileManifest); } // For each chunk setup it's info for (const auto& DataGuid : AllDataGuids) { int32 ChunkIndex = Data->ChunkList.Add(FChunkInfoData()); Data->ChunkList[ChunkIndex].Guid = DataGuid; } // Setup chunk info lookup for (auto& ChunkInfo : Data->ChunkList) { ChunkInfoLookup.Add(ChunkInfo.Guid, &ChunkInfo); } // Get the ChunkHashList bool bHasChunkHashList = false; TSharedPtr<FJsonValue> JsonChunkHashList = JsonValueMap.FindRef(TEXT("ChunkHashList")); bSuccess = bSuccess && JsonChunkHashList.IsValid(); if (bSuccess) { TSharedPtr<FJsonObject> JsonChunkHashListObj = JsonChunkHashList->AsObject(); for (auto ChunkHashIt = JsonChunkHashListObj->Values.CreateConstIterator(); ChunkHashIt && bSuccess; ++ChunkHashIt) { FGuid ChunkGuid; uint64 ChunkHash = 0; bSuccess = bSuccess && FGuid::Parse(ChunkHashIt.Key(), ChunkGuid); bSuccess = bSuccess && FromStringBlob(ChunkHashIt.Value()->AsString(), ChunkHash); if (bSuccess && ChunkInfoLookup.Contains(ChunkGuid)) { FChunkInfoData* ChunkInfoData = ChunkInfoLookup[ChunkGuid]; ChunkInfoData->Hash = ChunkHash; bHasChunkHashList = true; } } } // Get the DataGroupList TSharedPtr<FJsonValue> JsonDataGroupList = JsonValueMap.FindRef(TEXT("DataGroupList")); if (JsonDataGroupList.IsValid()) { TSharedPtr<FJsonObject> JsonDataGroupListObj = JsonDataGroupList->AsObject(); for (auto DataGroupIt = JsonDataGroupListObj->Values.CreateConstIterator(); DataGroupIt && bSuccess; ++DataGroupIt) { FGuid DataGuid; uint8 DataGroup = INDEX_NONE; // If the list exists, we must be able to parse it ok otherwise error bSuccess = bSuccess && FGuid::Parse(DataGroupIt.Key(), DataGuid); bSuccess = bSuccess && FromStringBlob(DataGroupIt.Value()->AsString(), DataGroup); if (bSuccess && ChunkInfoLookup.Contains(DataGuid)) { FChunkInfoData* ChunkInfoData = ChunkInfoLookup[DataGuid]; ChunkInfoData->GroupNumber = DataGroup; } } } else if (bSuccess) { // If the list did not exist in the manifest then the grouping is the deprecated crc functionality, as long // as there are no previous parsing errors we can build the group list from the Guids. for (auto& ChunkInfo : Data->ChunkList) { ChunkInfo.GroupNumber = FCrc::MemCrc_DEPRECATED(&ChunkInfo.Guid, sizeof(FGuid)) % 100; } } // Get the ChunkFilesizeList bool bHasChunkFilesizeList = false; TSharedPtr< FJsonValue > JsonChunkFilesizeList = JsonValueMap.FindRef(TEXT("ChunkFilesizeList")); if (JsonChunkFilesizeList.IsValid()) { TSharedPtr< FJsonObject > JsonChunkFilesizeListObj = JsonChunkFilesizeList->AsObject(); for (auto ChunkFilesizeIt = JsonChunkFilesizeListObj->Values.CreateConstIterator(); ChunkFilesizeIt; ++ChunkFilesizeIt) { FGuid ChunkGuid; int64 ChunkSize = 0; if (FGuid::Parse(ChunkFilesizeIt.Key(), ChunkGuid)) { FromStringBlob(ChunkFilesizeIt.Value()->AsString(), ChunkSize); if (ChunkInfoLookup.Contains(ChunkGuid)) { FChunkInfoData* ChunkInfoData = ChunkInfoLookup[ChunkGuid]; ChunkInfoData->FileSize = ChunkSize; bHasChunkFilesizeList = true; } } } } if (bHasChunkFilesizeList == false) { // Missing chunk list, version before we saved them compressed.. Assume chunk size for (FChunkInfoData& ChunkInfo : Data->ChunkList) { ChunkInfo.FileSize = FBuildPatchData::ChunkDataSize; } } // Get the bIsFileData value. The variable will exist in versions of StoresIfChunkOrFileData or later, otherwise the previous method is to check // if ChunkHashList is empty. TSharedPtr<FJsonValue> JsonIsFileData = JsonValueMap.FindRef(TEXT("bIsFileData")); if (JsonIsFileData.IsValid() && JsonIsFileData->Type == EJson::Boolean) { Data->bIsFileData = JsonIsFileData->AsBool(); } else { Data->bIsFileData = !bHasChunkHashList; } // Get the custom fields. This is optional, and should not fail if it does not exist TSharedPtr< FJsonValue > JsonCustomFields = JsonValueMap.FindRef( TEXT( "CustomFields" ) ); if( JsonCustomFields.IsValid() ) { TSharedPtr< FJsonObject > JsonCustomFieldsObj = JsonCustomFields->AsObject(); for( auto CustomFieldIt = JsonCustomFieldsObj->Values.CreateConstIterator(); CustomFieldIt && bSuccess; ++CustomFieldIt ) { Data->CustomFields.Add(FCustomFieldData(CustomFieldIt.Key(), CustomFieldIt.Value()->AsString())); } } CustomFieldLookup.Empty(Data->CustomFields.Num()); for (auto& CustomField : Data->CustomFields) { CustomFieldLookup.Add(CustomField.Key, &CustomField); } // If this is file data, fill out the guid to filename lookup, and chunk file size if (Data->bIsFileData) { for (auto& FileManifest : Data->FileManifestList) { if (FileManifest.FileChunkParts.Num() == 1) { FGuid& Guid = FileManifest.FileChunkParts[0].Guid; FileNameLookup.Add(Guid, &FileManifest.Filename); if (ChunkInfoLookup.Contains(Guid)) { FChunkInfoData* ChunkInfoData = ChunkInfoLookup[Guid]; ChunkInfoData->FileSize = FileManifest.GetFileSize(); } } else { bSuccess = false; } } } // Calculate build size TotalBuildSize = 0; TotalDownloadSize = 0; if (bSuccess) { for (auto& FileManifest : Data->FileManifestList) { TotalBuildSize += FileManifest.GetFileSize(); } for (auto& Chunk : Data->ChunkList) { TotalDownloadSize += Chunk.FileSize; } } // Mark as should be re-saved, client that stores manifests should start using binary bNeedsResaving = true; // Make sure we don't have any half loaded data if( !bSuccess ) { DestroyData(); } return bSuccess; }
bool FModuleDescriptor::Read(const FJsonObject& Object, FText& OutFailReason) { // Read the module name TSharedPtr<FJsonValue> NameValue = Object.TryGetField(TEXT("Name")); if(!NameValue.IsValid() || NameValue->Type != EJson::String) { OutFailReason = LOCTEXT("ModuleWithoutAName", "Found a 'Module' entry with a missing 'Name' field"); return false; } Name = FName(*NameValue->AsString()); // Read the module type TSharedPtr<FJsonValue> TypeValue = Object.TryGetField(TEXT("Type")); if(!TypeValue.IsValid() || TypeValue->Type != EJson::String) { OutFailReason = FText::Format( LOCTEXT( "ModuleWithoutAType", "Found Module entry '{0}' with a missing 'Type' field" ), FText::FromName(Name) ); return false; } Type = EHostType::FromString(*TypeValue->AsString()); if(Type == EHostType::Max) { OutFailReason = FText::Format( LOCTEXT( "ModuleWithInvalidType", "Module entry '{0}' specified an unrecognized module Type '{1}'" ), FText::FromName(Name), FText::FromString(TypeValue->AsString()) ); return false; } // Read the loading phase TSharedPtr<FJsonValue> LoadingPhaseValue = Object.TryGetField(TEXT("LoadingPhase")); if(LoadingPhaseValue.IsValid() && LoadingPhaseValue->Type == EJson::String) { LoadingPhase = ELoadingPhase::FromString(*LoadingPhaseValue->AsString()); if(LoadingPhase == ELoadingPhase::Max) { OutFailReason = FText::Format( LOCTEXT( "ModuleWithInvalidLoadingPhase", "Module entry '{0}' specified an unrecognized module LoadingPhase '{1}'" ), FText::FromName(Name), FText::FromString(LoadingPhaseValue->AsString()) ); return false; } } // Read the whitelisted platforms TSharedPtr<FJsonValue> WhitelistPlatformsValue = Object.TryGetField(TEXT("WhitelistPlatforms")); if(WhitelistPlatformsValue.IsValid() && WhitelistPlatformsValue->Type == EJson::Array) { const TArray< TSharedPtr< FJsonValue > >& PlatformsArray = WhitelistPlatformsValue->AsArray(); for(int Idx = 0; Idx < PlatformsArray.Num(); Idx++) { WhitelistPlatforms.Add(PlatformsArray[Idx]->AsString()); } } // Read the blacklisted platforms TSharedPtr<FJsonValue> BlacklistPlatformsValue = Object.TryGetField(TEXT("BlacklistPlatforms")); if(BlacklistPlatformsValue.IsValid() && BlacklistPlatformsValue->Type == EJson::Array) { const TArray< TSharedPtr< FJsonValue > >& PlatformsArray = BlacklistPlatformsValue->AsArray(); for(int Idx = 0; Idx < PlatformsArray.Num(); Idx++) { BlacklistPlatforms.Add(PlatformsArray[Idx]->AsString()); } } // Read the additional dependencies TSharedPtr<FJsonValue> AdditionalDependenciesValue = Object.TryGetField(TEXT("AdditionalDependencies")); if (AdditionalDependenciesValue.IsValid() && AdditionalDependenciesValue->Type == EJson::Array) { const TArray< TSharedPtr< FJsonValue > >& DepArray = AdditionalDependenciesValue->AsArray(); for (int Idx = 0; Idx < DepArray.Num(); Idx++) { AdditionalDependencies.Add(DepArray[Idx]->AsString()); } } return true; }