FString FChunkManifestGenerator::CreateCookerFileOrderString(const TMap<FName, FAssetData*>& InAssetData, const TArray<FName>& InMaps)
{
	FString FileOrderString;
	TArray<FAssetData*> TopLevelNodes;

	for (auto Asset : InAssetData)
	{
		auto PackageName = Asset.Value->PackageName;
		TArray<FName> Referencers;
		AssetRegistry.GetReferencers(PackageName, Referencers);

		bool bIsTopLevel = true;
		bool bIsMap = InMaps.Contains(PackageName);

		if (!bIsMap && Referencers.Num() > 0)
		{
			for (auto ReferencerName : Referencers)
			{
				if (InAssetData.Contains(ReferencerName))
				{
					bIsTopLevel = false;
					break;
				}
			}
		}

		if (bIsTopLevel)
		{
			if (bIsMap)
			{
				TopLevelNodes.Insert(Asset.Value, 0);
			}
			else
			{
				TopLevelNodes.Insert(Asset.Value, TopLevelNodes.Num());
			}
		}
	}

	TArray<FName> FileOrder;
	TArray<FName> EncounteredNames;
	for (auto Asset : TopLevelNodes)
	{
		AddAssetToFileOrderRecursive(Asset, FileOrder, EncounteredNames, InAssetData, InMaps);
	}

	int32 CurrentIndex = 0;
	for (auto PackageName : FileOrder)
	{
		auto Asset = InAssetData[PackageName];
		bool bIsMap = InMaps.Contains(Asset->PackageName);
		auto Filename = FPackageName::LongPackageNameToFilename(Asset->PackageName.ToString(), bIsMap ? FPackageName::GetMapPackageExtension() : FPackageName::GetAssetPackageExtension());

		ConvertFilenameToPakFormat(Filename);
		auto Line = FString::Printf(TEXT("\"%s\" %i\n"), *Filename, CurrentIndex++);
		FileOrderString.Append(Line);
	}

	return FileOrderString;
}
/**
 * Returns true if the specified level is locked for edit, false otherwise.
 *
 * @param	Level		The level to query.
 * @return				true if the level is locked, false otherwise.
 */
bool FLevelUtils::IsLevelLocked(ULevel* Level)
{
//We should not check file status on disk if we are not running the editor
#if WITH_EDITOR
	// Don't permit spawning in read only levels if they are locked
	if ( GIsEditor && !GIsEditorLoadingPackage )
	{
		if ( GEngine && GEngine->bLockReadOnlyLevels )
		{
			if (!LevelReadOnlyCache.Contains(Level))
			{
				LevelReadOnlyCache.Add(Level, FLevelReadOnlyData());
			}
			check(LevelReadOnlyCache.Contains(Level));
			FLevelReadOnlyData &LevelData = LevelReadOnlyCache[Level];
			//Make sure we test if the level file on disk is readonly only once a frame,
			//when the frame time get updated.
			if (LevelData.LastUpdateTime < Level->OwningWorld->GetRealTimeSeconds())
			{
				LevelData.LastUpdateTime = Level->OwningWorld->GetRealTimeSeconds();
				//If we dont find package we dont consider it as readonly
				LevelData.IsReadOnly = false;
				const UPackage* pPackage = Cast<UPackage>(Level->GetOutermost());
				if (pPackage)
				{
					FString PackageFileName;
					if (FPackageName::DoesPackageExist(pPackage->GetName(), NULL, &PackageFileName))
					{
						LevelData.IsReadOnly = IFileManager::Get().IsReadOnly(*PackageFileName);
					}
				}
			}

			if (LevelData.IsReadOnly)
			{
				return true;
			}
		}
	}
#endif //#if WITH_EDITOR

	// PIE levels, the persistent level, and transient move levels are usually never locked.
	if ( Level->RootPackageHasAnyFlags(PKG_PlayInEditor) || Level->IsPersistentLevel() || Level->GetName() == TEXT("TransLevelMoveBuffer") )
	{
		return false;
	}

	ULevelStreaming* StreamingLevel = FindStreamingLevel( Level );
	if ( StreamingLevel != NULL )
	{
		return StreamingLevel->bLocked;
	}
	else
	{
		return Level->bLocked;
	}
}
		virtual bool Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory) override
		{
			auto Filename = FString(FilenameOrDirectory);
			if (!Filename.EndsWith(".cpp.includes"))
			{
				return true;
			}

			++FileCount;
			TSet<FString> IncludePaths;
			FString FileContents;
			TArray<FString> OutStrings;
			FFileHelper::LoadANSITextFileToStrings(*Filename, &IFileManager::Get(), OutStrings);
			IncludePaths.Reserve(OutStrings.Num());
			for (auto& IncludePath : OutStrings)
			{
				IncludePaths.Add(MoveTemp(IncludePath));
			}

			for (const auto& IncludePath : IncludePaths)
			{
				if (!IncludeHeaderCount.Contains(IncludePath))
				{
					IncludeHeaderCount.Add(IncludePath, 1);
				}
				else
				{
					++IncludeHeaderCount[IncludePath];
				}
			}
			return true;
		}
void UFaceFXMatineeControl::GetTrackKeyForTime(float InTime, TArray<TPair<int32, const FFaceFXTrackKey*>>& OutResult, TArray<FFaceFXSkelMeshComponentId>* OutNoTracks) const
{
	//build a list of all keys for all skelmesh component ids
	TMap<int32, TArray<const FFaceFXTrackKey*>> SkelMeshTracks;
	TMap<int32, FFaceFXSkelMeshComponentId> SkelMeshIds;
	for(const FFaceFXTrackKey& Key : Keys)
	{
		SkelMeshTracks.FindOrAdd(Key.SkelMeshComponentId.Index).Add(&Key);
		if(OutNoTracks && !SkelMeshIds.Contains(Key.SkelMeshComponentId.Index))
		{
			SkelMeshIds.Add(Key.SkelMeshComponentId.Index, Key.SkelMeshComponentId);
		}
	}

	//then generate the pair results for each skelmesh component
	for(auto It = SkelMeshTracks.CreateConstIterator(); It; ++It)
	{
		const TArray<const FFaceFXTrackKey*>& SkelMeshKeys = It.Value();

		const int32 IndexMax = SkelMeshKeys.Num()-1;
		int32 Index = INDEX_NONE;
		for(; Index < IndexMax && SkelMeshKeys[Index+1]->Time <= InTime; ++Index);

		if(Index != INDEX_NONE)
		{
			OutResult.Add(TPairInitializer<int32, const FFaceFXTrackKey*>(Index, SkelMeshKeys[Index]));
		}
		else if(OutNoTracks)
		{
			OutNoTracks->Add(SkelMeshIds.FindChecked(It.Key()));
		}
	}
}
void FSourceControlSettings::LoadSettings()
{
	// make sure we load the global ini first
	const FString& GlobalIniFile = SourceControlHelpers::GetGlobalSettingsIni();
	GConfig->GetBool(*SourceControlSettingsConstants::SettingsSection, TEXT("UseGlobalSettings"), bUseGlobalSettings, GlobalIniFile);

	TArray<FString> Tokens;
	TArray<FString> Switches;
	FCommandLine::Parse( FCommandLine::Get(), Tokens, Switches );
	TMap<FString, FString> SwitchPairs;
	for (int32 SwitchIdx = Switches.Num() - 1; SwitchIdx >= 0; --SwitchIdx)
	{
		FString& Switch = Switches[SwitchIdx];
		TArray<FString> SplitSwitch;
		if (2 == Switch.ParseIntoArray(SplitSwitch, TEXT("="), true))
		{
			SwitchPairs.Add(SplitSwitch[0], SplitSwitch[1].TrimQuotes());
			Switches.RemoveAt(SwitchIdx);
		}
	}

	if( SwitchPairs.Contains( TEXT("SCCProvider") ) )
	{
		Provider = SwitchPairs[TEXT("SCCProvider")];
	}
	else
	{
		const FString& IniFile = SourceControlHelpers::GetSettingsIni();
		GConfig->GetString(*SourceControlSettingsConstants::SettingsSection, TEXT("Provider"), Provider, IniFile);
	}
}
	bool FDataScannerImpl::FindExistingChunk(const TMap<uint64, TSet<FGuid>>& ChunkLookup, TMap<FGuid, FSHAHash>& ChunkShaHashes, uint64 ChunkHash, const FRollingHash<WindowSize>& RollingHash, FGuid& OutMatchedChunk)
	{
		FStatsScopedTimer FindTimer(StatFindMatchTime);
		bool bFoundChunkMatch = false;
		if (ChunkLookup.Contains(ChunkHash))
		{
			FSHAHash ChunkSha;
			RollingHash.GetWindowData().GetShaHash(ChunkSha);
			for (FGuid& PotentialMatch : ChunkLookup.FindRef(ChunkHash))
			{
				// Use sha if we have it
				if (ChunkShaHashes.Contains(PotentialMatch))
				{
					if(ChunkSha == ChunkShaHashes[PotentialMatch])
					{
						bFoundChunkMatch = true;
						OutMatchedChunk = PotentialMatch;
						break;
					}
				}
				else
				{
					// Otherwise compare data
					TArray<uint8> SerialBuffer;
					FStatsScopedTimer DataMatchTimer(StatDataMatchTime);
					FStatsCollector::Accumulate(StatChunkDataChecks, 1);
					SerialBuffer.AddUninitialized(WindowSize);
					RollingHash.GetWindowData().Serialize(SerialBuffer.GetData());
					bool ChunkFound = false;
					if (DataMatcher->CompareData(PotentialMatch, ChunkHash, SerialBuffer, ChunkFound))
					{
						FStatsCollector::Accumulate(StatChunkDataMatches, 1);
						ChunkShaHashes.Add(PotentialMatch, ChunkSha);
						bFoundChunkMatch = true;
						OutMatchedChunk = PotentialMatch;
						break;
					}
					else if(!ChunkFound)
					{
						FStatsCollector::Accumulate(StatMissingChunks, 1);
					}
				}
				FStatsCollector::Accumulate(StatHashCollisions, 1);
			}
		}
		return bFoundChunkMatch;
	}
