Пример #1
0
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());
	}
}
Пример #4
0
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());
		
	}
}
Пример #6
0
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;
}
Пример #7
0
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);
}
Пример #8
0
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;
			}
		}
	}
}
Пример #10
0
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();
		}
	}
}
Пример #11
0
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
				]
			];
		}
	}
}
Пример #12
0
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);
	}
}
Пример #13
0
// @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;
}
Пример #14
0
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;
}