Exemple #7
0
/******************** HasResourcesAvailable *************************/
bool APOTLStructure::HasResourcesAvailable(TMap<FString, int32>& Request, bool IncludeAllocations, int32 Sequence)
{
	bool RequestMet = true;
	TMap<FString, int32> ResourceAvailable = FreeResources; //~~ Copy resources ~~//
	//~~ Append all allocated resources  with lower sequence to available resources ~~//

	if (IncludeAllocations) 
	{
		for (auto& AllocatedResource : AllocatedResources)
		{
			FST_ResourceAllocation& Allocation = AllocatedResource.Value;
			if (Allocation.Sequence < Sequence && Allocation.Type == EAllocationType::FactoryProduction && Allocation.To == this && Allocation.Quantity > 0) //~~ If allocation has a lower sequence than the check and is allocated to this structure ~~//
			{
				if (ResourceAvailable.Contains(Allocation.ResourceKey))		ResourceAvailable[Allocation.ResourceKey] = ResourceAvailable[Allocation.ResourceKey] + Allocation.Quantity;
				else														ResourceAvailable.Add(Allocation.ResourceKey, Allocation.Quantity);
			}
		}
	}

	

	for (auto& ResourceRequest : Request)
	{
		if (ResourceAvailable.Contains(ResourceRequest.Key))
		{
			int32 Remaining = ResourceRequest.Value;
			if (Remaining > ResourceAvailable[ResourceRequest.Key]) //~~ If request is larger than the resource pool ~~//
			{
				RequestMet = false;
				break;
			}
		}
		else
		{
			RequestMet = false;
			break;
		}
	}
	return RequestMet;
}
// DEPRECATED
void ADEPRECATED_VolumeAdaptiveBuilder::ExpandFrontierTowardsTarget(UDoNNavigationVolumeComponent* current, UDoNNavigationVolumeComponent* neighbor, DoNNavigation::PriorityQueue<UDoNNavigationVolumeComponent*> &frontier, TMap<UDoNNavigationVolumeComponent*, FVector> &entryPointMap, bool &goalFound, UDoNNavigationVolumeComponent* start, UDoNNavigationVolumeComponent* goal, FVector origin, FVector destination, TMap<UDoNNavigationVolumeComponent*, int>& VolumeVsCostMap, bool DrawDebug, TMap<UDoNNavigationVolumeComponent*, TArray<UDoNNavigationVolumeComponent*>> &PathVolumeSolutionMap)
{		
	if (DrawDebug)
	{		
		DisplayDebugVolume(current, FColor::Red);
		DisplayDebugVolume(neighbor, FColor::Blue);
	}
	float SegmentDist = 0;
	FVector nextEntryPoint;

	TArray<UDoNNavigationVolumeComponent*> PathSolutionSoFar = PathVolumeSolutionMap.FindOrAdd(current);
	
	nextEntryPoint = NavEntryPointsForTraversal(*entryPointMap.Find(current), current, neighbor, SegmentDist, DrawDebug);

	entryPointMap.Add(neighbor, nextEntryPoint);

	if (nextEntryPoint == *entryPointMap.Find(current)) // i.e. no traversal solution exists
	{
		if (DrawDebug)
		{
			DisplayDebugVolume(current, FColor::Red);
			DisplayDebugVolume(neighbor, FColor::Blue);
		}

		UE_LOG(LogTemp, Log, TEXT("Skipping neighbor due to lack of traversal solution"));
		return;
	}

	//int new_cost = *VolumeVsCostMap.Find(current) + graph.cost(current, next);
	int new_cost = *VolumeVsCostMap.Find(current) + SegmentDist;

	if (!VolumeVsCostMap.Contains(neighbor) || new_cost < *VolumeVsCostMap.Find(neighbor))
	{	
		PathSolutionSoFar.Add(neighbor);
		PathVolumeSolutionMap.Add(neighbor, PathSolutionSoFar);
		VolumeVsCostMap.Add(neighbor, new_cost);

		float heuristic = FVector::Dist(nextEntryPoint, destination);
		int priority = new_cost + heuristic;

		if (DrawDebug)
		{
			DrawDebugLine(GetWorld(), nextEntryPoint, destination, FColor::Red, true, -1.f, 0, 10.f);
			FString priorityText = FString::Printf(TEXT("Priority: %d"), priority);
			UE_LOG(LogTemp, Log, TEXT("%s"), *priorityText);
		}			

		frontier.put(neighbor, priority);		
	}
}
FName FNativeClassHierarchy::GetClassPathRootForModule(const FName& InModuleName, const TSet<FName>& InGameModules, const TMap<FName, FName>& InPluginModules)
{
	static const FName EngineRootNodeName = "Classes_Engine";
	static const FName GameRootNodeName = "Classes_Game";

	// Work out which root this class should go under (anything that isn't a game or plugin module goes under engine)
	FName RootNodeName = EngineRootNodeName;
	if(InGameModules.Contains(InModuleName))
	{
		RootNodeName = GameRootNodeName;
	}
	else if(InPluginModules.Contains(InModuleName))
	{
		const FName PluginName = InPluginModules.FindRef(InModuleName);
		RootNodeName = FName(*(FString(TEXT("Classes_")) + PluginName.ToString()));
	}

	return RootNodeName;
}
	// Determine whether or not scene components in the new object set can be attached to the given scene root component
	bool CanAttachComponentsTo(USceneComponent* InRootComponent)
	{
		check(InRootComponent);

		// For each component in the set, check against the given root component and break if we fail to validate
		bool bCanAttachToRoot = true;
		for (auto NewComponentIt = NewObjectMap.CreateConstIterator(); NewComponentIt && bCanAttachToRoot; ++NewComponentIt)
		{
			// If this is a scene component, and it does not already have a parent within the set
			USceneComponent* SceneComponent = Cast<USceneComponent>(NewComponentIt->Value);
			if (SceneComponent != NULL && !ParentMap.Contains(SceneComponent->GetFName()))
			{
				// Determine if we are allowed to attach the scene component to the given root component
				bCanAttachToRoot = InRootComponent->CanAttachAsChild(SceneComponent, NAME_None)
					&& SceneComponent->Mobility >= InRootComponent->Mobility
					&& ( !InRootComponent->IsEditorOnly() || SceneComponent->IsEditorOnly() );
			}
		}

		return bCanAttachToRoot;
	}
void FChunkManifestGenerator::AddAssetToFileOrderRecursive(FAssetData* InAsset, TArray<FName>& OutFileOrder, TArray<FName>& OutEncounteredNames, const TMap<FName, FAssetData*>& InAssets, const TArray<FName>& InMapList)
{
	if (!OutEncounteredNames.Contains(InAsset->PackageName))
	{
		OutEncounteredNames.Add(InAsset->PackageName);

		TArray<FName> Dependencies;
		AssetRegistry.GetDependencies(InAsset->PackageName, Dependencies);

		for (auto DependencyName : Dependencies)
		{
			if (InAssets.Contains(DependencyName) && !OutFileOrder.Contains(DependencyName))
			{
				if (!InMapList.Contains(DependencyName))
				{
					auto Dependency = InAssets[DependencyName];
					AddAssetToFileOrderRecursive(Dependency, OutFileOrder, OutEncounteredNames, InAssets, InMapList);
				}
			}
		}

		OutFileOrder.Add(InAsset->PackageName);
	}
}
Exemple #12
0
/******************** GetResourceAlteration *************************/
TArray<FST_ResourceAlteration> APOTLStructure::GetResourceAlteration()
{
	TArray<FST_ResourceAlteration> List;
	TMap<FString, FST_ResourceAlteration> TMapList; //~~ Make complete list of resource from FreeResources and allocations ~~//
	for (auto& FreeResource : FreeResources)
	{
		FST_ResourceAlteration ResourceAlteration;
		ResourceAlteration.Id = FreeResource.Key;
		ResourceAlteration.Storage = FreeResource.Value;
		//ResourceAlteration.Alteration = GetAllocationTotal(FreeResource.Key);
		TMapList.Add(FreeResource.Key, ResourceAlteration);
	}
	for (auto& AllocatedResource : AllocatedResources)
	{
		//~~ Add alteration if allocation key isn't in free resources ~~//
		if (AllocatedResource.Value.From == this || AllocatedResource.Value.To == this) //~~~ If either outgoing or incomming, then create an alteration struct  ~~//
		{
			if (!TMapList.Contains(AllocatedResource.Value.ResourceKey))
			{
				FST_ResourceAlteration ResourceAlteration;
				ResourceAlteration.Id = AllocatedResource.Value.ResourceKey;
				TMapList.Add(AllocatedResource.Value.ResourceKey, ResourceAlteration);
			}
		}
		//~~ Outgoing resources from root ~~//
		if (AllocatedResource.Value.From == this) 
		{
			if (AllocatedResource.Value.Type == EAllocationType::Decay)
			{
				TMapList[AllocatedResource.Value.ResourceKey].Decay -= AllocatedResource.Value.Quantity;
				TMapList[AllocatedResource.Value.ResourceKey].Storage += AllocatedResource.Value.Quantity;
			}
			else if (AllocatedResource.Value.Type == EAllocationType::FactoryBilling)
			{
				TMapList[AllocatedResource.Value.ResourceKey].Alteration -= AllocatedResource.Value.Quantity;
				TMapList[AllocatedResource.Value.ResourceKey].Storage += AllocatedResource.Value.Quantity;
			}
		}
		//~~ Incomming resources to root ~~//
		if (AllocatedResource.Value.To == this) 
		{ 
			if (AllocatedResource.Value.Type == EAllocationType::ProductionDecay)
			{
				TMapList[AllocatedResource.Value.ResourceKey].Alteration += AllocatedResource.Value.Quantity;
				TMapList[AllocatedResource.Value.ResourceKey].Decay -= AllocatedResource.Value.Quantity;
			}
			else
			{
				TMapList[AllocatedResource.Value.ResourceKey].Alteration += AllocatedResource.Value.Quantity;
			}
		}
	}
	/*
	if (TMapList.Contains(AllocatedResource.Value.ResourceKey))
	{
		if (AllocatedResource.Value.Type == EAllocationType::FactoryBilling)
		{
			TMapList[AllocatedResource.Value.ResourceKey].Storage = TMapList[AllocatedResource.Value.ResourceKey].Storage + TMapList[AllocatedResource.Value.ResourceKey].Alteration;
		}
	}
	else
	{
		FST_ResourceAlteration ResourceAlteration;
		ResourceAlteration.Id = AllocatedResource.Value.ResourceKey;
		ResourceAlteration.Alteration = GetAllocationTotal(AllocatedResource.Value.ResourceKey);
		TMapList.Add(AllocatedResource.Value.ResourceKey, ResourceAlteration);
	}
	*/
	for (auto& TMapItem : TMapList)
	{
		List.Add(TMapItem.Value);
	}
	//~~ Sort the list by sort sequence ~~//
	/*
	List.Sort([](const FString& One, const FString& Two) {
		return One > Two;
	});
	List.Sort([](const FString& A, const FString& B) {
		return A.Len() < B.Len();
	});
	*/

	//GameInstance->DATA_Recipes

	List.Sort([](const FST_ResourceAlteration& A, const FST_ResourceAlteration& B) {
		return A.Id.Len() < B.Id.Len();
		//return A.Id.Len() < B.Id.Len();
	});

	//List.Sort();
	return List;
}
void FComponentEditorUtils::CopyComponents(const TArray<UActorComponent*>& ComponentsToCopy)
{
	FStringOutputDevice Archive;
	const FExportObjectInnerContext Context;

	// Clear the mark state for saving.
	UnMarkAllObjects(EObjectMark(OBJECTMARK_TagExp | OBJECTMARK_TagImp));

	// Duplicate the selected component templates into temporary objects that we can modify
	TMap<FName, FName> ParentMap;
	TMap<FName, UActorComponent*> ObjectMap;
	for (UActorComponent* Component : ComponentsToCopy)
	{
		// Duplicate the component into a temporary object
		UObject* DuplicatedComponent = StaticDuplicateObject(Component, GetTransientPackage(), Component->GetFName(), RF_AllFlags & ~RF_ArchetypeObject);
		if (DuplicatedComponent)
		{
			// If the duplicated component is a scene component, wipe its attach parent (to prevent log warnings for referencing a private object in an external package)
			if (auto DuplicatedCompAsSceneComp = Cast<USceneComponent>(DuplicatedComponent))
			{
				DuplicatedCompAsSceneComp->AttachParent = nullptr;
			}

			// Find the closest parent component of the current component within the list of components to copy
			USceneComponent* ClosestSelectedParent = FindClosestParentInList(Component, ComponentsToCopy);
			if (ClosestSelectedParent)
			{
				// If the parent is included in the list, record it into the node->parent map
				ParentMap.Add(Component->GetFName(), ClosestSelectedParent->GetFName());
			}

			// Record the temporary object into the name->object map
			ObjectMap.Add(Component->GetFName(), CastChecked<UActorComponent>(DuplicatedComponent));
		}
	}

	// Export the component object(s) to text for copying
	for (auto ObjectIt = ObjectMap.CreateIterator(); ObjectIt; ++ObjectIt)
	{
		// Get the component object to be copied
		UActorComponent* ComponentToCopy = ObjectIt->Value;
		check(ComponentToCopy);

		// If this component object had a parent within the selected set
		if (ParentMap.Contains(ComponentToCopy->GetFName()))
		{
			// Get the name of the parent component
			FName ParentName = ParentMap[ComponentToCopy->GetFName()];
			if (ObjectMap.Contains(ParentName))
			{
				// Ensure that this component is a scene component
				USceneComponent* SceneComponent = Cast<USceneComponent>(ComponentToCopy);
				if (SceneComponent)
				{
					// Set the attach parent to the matching parent object in the temporary set. This allows us to preserve hierarchy in the copied set.
					SceneComponent->AttachParent = Cast<USceneComponent>(ObjectMap[ParentName]);
				}
			}
		}

		// Export the component object to the given string
		UExporter::ExportToOutputDevice(&Context, ComponentToCopy, NULL, Archive, TEXT("copy"), 0, PPF_ExportsNotFullyQualified | PPF_Copy | PPF_Delimited, false, ComponentToCopy->GetOuter());
	}

	// Copy text to clipboard
	FString ExportedText = Archive;
	FPlatformMisc::ClipboardCopy(*ExportedText);
}
	bool FFileAttributesParserImpl::FileAttributesMetaToMap(const FString& AttributesList, TMap<FString, FFileAttributes>& FileAttributesMap)
	{
		const TCHAR Quote = TEXT('\"');
		const TCHAR EOFile = TEXT('\0');
		const TCHAR EOLine = TEXT('\n');

		bool Successful = true;
		bool FoundFilename = false;

		const TCHAR* CharPtr = *AttributesList;
		while (*CharPtr != EOFile)
		{
			// Parse filename
			while (*CharPtr != Quote && *CharPtr != EOFile){ ++CharPtr; }
			if (*CharPtr == EOFile)
			{
				if (!FoundFilename)
				{
					UE_LOG(LogFileAttributesParser, Error, TEXT("Did not find opening quote for filename!"));
					return false;
				}
				break;
			}
			const TCHAR* FilenameStart = ++CharPtr;
			while (*CharPtr != Quote && *CharPtr != EOFile && *CharPtr != EOLine){ ++CharPtr; }
			// Check we didn't run out of file
			if (*CharPtr == EOFile)
			{
				UE_LOG(LogFileAttributesParser, Error, TEXT("Unexpected end of file before next quote! Pos:%d"), CharPtr - *AttributesList);
				return false;
			}
			// Check we didn't run out of line
			if(*CharPtr == EOLine)
			{
				UE_LOG(LogFileAttributesParser, Error, TEXT("Unexpected end of line before next quote! Pos:%d"), CharPtr - *AttributesList);
				return false;
			}
			// Save positions
			const TCHAR* FilenameEnd = CharPtr++;
			const TCHAR* AttributesStart = CharPtr;
			// Parse keywords
			while (*CharPtr != Quote && *CharPtr != EOFile && *CharPtr != EOLine){ ++CharPtr; }
			// Check we hit the end of the line or file, another quote it wrong
			if (*CharPtr == Quote)
			{
				UE_LOG(LogFileAttributesParser, Error, TEXT("Unexpected Quote before end of keywords! Pos:%d"), CharPtr - *AttributesList);
				return false;
			}
			FoundFilename = true;
			// Save position
			const TCHAR* EndOfLine = CharPtr;
			// Grab info
			FString Filename = FString(FilenameEnd - FilenameStart, FilenameStart).Replace(TEXT("\\"), TEXT("/"));
			FFileAttributes& FileAttributes = FileAttributesMap.FindOrAdd(Filename);
			TArray<FString> AttributeParamsArray;
			FString AttributeParams(EndOfLine - AttributesStart, AttributesStart);
			AttributeParams.ParseIntoArrayWS(AttributeParamsArray);
			for (const FString& AttributeParam : AttributeParamsArray)
			{
				FString Key, Value;
				if(!AttributeParam.Split(TEXT(":"), &Key, &Value))
				{
					Key = AttributeParam;
				}
				if (AttributeSetters.Contains(Key))
				{
					AttributeSetters[Key](FileAttributes, MoveTemp(Value));
				}
				else
				{
					UE_LOG(LogFileAttributesParser, Error, TEXT("Unrecognised attribute %s for %s"), *AttributeParam, *Filename);
					Successful = false;
				}
			}
		}

		return Successful;
	}
	void FixUpChunkBoneMaps( FSkelMeshChunk & Chunk, const TMap<FBoneIndexType, FBoneIndexType> &BonesToRepair ) override
	{
		// now you have list of bones, remove them from vertex influences
		{
			TMap<uint8, uint8> BoneMapRemapTable;
			// first go through bone map and see if this contains BonesToRemove
			int32 BoneMapSize = Chunk.BoneMap.Num();
			int32 AdjustIndex=0;

			for (int32 BoneMapIndex=0; BoneMapIndex < BoneMapSize; ++BoneMapIndex )
			{
				// look for this bone to be removed or not?
				const FBoneIndexType* ParentBoneIndex = BonesToRepair.Find(Chunk.BoneMap[BoneMapIndex]);
				if ( ParentBoneIndex  )
				{
					// this should not happen, I don't ever remove root
					check (*ParentBoneIndex!=INDEX_NONE);

					// if Parent already exists in the current BoneMap, we just have to fix up the mapping
					int32 ParentBoneMapIndex = Chunk.BoneMap.Find(*ParentBoneIndex);

					// if it exists
					if (ParentBoneMapIndex != INDEX_NONE)
					{
						// if parent index is higher, we have to decrease it to match to new index
						if (ParentBoneMapIndex > BoneMapIndex)
						{
							--ParentBoneMapIndex;
						}

						// remove current chunk count, will replace with parent
						Chunk.BoneMap.RemoveAt(BoneMapIndex);
					}
					else
					{
						// if parent doens't exists, we have to add one
						// this doesn't change bone map size 
						Chunk.BoneMap.RemoveAt(BoneMapIndex);
						ParentBoneMapIndex = Chunk.BoneMap.Add(*ParentBoneIndex);
					}

					// first fix up all indices of BoneMapRemapTable for the indices higher than BoneMapIndex, since BoneMapIndex is being removed
					for (auto Iter = BoneMapRemapTable.CreateIterator(); Iter; ++Iter)
					{
						uint8& Value = Iter.Value();

						check (Value != BoneMapIndex);
						if (Value > BoneMapIndex)
						{
							--Value;
						}
					}

					int32 OldIndex = BoneMapIndex+AdjustIndex;
					int32 NewIndex = ParentBoneMapIndex;
					// you still have to add no matter what even if same since indices might change after added
					{
						// add to remap table
						check (OldIndex < 256 && OldIndex >= 0);
						check (NewIndex < 256 && NewIndex >= 0);
						check (BoneMapRemapTable.Contains((uint8)OldIndex) == false);
						BoneMapRemapTable.Add((uint8)OldIndex, (uint8)NewIndex);
					}

					// reduce index since the item is removed
					--BoneMapIndex;
					--BoneMapSize;

					// this is to adjust the later indices. We need to refix their indices
					++AdjustIndex;
				}
				else if (AdjustIndex > 0)
				{
					int32 OldIndex = BoneMapIndex+AdjustIndex;
					int32 NewIndex = BoneMapIndex;

					check (OldIndex < 256 && OldIndex >= 0);
					check (NewIndex < 256 && NewIndex >= 0);
					check (BoneMapRemapTable.Contains((uint8)OldIndex) == false);
					BoneMapRemapTable.Add((uint8)OldIndex, (uint8)NewIndex);
				}
			}

			if ( BoneMapRemapTable.Num() > 0 )
			{
				// fix up rigid verts
				for (int32 VertIndex=0; VertIndex < Chunk.RigidVertices.Num(); ++VertIndex)
				{
					FRigidSkinVertex & Vert = Chunk.RigidVertices[VertIndex];

					uint8 *RemappedBone = BoneMapRemapTable.Find(Vert.Bone);
					if (RemappedBone)
					{
						Vert.Bone = *RemappedBone;
					}
				}

				// fix up soft verts
				for (int32 VertIndex=0; VertIndex < Chunk.SoftVertices.Num(); ++VertIndex)
				{
					FSoftSkinVertex & Vert = Chunk.SoftVertices[VertIndex];
					bool ShouldRenormalize = false;

					for(int32 InfluenceIndex = 0;InfluenceIndex < MAX_TOTAL_INFLUENCES;InfluenceIndex++)
					{
						uint8 *RemappedBone = BoneMapRemapTable.Find(Vert.InfluenceBones[InfluenceIndex]);
						if (RemappedBone)
						{
							Vert.InfluenceBones[InfluenceIndex] = *RemappedBone;
							ShouldRenormalize = true;
						}
					}

					if (ShouldRenormalize)
					{
						// should see if same bone exists
						for(int32 InfluenceIndex = 0;InfluenceIndex < MAX_TOTAL_INFLUENCES;InfluenceIndex++)
						{
							for(int32 InfluenceIndex2 = InfluenceIndex+1;InfluenceIndex2 < MAX_TOTAL_INFLUENCES;InfluenceIndex2++)
							{
								// cannot be 0 because we don't allow removing root
								if (Vert.InfluenceBones[InfluenceIndex] != 0 && Vert.InfluenceBones[InfluenceIndex] == Vert.InfluenceBones[InfluenceIndex2])
								{
									Vert.InfluenceWeights[InfluenceIndex] += Vert.InfluenceWeights[InfluenceIndex2];
									// reset
									Vert.InfluenceBones[InfluenceIndex2] = 0;
									Vert.InfluenceWeights[InfluenceIndex2] = 0;
								}
							}
						}
					}
				}
			}

			// @todo fix up RequiredBones/ActiveBoneIndices?
			
		}
	}
Exemple #16
0
void SSizeMap::GatherDependenciesRecursively( FAssetRegistryModule& AssetRegistryModule, TSharedPtr<FAssetThumbnailPool>& InAssetThumbnailPool, TMap<FName, TSharedPtr<FTreeMapNodeData>>& VisitedAssetPackageNames, const TArray<FName>& AssetPackageNames, const TSharedPtr<FTreeMapNodeData>& Node, TSharedPtr<FTreeMapNodeData>& SharedRootNode, int32& NumAssetsWhichFailedToLoad )
{
	for( const FName AssetPackageName : AssetPackageNames )
	{
		// Have we already added this asset to the tree?  If so, we'll either move it to a "shared" group or (if it's referenced again by the same
		// root-level asset) ignore it
		if( VisitedAssetPackageNames.Contains( AssetPackageName ) )
		{ 
			// OK, we've determined that this asset has already been referenced by something else in our tree.  We'll move it to a "shared" group
			// so all of the assets that are referenced in multiple places can be seen together.
			TSharedPtr<FTreeMapNodeData> ExistingNode = VisitedAssetPackageNames[ AssetPackageName ];

			// Is the existing node not already under the "shared" group?  Note that it might still be (indirectly) under
			// the "shared" group, in which case we'll still want to move it up to the root since we've figured out that it is
			// actually shared between multiple assets which themselves may be shared
			if( ExistingNode->Parent != SharedRootNode.Get() )
			{
				// Don't bother moving any of the assets at the root level into a "shared" bucket.  We're only trying to best
				// represent the memory used when all of the root-level assets have become loaded.  It's OK if root-level assets
				// are referenced by other assets in the set -- we don't need to indicate they are shared explicitly
				FTreeMapNodeData* ExistingNodeParent = ExistingNode->Parent;
				check( ExistingNodeParent != nullptr );
				const bool bExistingNodeIsAtRootLevel = ExistingNodeParent->Parent == nullptr || RootAssetPackageNames.Contains( AssetPackageName );
				if( !bExistingNodeIsAtRootLevel )
				{
					// OK, the current asset (AssetPackageName) is definitely not a root level asset, but its already in the tree
					// somewhere as a non-shared, non-root level asset.  We need to make sure that this Node's reference is not from the
					// same root-level asset as the ExistingNodeInTree.  Otherwise, there's no need to move it to a 'shared' group.
					FTreeMapNodeData* MyParentNode = Node.Get();
					check( MyParentNode != nullptr );
					FTreeMapNodeData* MyRootLevelAssetNode = MyParentNode;
					while( MyRootLevelAssetNode->Parent != nullptr && MyRootLevelAssetNode->Parent->Parent != nullptr )
					{
						MyRootLevelAssetNode = MyRootLevelAssetNode->Parent;
					}
					if( MyRootLevelAssetNode->Parent == nullptr )
					{
						// No root asset (Node must be a root level asset itself!)
						MyRootLevelAssetNode = nullptr;
					}
					
					// Find the existing node's root level asset node
					FTreeMapNodeData* ExistingNodeRootLevelAssetNode = ExistingNodeParent;
					while( ExistingNodeRootLevelAssetNode->Parent->Parent != nullptr )
					{
						ExistingNodeRootLevelAssetNode = ExistingNodeRootLevelAssetNode->Parent;
					}

					// If we're being referenced by another node within the same asset, no need to move it to a 'shared' group.  
					if( MyRootLevelAssetNode != ExistingNodeRootLevelAssetNode )
					{
						// This asset was already referenced by something else (or was in our top level list of assets to display sizes for)
						if( !SharedRootNode.IsValid() )
						{
							// Find the root-most tree node
							FTreeMapNodeData* RootNode = MyParentNode;
							while( RootNode->Parent != nullptr )
							{
								RootNode = RootNode->Parent;
							}

							SharedRootNode = MakeShareable( new FTreeMapNodeData() );
							RootNode->Children.Add( SharedRootNode );
							SharedRootNode->Parent = RootNode;	// Keep back-pointer to parent node
						}

						// Reparent the node that we've now determined to be shared
						ExistingNode->Parent->Children.Remove( ExistingNode );
						SharedRootNode->Children.Add( ExistingNode );
						ExistingNode->Parent = SharedRootNode.Get();
					}
				}
			}
		}
		else
		{
			// This asset is new to us so far!  Let's add it to the tree.  Later as we descend through references, we might find that the
			// asset is referenced by something else as well, in which case we'll pull it out and move it to a "shared" top-level box
					
			// Don't bother showing code references
			const FString AssetPackageNameString = AssetPackageName.ToString();
			if( !AssetPackageNameString.StartsWith( TEXT( "/Script/" ) ) )
			{
				FTreeMapNodeDataRef ChildTreeMapNode = MakeShareable( new FTreeMapNodeData() );
				Node->Children.Add( ChildTreeMapNode );
				ChildTreeMapNode->Parent = Node.Get();	// Keep back-pointer to parent node

				VisitedAssetPackageNames.Add( AssetPackageName, ChildTreeMapNode );

				FNodeSizeMapData& NodeSizeMapData = NodeSizeMapDataMap.Add( ChildTreeMapNode );

				// Set some defaults for this node.  These will be used if we can't actually locate the asset.
				// @todo sizemap urgent: We need a better indication in the UI when there are one or more missing assets.  Because missing assets have a size 
				//    of zero, they are nearly impossible to zoom into.  At the least, we should have some Output Log spew when assets cannot be loaded
				NodeSizeMapData.AssetData.AssetName = AssetPackageName;
				NodeSizeMapData.AssetData.AssetClass = FName( *LOCTEXT( "MissingAsset", "MISSING!" ).ToString() );
				NodeSizeMapData.AssetSize = 0;
				NodeSizeMapData.bHasKnownSize = false;

				// Find the asset using the asset registry
				// @todo sizemap: Asset registry-based reference gathering is faster but possibly not as exhaustive (no PostLoad created references, etc.)  Maybe should be optional?
				// @todo sizemap: With AR-based reference gathering, sometimes the size map is missing root level dependencies until you reopen it a few times (Buggy BP)
				// @todo sizemap: With AR-based reference gathering, reference changes at editor-time do not appear in the Size Map until you restart
				// @todo sizemap: With AR-based reference gathering, opening the size map for all engine content caused the window to not respond until a restart
				// @todo sizemap: We don't really need the asset registry given we need to load the objects to figure out their size, unless we make that AR-searchable.
				//   ---> This would allow us to not have to wait for AR initialization.  But if we made size AR-searchable, we could run very quickly for large data sets!
				const bool bUseAssetRegistryForDependencies = false;

				const FString AssetPathString = AssetPackageNameString + TEXT(".") + FPackageName::GetLongPackageAssetName( AssetPackageNameString );
				const FAssetData FoundAssetData = AssetRegistryModule.Get().GetAssetByObjectPath( FName( *AssetPathString ) );
				if( FoundAssetData.IsValid() )
				{
					NodeSizeMapData.AssetData = FoundAssetData;

					// Now actually load up the asset.  We need it in memory in order to accurately determine its size.
					// @todo sizemap: We could async load these packages to make the editor experience a bit nicer (smoother progress)
					UObject* Asset = StaticLoadObject( UObject::StaticClass(), nullptr, *AssetPathString );
					if( Asset != nullptr )
					{
						TArray<FName> ReferencedAssetPackageNames;
						if( bUseAssetRegistryForDependencies )
						{
							AssetRegistryModule.Get().GetDependencies( AssetPackageName, ReferencedAssetPackageNames );
						}
						else
						{
							SizeMapInternals::FAssetReferenceFinder References( Asset );
							for( UObject* Object : References.GetReferencedAssets() )
							{
								ReferencedAssetPackageNames.Add( FName( *Object->GetOutermost()->GetPathName() ) );
							}
						}

						// For textures, make sure we're getting the worst case size, not the size of the currently loaded set of mips
						// @todo sizemap: We should instead have a special EResourceSizeMode that asks for the worst case size.  Some assets (like UTextureCube) currently always report resident mip size, even when asked for inclusive size
						if( Asset->IsA( UTexture2D::StaticClass() ) )
						{
							NodeSizeMapData.AssetSize = Asset->GetResourceSize( EResourceSizeMode::Inclusive );
						}
						else
						{
							NodeSizeMapData.AssetSize = Asset->GetResourceSize( EResourceSizeMode::Exclusive );
						}

						NodeSizeMapData.bHasKnownSize = NodeSizeMapData.AssetSize != UObject::RESOURCE_SIZE_NONE && NodeSizeMapData.AssetSize != 0;
						if( !NodeSizeMapData.bHasKnownSize )
						{
							// Asset has no meaningful size
							NodeSizeMapData.AssetSize = 0;

							// @todo sizemap urgent: Try to serialize to figure out how big it is (not into sub-assets though!)
							// FObjectMemoryAnalyzer ObjectMemoryAnalyzer( Asset );
						}

								
						// Now visit all of the assets that we are referencing
						GatherDependenciesRecursively( AssetRegistryModule, InAssetThumbnailPool, VisitedAssetPackageNames, ReferencedAssetPackageNames, ChildTreeMapNode, SharedRootNode, NumAssetsWhichFailedToLoad );
					}
					else
					{
						++NumAssetsWhichFailedToLoad;
					}
				}
				else
				{
					++NumAssetsWhichFailedToLoad;
				}
			}
		}
	}
}
void SVisualLoggerReport::GenerateReportText()
{
	FString OutString;
	TArray<FVisualLogEvent> GlobalEventsStats;
	TMap<FString, TArray<FString> >	 EventToObjectsMap;


	OutString.Append(TEXT("<RichText.HeaderText1>Report Details</>\n"));
	for (TSharedPtr<class SLogVisualizerTimeline> LogItem : SelectedItems)
	{
		TArray<FVisualLogEvent> AllEvents;

		for (const FVisualLogDevice::FVisualLogEntryItem& CurrentEntry : LogItem->GetEntries())
		{
			for (const FVisualLogEvent& Event : CurrentEntry.Entry.Events)
			{
				int32 Index = AllEvents.Find(FVisualLogEvent(Event));
				if (Index != INDEX_NONE)
				{
					for (auto& CurrentEventTag : Event.EventTags)
					{
						if (AllEvents[Index].EventTags.Contains(CurrentEventTag.Key))
						{
							AllEvents[Index].EventTags[CurrentEventTag.Key] += CurrentEventTag.Value;
						}
						else
						{
							AllEvents[Index].EventTags.Add(CurrentEventTag.Key, CurrentEventTag.Value);
						}
					}
					AllEvents[Index].Counter++;
				}
				else
				{
					AllEvents.Add(Event);
				}
			}
		}

		bool bPrintNextLine = false;

		if (AllEvents.Num() > 0)
		{
			OutString.Append(FString::Printf(TEXT("    <RichText.HeaderText2>%s</>"), *LogItem->GetName().ToString()));
		}
		for (auto& CurrentEvent : AllEvents)
		{
			for (auto& CurrentEventTag : CurrentEvent.EventTags)
			{
				OutString.Append(FString::Printf(TEXT(" \n        \u2022  <a id=\"%s\" style=\"RichText.Hyperlink\">%s</>  with <RichText.TextBold>%s</> tag occurred    <RichText.TextBold>%d times</>"), *CurrentEvent.Name, *CurrentEvent.Name, *CurrentEventTag.Key.ToString(), CurrentEventTag.Value));
			}
			OutString.Append(FString::Printf(TEXT("\n        \u2022  <a id=\"%s\" style=\"RichText.Hyperlink\">%s</> occurred <RichText.TextBold>%d times</>"), *CurrentEvent.Name, *CurrentEvent.Name, CurrentEvent.Counter));

			bool bJustAdded = false;
			int32 Index = GlobalEventsStats.Find(FVisualLogEvent(CurrentEvent));
			if (Index != INDEX_NONE)
			{
				GlobalEventsStats[Index].Counter += CurrentEvent.Counter;
				EventToObjectsMap[CurrentEvent.Name].AddUnique(LogItem->GetName().ToString());
			}
			else
			{
				bJustAdded = true;
				GlobalEventsStats.Add(CurrentEvent);
				EventToObjectsMap.FindOrAdd(CurrentEvent.Name).Add(LogItem->GetName().ToString());
			}

			Index = GlobalEventsStats.Find(FVisualLogEvent(CurrentEvent));
			for (auto& CurrentEventTag : CurrentEvent.EventTags)
			{
				if (!bJustAdded)
				{
					GlobalEventsStats[Index].EventTags.FindOrAdd(CurrentEventTag.Key) += CurrentEventTag.Value;
				}

				if (EventToObjectsMap.Contains(CurrentEvent.Name + CurrentEventTag.Key.ToString()))
				{
					EventToObjectsMap[CurrentEvent.Name + CurrentEventTag.Key.ToString()].AddUnique(LogItem->GetName().ToString());
				}
				else
				{
					EventToObjectsMap.FindOrAdd(CurrentEvent.Name + CurrentEventTag.Key.ToString()).AddUnique(LogItem->GetName().ToString());
				}
			}
			OutString.Append(TEXT("\n"));
		}
		OutString.Append(TEXT("\n"));
	}

	OutString.Append(TEXT("\n\n<RichText.HeaderText1>Report Summary</>\n"));

	CollectedEvents.Reset();
	for (auto& CurrentEvent : GlobalEventsStats)
	{
		CollectedEvents.Add(*CurrentEvent.Name);
		OutString.Append(FString::Printf(TEXT("    <a id=\"%s\" style=\"RichText.Hyperlink\">%s</>  occurred <RichText.TextBold>%d times</> by %d owners (%s)\n"), *CurrentEvent.Name, *CurrentEvent.Name, CurrentEvent.Counter, EventToObjectsMap.Contains(CurrentEvent.Name) ? EventToObjectsMap[CurrentEvent.Name].Num() : 0, *CurrentEvent.UserFriendlyDesc));
		for (auto& CurrentEventTag : CurrentEvent.EventTags)
		{
			const int32 ObjectsNumber = EventToObjectsMap.Contains(CurrentEvent.Name + CurrentEventTag.Key.ToString()) ? EventToObjectsMap[CurrentEvent.Name + CurrentEventTag.Key.ToString()].Num() : 0;
			OutString.Append(FString::Printf(TEXT("        \u2022  %s to <RichText.TextBold>%s</> tag occurred <RichText.TextBold>%d times</> by %d owners (average %.2f times each)\n"), *CurrentEvent.Name, *CurrentEventTag.Key.ToString(), CurrentEventTag.Value, ObjectsNumber, ObjectsNumber > 0 ? float(CurrentEventTag.Value) / ObjectsNumber : -1));
		}
		OutString.Append(TEXT("\n"));
	}

	ReportText = FText::FromString(OutString);
}
UObject* USspjFactory::FactoryCreateBinary(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, const TCHAR* Type, const uint8*& Buffer, const uint8* InBufferEnd, FFeedbackContext* Warn)
{
	bool bReimport = this->IsA(UReimportSspjFactory::StaticClass());
	TMap<FString, UTexture*>* ExistImages = NULL;
	if(bReimport)
	{
		ExistImages = &(Cast<UReimportSspjFactory>(this)->ExistImages);
	}

	FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools");

	FString ProjectNameStr = InName.ToString();
	FName ProjectName = InName;

	UPackage* InParentPackage = Cast<UPackage>(InParent);
	if(InParentPackage && !bReimport)
	{
		FString ProjectPackageName;
		FString BasePackageName = FPackageName::GetLongPackagePath(InParent->GetOutermost()->GetName()) / ProjectNameStr;
		AssetToolsModule.Get().CreateUniqueAssetName(BasePackageName, TEXT(""), ProjectPackageName, ProjectNameStr);
		InParentPackage->Rename(*ProjectPackageName);
	}

	// インポート設定の取得 
	const USsImportSettings* ImportSettings = GetDefault<USsImportSettings>();

	// インポート開始 
	FEditorDelegates::OnAssetPreImport.Broadcast(this, InClass, InParent, ProjectName, Type);

	// sspj
	USsProject* NewProject = FSsLoader::LoadSsProject(InParent, ProjectName, Flags, Buffer, (InBufferEnd - Buffer) + 1);
	NewProject->SetFilepath( GetCurrentFilename() );
	if(NewProject)
	{
		if(NewProject->AssetImportData == nullptr)
		{
			NewProject->AssetImportData = NewObject<UAssetImportData>(NewProject);
		}
		NewProject->AssetImportData->Update(CurrentFilename);

		FString CurPath = FPaths::GetPath(GetCurrentFilename());

		TArray<FString> ImagePaths;
		TArray<SsTexWrapMode::Type> ImageWrapModes;
		TArray<SsTexFilterMode::Type> ImageFilterModes;

		// ssce
		NewProject->CellmapList.Empty();
		NewProject->CellmapList.AddZeroed(NewProject->CellmapNames.Num());
		for(int i = 0; i < NewProject->CellmapNames.Num(); ++i)
		{
			FString FileName = GetFilePath(CurPath, NewProject->Settings.CellMapBaseDirectory, NewProject->CellmapNames[i].ToString());

			TArray<uint8> Data;
			if(FFileHelper::LoadFileToArray(Data, *FileName))
			{
				const uint8* BufferBegin = Data.GetData();
				const uint8* BufferEnd = BufferBegin + Data.Num() - 1;
				if(FSsLoader::LoadSsCellMap(&(NewProject->CellmapList[i]), BufferBegin, (BufferEnd - BufferBegin) + 1))
				{
					NewProject->CellmapList[i].FileName = NewProject->CellmapNames[i];
					if(0 < NewProject->CellmapList[i].ImagePath.Len())
					{
						if(INDEX_NONE == ImagePaths.Find(NewProject->CellmapList[i].ImagePath))
						{
							ImagePaths.Add(NewProject->CellmapList[i].ImagePath);
							if(NewProject->CellmapList[i].OverrideTexSettings)
							{
								ImageWrapModes.Add(NewProject->CellmapList[i].WrapMode);
								ImageFilterModes.Add(NewProject->CellmapList[i].FilterMode);
							}
							else
							{
								ImageWrapModes.Add(NewProject->Settings.WrapMode);
								ImageFilterModes.Add(NewProject->Settings.FilterMode);
							}
						}
					}
				}
			}
		}

		// ssae
		NewProject->AnimeList.Empty();
		NewProject->AnimeList.AddZeroed(NewProject->AnimepackNames.Num());
		for(int i = 0; i < NewProject->AnimepackNames.Num(); ++i)
		{
			FString FileName = GetFilePath(CurPath, NewProject->Settings.AnimeBaseDirectory, NewProject->AnimepackNames[i].ToString());

			TArray<uint8> Data;
			if(FFileHelper::LoadFileToArray(Data, *FileName))
			{
				const uint8* BufferBegin = Data.GetData();
				const uint8* BufferEnd = BufferBegin + Data.Num() - 1;
				FSsLoader::LoadSsAnimePack(&(NewProject->AnimeList[i]), BufferBegin, (BufferEnd - BufferBegin) + 1);
			}
		}

		// texture
		for(int i = 0; i < ImagePaths.Num(); ++i)
		{
			FString FileName = GetFilePath(CurPath, NewProject->Settings.ImageBaseDirectory, ImagePaths[i]);

			UTexture* ImportedTexture = NULL;
			if(ExistImages && ExistImages->Contains(ImagePaths[i]))
			{
				ImportedTexture = ExistImages->FindChecked(ImagePaths[i]);
			}

			TArray<uint8> Data;
			if(FFileHelper::LoadFileToArray(Data, *FileName))
			{

				UTextureFactory* TextureFact = NewObject<UTextureFactory>();
				TextureFact->AddToRoot();

				FString TextureName = FPaths::GetBaseFilename(ImagePaths[i]);

				UPackage* TexturePackage = NULL;
				if(ImportedTexture)
				{
					TexturePackage = ImportedTexture->GetOutermost();
				}
				else
				{
					FString TexturePackageName;
					FString BasePackageName = FPackageName::GetLongPackagePath(InParent->GetOutermost()->GetName()) / TextureName;
					AssetToolsModule.Get().CreateUniqueAssetName(BasePackageName, TEXT(""), TexturePackageName, TextureName);
					TexturePackage = CreatePackage(NULL, *TexturePackageName);
				}

				const uint8* BufferBegin = Data.GetData();
				const uint8* BufferEnd = BufferBegin + Data.Num();
				UTexture2D* NewTexture = (UTexture2D*)TextureFact->FactoryCreateBinary(
					UTexture2D::StaticClass(),
					TexturePackage,
					FName(*TextureName),
					Flags,
					NULL,
					*FPaths::GetExtension(ImagePaths[i]),
					BufferBegin, BufferEnd,
					Warn
					);
				if(NewTexture)
				{
					if(ImportSettings->bOverwriteMipGenSettings)
					{
						NewTexture->MipGenSettings = TMGS_NoMipmaps;
					}
					if(ImportSettings->bOverwriteTextureGroup)
					{
						NewTexture->LODGroup = ImportSettings->TextureGroup;
					}
					if(ImportSettings->bOverwriteCompressionSettings)
					{
						NewTexture->CompressionSettings = TextureCompressionSettings::TC_EditorIcon;
					}
					if(ImportSettings->bOverwriteTilingMethodFromSspj)
					{
						switch(ImageWrapModes[i])
						{
							case SsTexWrapMode::Clamp:
								{
									NewTexture->AddressX = NewTexture->AddressY = TA_Clamp;
								} break;
							case SsTexWrapMode::Repeat:
								{
									NewTexture->AddressX = NewTexture->AddressY = TA_Wrap;
								} break;
							case SsTexWrapMode::Mirror:
								{
									NewTexture->AddressX = NewTexture->AddressY = TA_Mirror;
								} break;
						}
					}
					if(ImportSettings->bOverwriteNeverStream)
					{
						NewTexture->NeverStream = true;
					}
					if(ImportSettings->bOverwriteFilterFromSspj)
					{
						switch(ImageFilterModes[i])
						{
							case SsTexFilterMode::Nearest:
								{
									NewTexture->Filter = TF_Nearest;
								} break;
							case SsTexFilterMode::Linear:
								{
									NewTexture->Filter = TF_Bilinear;
								} break;
						}
					}

					NewTexture->UpdateResource();

					FAssetRegistryModule::AssetCreated(NewTexture);
					TexturePackage->SetDirtyFlag(true);

					TextureFact->RemoveFromRoot();

					ImportedTexture = NewTexture;
				}
			}

			if(ImportedTexture)
			{
				for(int ii = 0; ii < NewProject->CellmapList.Num(); ++ii)
				{
					if(NewProject->CellmapList[ii].ImagePath == ImagePaths[i])
					{
						NewProject->CellmapList[ii].Texture = ImportedTexture;
					}
				}
			}
		}
	}

	// インポート終了
	FEditorDelegates::OnAssetPostImport.Broadcast(this, NewProject);
	return NewProject;
}
Exemple #19
0
void AActor::RerunConstructionScripts()
{
	checkf(!HasAnyFlags(RF_ClassDefaultObject), TEXT("RerunConstructionScripts should never be called on a CDO as it can mutate the transient data on the CDO which then propagates to instances!"));

	FEditorScriptExecutionGuard ScriptGuard;
	// don't allow (re)running construction scripts on dying actors
	bool bAllowReconstruction = !IsPendingKill() && !HasAnyFlags(RF_BeginDestroyed|RF_FinishDestroyed);
#if WITH_EDITOR
	if(bAllowReconstruction && GIsEditor)
	{
		// Generate the blueprint hierarchy for this actor
		TArray<UBlueprint*> ParentBPStack;
		bAllowReconstruction = UBlueprint::GetBlueprintHierarchyFromClass(GetClass(), ParentBPStack);
		if(bAllowReconstruction)
		{
			for(int i = ParentBPStack.Num() - 1; i > 0 && bAllowReconstruction; --i)
			{
				const UBlueprint* ParentBP = ParentBPStack[i];
				if(ParentBP && ParentBP->bBeingCompiled)
				{
					// don't allow (re)running construction scripts if a parent BP is being compiled
					bAllowReconstruction = false;
				}
			}
		}
	}
#endif
	if(bAllowReconstruction)
	{
		// Set global flag to let system know we are reconstructing blueprint instances
		TGuardValue<bool> GuardTemplateNameFlag(GIsReconstructingBlueprintInstances, true);

		// Temporarily suspend the undo buffer; we don't need to record reconstructed component objects into the current transaction
		ITransaction* CurrentTransaction = GUndo;
		GUndo = NULL;
		
		// Create cache to store component data across rerunning construction scripts
#if WITH_EDITOR
		FActorTransactionAnnotation* ActorTransactionAnnotation = CurrentTransactionAnnotation.Get();
#endif
		FComponentInstanceDataCache* InstanceDataCache;
		
		FTransform OldTransform = FTransform::Identity;
		FName  SocketName;
		AActor* Parent = NULL;
		USceneComponent* ParentComponent = NULL;

		bool bUseRootComponentProperties = true;

		// Struct to store info about attached actors
		struct FAttachedActorInfo
		{
			AActor* AttachedActor;
			FName AttachedToSocket;
			bool bSetRelativeTransform;
			FTransform RelativeTransform;
		};

		// Save info about attached actors
		TArray<FAttachedActorInfo> AttachedActorInfos;

#if WITH_EDITOR
		if (ActorTransactionAnnotation)
		{
			InstanceDataCache = &ActorTransactionAnnotation->ComponentInstanceData;

			if (ActorTransactionAnnotation->bRootComponentDataCached)
			{
				OldTransform = ActorTransactionAnnotation->RootComponentData.Transform;
				Parent = ActorTransactionAnnotation->RootComponentData.AttachedParentInfo.Actor.Get();
				if (Parent)
				{
					USceneComponent* AttachParent = ActorTransactionAnnotation->RootComponentData.AttachedParentInfo.AttachParent.Get();
					ParentComponent = (AttachParent ? AttachParent : FindObjectFast<USceneComponent>(Parent, ActorTransactionAnnotation->RootComponentData.AttachedParentInfo.AttachParentName));
					SocketName = ActorTransactionAnnotation->RootComponentData.AttachedParentInfo.SocketName;
					DetachRootComponentFromParent();
				}

				for (const auto& CachedAttachInfo : ActorTransactionAnnotation->RootComponentData.AttachedToInfo)
				{
					AActor* AttachedActor = CachedAttachInfo.Actor.Get();
					if (AttachedActor)
					{
						FAttachedActorInfo Info;
						Info.AttachedActor = AttachedActor;
						Info.AttachedToSocket = CachedAttachInfo.SocketName;
						Info.bSetRelativeTransform = true;
						Info.RelativeTransform = CachedAttachInfo.RelativeTransform;
						AttachedActorInfos.Add(Info);

						AttachedActor->DetachRootComponentFromParent();
					}
				}

				bUseRootComponentProperties = false;
			}
		}
		else
#endif
		{
			InstanceDataCache = new FComponentInstanceDataCache(this);

			// If there are attached objects detach them and store the socket names
			TArray<AActor*> AttachedActors;
			GetAttachedActors(AttachedActors);

			for (AActor* AttachedActor : AttachedActors)
			{
				USceneComponent* EachRoot = AttachedActor->GetRootComponent();
				// If the component we are attached to is about to go away...
				if (EachRoot && EachRoot->AttachParent && EachRoot->AttachParent->IsCreatedByConstructionScript())
				{
					// Save info about actor to reattach
					FAttachedActorInfo Info;
					Info.AttachedActor = AttachedActor;
					Info.AttachedToSocket = EachRoot->AttachSocketName;
					Info.bSetRelativeTransform = false;
					AttachedActorInfos.Add(Info);

					// Now detach it
					AttachedActor->Modify();
					EachRoot->DetachFromParent(true);
				}
			}
		}

		if (bUseRootComponentProperties && RootComponent != nullptr)
		{
			// Do not need to detach if root component is not going away
			if (RootComponent->AttachParent != NULL && RootComponent->IsCreatedByConstructionScript())
			{
				Parent = RootComponent->AttachParent->GetOwner();
				// Root component should never be attached to another component in the same actor!
				if (Parent == this)
				{
					UE_LOG(LogActor, Warning, TEXT("RerunConstructionScripts: RootComponent (%s) attached to another component in this Actor (%s)."), *RootComponent->GetPathName(), *Parent->GetPathName());
					Parent = NULL;
				}
				ParentComponent = RootComponent->AttachParent;
				SocketName = RootComponent->AttachSocketName;
				//detach it to remove any scaling 
				RootComponent->DetachFromParent(true);
			}

			OldTransform = RootComponent->ComponentToWorld;
			OldTransform.SetTranslation(RootComponent->GetComponentLocation()); // take into account any custom location
		}

#if WITH_EDITOR
		// Save the current construction script-created components by name
		TMap<const FName, UObject*> DestroyedComponentsByName;
		TInlineComponentArray<UActorComponent*> PreviouslyAttachedComponents;
		GetComponents(PreviouslyAttachedComponents);
		for (auto Component : PreviouslyAttachedComponents)
		{
			if (Component)
			{
				if (Component->IsCreatedByConstructionScript())
				{

					DestroyedComponentsByName.Add(Component->GetFName(), Component);
				}
				else
				{
					UActorComponent* OuterComponent = Component->GetTypedOuter<UActorComponent>();
					while (OuterComponent)
					{
						if (OuterComponent->IsCreatedByConstructionScript())
						{
							DestroyedComponentsByName.Add(Component->GetFName(), Component);
							break;
						}
						OuterComponent = OuterComponent->GetTypedOuter<UActorComponent>();
					}
				}
			}
		}
#endif

		// Destroy existing components
		DestroyConstructedComponents();

		// Reset random streams
		ResetPropertiesForConstruction();

		// Exchange net roles before running construction scripts
		UWorld *OwningWorld = GetWorld();
		if (OwningWorld && !OwningWorld->IsServer())
		{
			ExchangeNetRoles(true);
		}

		// Run the construction scripts
		ExecuteConstruction(OldTransform, InstanceDataCache);

		if(Parent)
		{
			USceneComponent* ChildRoot = GetRootComponent();
			if (ParentComponent == NULL)
			{
				ParentComponent = Parent->GetRootComponent();
			}
			if (ChildRoot != NULL && ParentComponent != NULL)
			{
				ChildRoot->AttachTo(ParentComponent, SocketName, EAttachLocation::KeepWorldPosition);
			}
		}

		// If we had attached children reattach them now - unless they are already attached
		for(FAttachedActorInfo& Info : AttachedActorInfos)
		{
			// If this actor is no longer attached to anything, reattach
			if (!Info.AttachedActor->IsPendingKill() && Info.AttachedActor->GetAttachParentActor() == NULL)
			{
				USceneComponent* ChildRoot = Info.AttachedActor->GetRootComponent();
				if (ChildRoot && ChildRoot->AttachParent != RootComponent)
				{
					ChildRoot->AttachTo(RootComponent, Info.AttachedToSocket, EAttachLocation::KeepWorldPosition);
					if (Info.bSetRelativeTransform)
					{
						ChildRoot->SetRelativeTransform(Info.RelativeTransform);
					}
					ChildRoot->UpdateComponentToWorld();
				}
			}
		}

		// Restore the undo buffer
		GUndo = CurrentTransaction;

#if WITH_EDITOR
		// Create the mapping of old->new components and notify the editor of the replacements
		TMap<UObject*, UObject*> OldToNewComponentMapping;

		TInlineComponentArray<UActorComponent*> NewComponents;
		GetComponents(NewComponents);
		for (auto NewComp : NewComponents)
		{
			const FName NewCompName = NewComp->GetFName();
			if (DestroyedComponentsByName.Contains(NewCompName))
			{
				OldToNewComponentMapping.Add(DestroyedComponentsByName[NewCompName], NewComp);
			}
		}

		if (GEditor && (OldToNewComponentMapping.Num() > 0))
		{
			GEditor->NotifyToolsOfObjectReplacement(OldToNewComponentMapping);
		}

		if (ActorTransactionAnnotation)
		{
			CurrentTransactionAnnotation = NULL;
		}
		else
#endif
		{
			delete InstanceDataCache;
		}

	}
}
Exemple #20
0
/******************** ProcessResourceRequests *************************/
void APOTLStructure::ProcessResourceRequests()
{
	int32 i;
	int32 HighestSequence = -1;
	TMap<int32, TArray<FST_ResourceRequest>> SortedResourceRequests;
	//~~ Get highest sequence from all of the requests ~~//
	for (i = 0; i < ResourceRequests.Num(); i++)
	{
		FST_ResourceRequest& ResourceRequest = ResourceRequests[i];
		if (ResourceRequest.Sequence > HighestSequence)
		{
			HighestSequence = ResourceRequest.Sequence;
		}
	}
	//~~ Init SortedResourceRequests. Make empty arrays ~~//
	for (i = 0; i <= HighestSequence; i++)
	{
		TArray<FST_ResourceRequest> List;
		SortedResourceRequests.Add(i, List);
	}
	//~~ Add resource request to sorted tmap ~~//
	for (i = 0; i < ResourceRequests.Num(); i++)
	{
		FST_ResourceRequest& ResourceRequest = ResourceRequests[i];
		int32 Sequence = ResourceRequest.Sequence;
		if (SortedResourceRequests.Contains(Sequence))
		{
			SortedResourceRequests[Sequence].Add(ResourceRequest);
		}
		else
		{
			GEngine->AddOnScreenDebugMessage(-1, 30.0f, FColor::Red, "ERROR: SortedResourceRequests could not recivce request with a sequence not found ");
		}
	}
	//~~ Allocate and process the requests ~~//
	for (i = 0; i <= HighestSequence; i++) //~~ Handle the request from sequence zero and up ~~//
	{
		TArray<FST_ResourceRequest>& RequestList = SortedResourceRequests[i];
		for (int32 ii = 0; ii < RequestList.Num(); ii++) // Loop through sequence row list. Ex 0[{R}, {R}, {R}]
		{
			FST_ResourceRequest& ResourceRequest = RequestList[ii];

			if (ResourceRequest.Request.Num() > 1)
			{
				FString Sasdsa;
			}

			if (HasResourcesAvailable(ResourceRequest.Request, true, i)) //~~ If self has the resources required. (i) is the sequence, not (ii), it is just a list index for the nested array. ~~//
			{
				TArray<int32> AllocationIndexes;
				//~~ Requirements ~~//
				for (auto& ReqResource : ResourceRequest.Request) //~~ Loop each resource in request ~~//
				{
					//? AllocateResource with group id for grouping multiple allocations?
					if (FreeResources.Contains(ReqResource.Key))
					{
						int32 AvailableQuantity = FreeResources[ReqResource.Key];
						if (AvailableQuantity > ReqResource.Value)
						{
							AvailableQuantity = ReqResource.Value;
						}
						//int32 AllocationIndex = AllocateResource(ResourceRequest.From, ReqResource.Key, AvailableQuantity, EAllocationType::FactoryBilling, ii, true, -1);
						int32 AllocationIndex = AllocateResource(ResourceRequest.From, ReqResource.Key, AvailableQuantity, EAllocationType::FactoryBilling, i, true, -1);
						AllocationIndexes.Add(AllocationIndex);
						ReqResource.Value = ReqResource.Value - AvailableQuantity;
					}
					if (ReqResource.Value > 0) //~~ If freeresources couldn't meet the requiement of the resource quantity, then make reallocations ~~//
					{
						for (auto& AllocatedResource : AllocatedResources)
						{
							FST_ResourceAllocation& Allocation = AllocatedResource.Value;
							if (Allocation.ResourceKey == ReqResource.Key && 
								Allocation.Sequence < ResourceRequest.Sequence && 
								Allocation.To == this && 
								Allocation.Type == EAllocationType::FactoryProduction && 
								Allocation.Quantity > 0)
							{	
								//!! BUG BEGIN
								if (ReqResource.Value < Allocation.Quantity) //~~ If request if less than allocation quantity, then split allocation ~~//
								{
									//Allocation.Quantity = Allocation.Quantity - ReqResource.Value; //~~ Subtract resource request quantity from the allocation, and then let it be ~~//
									//int32 NewAllocationAmount = Allocation.Quantity - ReqResource.Value;
									int32 NewAllocationAmount = ReqResource.Value;
									Allocation.Quantity = Allocation.Quantity - ReqResource.Value; //~~ Subtract resource request quantity from the allocation, and then let it be ~~//
									//Split logic //~~ Make new allocation with ~~//
									//int32 AllocationIndex = Allocation.From->AllocateResource(ResourceRequest.From, ReqResource.Key, ReqResource.Value, EAllocationType::FactoryBilling, ii, false, -1);
									int32 AllocationIndex = Allocation.From->AllocateResource(ResourceRequest.From, ReqResource.Key, NewAllocationAmount, EAllocationType::FactoryBilling, Allocation.Sequence, false, -1);
									AllocationIndexes.Add(AllocationIndex);
									ReqResource.Value = 0;
								}
								else if (ReqResource.Value >= Allocation.Quantity) //~~ If request is more or equal to allocation quantity, then just change allocation to target ~~//
								{
									Allocation.To = ResourceRequest.From;
									Allocation.Type = EAllocationType::FactoryBilling; //! Maybe it needs to be a unique type, like FactoryProductionReallocation or something.
									//ReqResource.Value = ReqResource.Value - AvailableQuantity;
									//ReqResource.Value = ReqResource.Value - Allocation.Quantity;
									FString TestValue = FString::FromInt(Allocation.Quantity);
									ReqResource.Value = ReqResource.Value - Allocation.Quantity;
									// 3 ? = 4 - 4
									// ? = 4 - 2;
								}
								//!! BUG END
							}
 							if (ReqResource.Value == 0)
							{
								break;
							}
						}
						if (ReqResource.Value > 0)
						{
							FString Bug;
						}
					}
				}
				//~~ Payoff ~~//
				for (auto& Resource : ResourceRequest.Payoff) //~~ Loop each resource in payoff ~~//
				{
					//~~ Add resource payoff to the keeper of the factory, and then allocate it to root afterwards ~~//
					//ResourceRequest.From->AddResource(Resource.Key, Resource.Value, EResourceList::Free); //~~ Add Resources and then consume them with AllocateResource(true) ~~// //!~~ No need for adding them, and then consuming them anymore. AllocateResource can not be called with consume: false ~~//
					//int32 AllocationIndex = ResourceRequest.From->AllocateResource(this, Resource.Key, Resource.Value, EAllocationType::FactoryProduction, ii, false, -1); // Maybe ii + 1 ? I think not. Are checked if sequence is lower, not lower or equal
					int32 AllocationIndex = ResourceRequest.From->AllocateResource(this, Resource.Key, Resource.Value, EAllocationType::FactoryProduction, i, false, -1); // Maybe ii + 1 ? I think not. Are checked if sequence is lower, not lower or equal
					if (ResourceRequest.Factory)
					{
						ResourceRequest.Factory->AllocationIndex = AllocationIndex;
					}
					AllocationIndexes.Add(AllocationIndex);
				}
				ResourceRequest.RequestMet = true;
			}
			else
			{ 

			}
		}
	}
}
/**
 * Enacts the transaction.
 */
void FTransaction::Apply()
{
	checkSlow(Inc==1||Inc==-1);

	// Figure out direction.
	const int32 Start = Inc==1 ? 0             : Records.Num()-1;
	const int32 End   = Inc==1 ? Records.Num() :              -1;

	// Init objects.
	TMap<UObject*, TSharedPtr<ITransactionObjectAnnotation>> ChangedObjects;
	for( int32 i=Start; i!=End; i+=Inc )
	{
		FObjectRecord& Record = Records[i];
		Record.bRestored = false;

		UObject* Object = Record.Object.Get();
		if (!ChangedObjects.Contains(Object))
		{
			Object->CheckDefaultSubobjects();
			Object->PreEditUndo();
		}

		ChangedObjects.Add(Object, Record.ObjectAnnotation);
	}
	for( int32 i=Start; i!=End; i+=Inc )
	{
		Records[i].Restore( this );
	}

	// An Actor's components must always get its PostEditUndo before the owning Actor so do a quick sort
	ChangedObjects.KeySort([](UObject& A, UObject& B)
	{
		UActorComponent* BAsComponent = Cast<UActorComponent>(&B);
		return (BAsComponent ? (BAsComponent->GetOwner() != &A) : true);
	});

	NumModelsModified = 0;		// Count the number of UModels that were changed.
	for (auto ChangedObjectIt : ChangedObjects)
	{
		UObject* ChangedObject = ChangedObjectIt.Key;
		UModel* Model = Cast<UModel>(ChangedObject);
		if (Model && Model->Nodes.Num())
		{
			FBSPOps::bspBuildBounds(Model);
			++NumModelsModified;
		}
		TSharedPtr<ITransactionObjectAnnotation> ChangedObjectTransactionAnnotation = ChangedObjectIt.Value;
		if (ChangedObjectTransactionAnnotation.IsValid())
		{
			ChangedObject->PostEditUndo(ChangedObjectTransactionAnnotation);
		}
		else
		{
			ChangedObject->PostEditUndo();
		}
	}

	// Flip it.
	if (bFlip)
	{
		Inc *= -1;
	}
	for (auto ChangedObjectIt : ChangedObjects)
	{
		UObject* ChangedObject = ChangedObjectIt.Key;
		ChangedObject->CheckDefaultSubobjects();
	}
}