Esempio n. 1
0
/**
 * Debug spew for components
 * @param Object object to dump component spew for
 */
void DumpComponents(UObject *Object)
{
    for ( FObjectIterator It; It; ++It )
    {
        It->UnMark(EObjectMark(OBJECTMARK_TagImp | OBJECTMARK_TagExp));
    }

    if (FPlatformMisc::IsDebuggerPresent() )
    {
        // if we have a debugger attached, the watch window won't be able to display the full output if we attempt to log it as a single string
        // so pass in GLog instead so that each line is sent separately;  this causes the output to have an extra line break between each log statement,
        // but at least we'll be able to see the full output in the debugger's watch window
        UE_LOG(LogExporter, Log, TEXT("Components for '%s':"), *Object->GetFullName());
        ExportProperties( NULL, *GLog, Object->GetClass(), (uint8*)Object, 0, NULL, NULL, Object, PPF_SubobjectsOnly );
        UE_LOG(LogExporter, Log, TEXT("<--- DONE!"));
    }
    else
    {
        FStringOutputDevice Output;
        Output.Logf(TEXT("Components for '%s':\r\n"), *Object->GetFullName());
        ExportProperties( NULL, Output, Object->GetClass(), (uint8*)Object, 2, NULL, NULL, Object, PPF_SubobjectsOnly );
        Output.Logf(TEXT("<--- DONE!\r\n"));
        UE_LOG(LogExporter, Log, TEXT("%s"), *Output);
    }
}
Esempio n. 2
0
FString DumpComponentsToString(UObject *Object)
{
    UnMarkAllObjects(EObjectMark(OBJECTMARK_TagExp | OBJECTMARK_TagImp));

    FStringOutputDevice Output;
    Output.Logf(TEXT("Components for '%s':\r\n"), *Object->GetFullName());
    ExportProperties(NULL, Output, Object->GetClass(), (uint8*)Object, 2, NULL, NULL, Object, PPF_SubobjectsOnly);
    Output.Logf(TEXT("<--- DONE!\r\n"));
    return Output;
}
bool GenerateProjectFiles(const FString& ProjectFileName)
{
	IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();

	// Check it's a code project
	FString SourceDir = FPaths::GetPath(ProjectFileName) / TEXT("Source");
	if(!IPlatformFile::GetPlatformPhysical().DirectoryExists(*SourceDir))
	{
		FPlatformMisc::MessageBoxExt(EAppMsgType::Ok, TEXT("This project does not have any source code. You need to add C++ source files to the project from the Editor before you can generate project files."), TEXT("Error"));
		return false;
	}

	// Get the engine root directory
	FString RootDir;
	if (!GetValidatedEngineRootDir(ProjectFileName, RootDir))
	{
		return false;
	}

	// Build the argument list
	FString Arguments = TEXT("-game");
	if (FDesktopPlatformModule::Get()->IsSourceDistribution(RootDir))
	{
		Arguments += TEXT(" -engine");
	}

	// Start capturing the log output
	FStringOutputDevice LogCapture;
	LogCapture.SetAutoEmitLineTerminator(true);
	GLog->AddOutputDevice(&LogCapture);

	// Generate project files
	FFeedbackContext* Warn = DesktopPlatform->GetNativeFeedbackContext();
	bool bResult = DesktopPlatform->GenerateProjectFiles(RootDir, ProjectFileName, Warn);
	GLog->RemoveOutputDevice(&LogCapture);

	// Display an error dialog if we failed
	if(!bResult)
	{
		FPlatformInstallation::ErrorDialog(TEXT("Failed to generate project files."), LogCapture);
		return false;
	}

	return true;
}
Esempio n. 4
0
void LogIncludeCount(const TArray<FString>& IncludesInPCH, const TMap<FString, int32>& IncludeHeaderCount, int32 FileCount, float IncludePercentageThreshold)
{
	for (const auto& FilenameAbsolutePath : IncludesInPCH)
	{
		auto IncludeCount = GetIncludeCount(IncludeHeaderCount, FilenameAbsolutePath);
		auto IncludePercentage = static_cast<float>(IncludeCount) / static_cast<float>(FileCount);
		if (IncludePercentage < IncludePercentageThreshold)
		{
			OutputFileContents.Logf(TEXT("%s %i(%f%%) with threshold %f%%"), *FilenameAbsolutePath, IncludeCount, IncludePercentage, IncludePercentageThreshold);
		}
	}
}
bool UDiffAssetsCommandlet::ExportFile(const FString& Filename, const TArray<UObject *>& LoadedObjects)
{
	FString Extension = TEXT("t3d");
	FStringOutputDevice Buffer;
	const FExportObjectInnerContext Context;
	for (int32 Index = 0; Index < LoadedObjects.Num(); Index++)
	{
		UExporter* Exporter = UExporter::FindExporter( LoadedObjects[Index], *Extension );
		if (!Exporter)
		{
			UE_LOG(LogDiffAssetsCommandlet, Warning, TEXT("Could not find exporter."));
			return false;
		}
		UExporter::ExportToOutputDevice( &Context, LoadedObjects[Index], Exporter, Buffer, *Extension, 0, PPF_ExportsNotFullyQualified, false );
		TMap<FString,FString> NativePropertyValues;
		if ( LoadedObjects[Index]->GetNativePropertyValues(NativePropertyValues) && NativePropertyValues.Num())
		{
			int32 LargestKey = 0;
			for ( TMap<FString,FString>::TIterator It(NativePropertyValues); It; ++It )
			{
				LargestKey = FMath::Max(LargestKey, It.Key().Len());
			}
			for ( TMap<FString,FString>::TIterator It(NativePropertyValues); It; ++It )
			{
				Buffer.Logf(TEXT("  %s=%s"), *It.Key().RightPad(LargestKey), *It.Value());
			}
		}
	}
	if (!Buffer.Len())
	{
		UE_LOG(LogDiffAssetsCommandlet, Warning, TEXT("No text was exported!"));
		return false;
	}
	if( !FFileHelper::SaveStringToFile( Buffer, *Filename ) )
	{
		UE_LOG(LogDiffAssetsCommandlet, Warning, TEXT("Could not write %s"), *Filename);
		return false;
	}
	return true;
}
FString FUnrealSourceFile::GetFileId() const
{
	FString StdFilename = Filename;

	FPaths::MakeStandardFilename(StdFilename);

	bool RelativePath = FPaths::IsRelative(StdFilename);

	if (!RelativePath)
	{
		// If path is still absolute that means MakeStandardFilename has failed
		// In this case make it relative to the current project. 
		RelativePath = FPaths::MakePathRelativeTo(StdFilename, *FPaths::GetPath(FPaths::GetProjectFilePath()));
	}

	// If the path has passed either MakeStandardFilename or MakePathRelativeTo it should be using internal path seperators
	if (RelativePath)
	{
		// Remove any preceding parent directory paths
		while (StdFilename.RemoveFromStart(TEXT("../")));
	}

	FStringOutputDevice Out;

	for (auto Char : StdFilename)
	{
		if (FChar::IsAlnum(Char))
		{
			Out.AppendChar(Char);
		}
		else
		{
			Out.AppendChar('_');
		}
	}

	return Out;
}
Esempio n. 7
0
int AnalyzePCHFile(const FString& CmdLine)
{
	auto IncludePercentageThreshold = ParseUsageThreshold(*CmdLine);
	auto IncludeSearchPaths = ParseIncludeSearchPaths(*CmdLine);

	FString IncludesDirectory;
	FParse::Value(*CmdLine, TEXT("-HeaderDataPath="), IncludesDirectory);

	int32 FileCount = 0;
	TMap<FString, int32> IncludeHeaderCount;
	GatherModuleHeaderData(*IncludesDirectory, FileCount, IncludeHeaderCount);

	// Open PCH file
	FString PCHFilePath;
	FParse::Value(*CmdLine, TEXT("-PCHFile="), PCHFilePath);

	TArray<FString> IncludesInPCH = GetIncludesInPCH(PCHFilePath, IncludeSearchPaths);

	OutputFileContents.Logf(TEXT("Remove the following #includes from %s"), *PCHFilePath);
	LogIncludeCount(IncludesInPCH, IncludeHeaderCount, FileCount, IncludePercentageThreshold);


	OutputFileContents.Logf(TEXT("Add the following #includes to %s"), *PCHFilePath);
	for (auto KVP : IncludeHeaderCount)
	{
		const auto& Filename = KVP.Key;
		const auto& HeaderIncludeCount = KVP.Value;
		auto IncludePercentage = static_cast<float>(HeaderIncludeCount) / static_cast<float>(FileCount);
		if (IncludePercentage > IncludePercentageThreshold)
		{
			OutputFileContents.Logf(TEXT("%s (%i/%i)%f%%"), *Filename, HeaderIncludeCount, FileCount, IncludePercentage);
		}
	}

	return 0;
}
Esempio n. 8
0
//
// If analysis/clang compilation gives an error, we still can provide some meaningful data to user,
// which is why we return 0 in such cases. We return error only when -OutputFile is not provided and
// when saving output file fails.
//
int main(int32 ArgC, const char* ArgV[])
{
	FString CmdLine = CreateCommandLine(ArgC, ArgV);
	FString ShortCmdLine = FCommandLine::RemoveExeName(*CmdLine);
	ShortCmdLine = ShortCmdLine.Trim();

	GEngineLoop.PreInit(*ShortCmdLine);

	if (!FParse::Value(*CmdLine, TEXT("-OutputFile="), OutputFileName))
	{
		return 1;
	}

	OutputFileContents.SetAutoEmitLineTerminator(true);

	if (FParse::Param(*CmdLine, TEXT("AnalyzePCHFile")))
	{
		AnalyzePCHFile(CmdLine);
	}

	if (FParse::Param(*CmdLine, TEXT("CreateIncludeFiles")))
	{
		CreateIncludeFiles(ArgC, ArgV);
	}

	if (FParse::Param(*CmdLine, TEXT("CheckThreadSafety")))
	{
		CheckThreadSafety(ArgC, ArgV);
	}

	if (!FFileHelper::SaveStringToFile(OutputFileContents, *OutputFileName))
	{
		return 2;
	}

	return 0;
}
Esempio n. 9
0
int32 UExporter::ExportToFile( UObject* Object, UExporter* InExporter, const TCHAR* Filename, bool InSelectedOnly, bool NoReplaceIdentical, bool Prompt )
{
#if WITH_EDITOR
    check(Object);

    CurrentFilename = Filename;

    UExporter*	Exporter	= InExporter;
    int32		Result		= 0;
    FString		Extension;

    if (!Exporter)
    {
        // look for an exporter with all possible extensions, so an exporter can have something like *.xxx.yyy as an extension
        int32 SearchStart = 0;
        int32 DotLocation;
        while (!Exporter && (DotLocation = CurrentFilename.Find(TEXT("."), ESearchCase::CaseSensitive, ESearchDir::FromStart, SearchStart)) != INDEX_NONE)
        {
            // get everything after the current .
            Extension = CurrentFilename.Mid(DotLocation + 1);

            // try to find an exporter with it
            Exporter = FindExporter( Object, *Extension );

            // skip past the dot in case we look again
            SearchStart = DotLocation + 1;
        }
    }

    if( !Exporter )
    {
        UE_LOG(LogExporter, Warning, TEXT("No %s exporter found for %s"), *Extension, *Object->GetFullName() );
        CurrentFilename = TEXT("");
        return 0;
    }

    Exporter->bSelectedOnly = InSelectedOnly;

    if( Exporter->bText )
    {
        FStringOutputDevice Buffer;
        const FExportObjectInnerContext Context;
        ExportToOutputDevice( &Context, Object, Exporter, Buffer, *Extension, 0, PPF_ExportsNotFullyQualified, InSelectedOnly );
        if ( Buffer.Len() == 0 )
        {
            Result = -1;
        }
        else
        {
            if( NoReplaceIdentical )
            {
                FString FileBytes;
                if ( FFileHelper::LoadFileToString(FileBytes,Filename) && FCString::Strcmp(*Buffer,*FileBytes) == 0 )
                {
                    UE_LOG(LogExporter, Log,  TEXT("Not replacing %s because identical"), Filename );
                    Result = 1;
                    goto Done;
                }

                if( Prompt )
                {
                    if( !GWarn->YesNof( FText::Format( NSLOCTEXT("Core", "Overwrite", "The file '{0}' needs to be updated.  Do you want to overwrite the existing version?"), FText::FromString( Filename ) ) ) )
                    {
                        Result = 1;
                        goto Done;
                    }
                }
            }
            if( !FFileHelper::SaveStringToFile( Buffer, Filename ) )
            {
#if 0
                if( GWarn->YesNof( FText::Format( NSLOCTEXT("Core", "OverwriteReadOnly", "'{0}' is marked read-only.  Would you like to try to force overwriting it?"), FText::FromString( Filename ) ) ) )
                {
                    IFileManager::Get().Delete( Filename, 0, 1 );
                    if( FFileHelper::SaveStringToFile( Buffer, Filename ) )
                    {
                        Result = 1;
                        goto Done;
                    }
                }
#endif
                UE_LOG(LogExporter, Error, TEXT("Error exporting %s: couldn't open file '%s'"), *Object->GetFullName(), Filename);
                goto Done;
            }
            Result = 1;
        }
    }
    else
    {
        for( int32 i = 0; i < Exporter->GetFileCount(); i++ )
        {
            FBufferArchive Buffer;
            if( ExportToArchive( Object, Exporter, Buffer, *Extension, i ) )
            {
                FString UniqueFilename = Exporter->GetUniqueFilename( Filename, i );

                if( NoReplaceIdentical )
                {
                    TArray<uint8> FileBytes;

                    if(	FFileHelper::LoadFileToArray( FileBytes, *UniqueFilename )
                            &&	FileBytes.Num() == Buffer.Num()
                            &&	FMemory::Memcmp( &FileBytes[ 0 ], &Buffer[ 0 ], Buffer.Num() ) == 0 )
                    {
                        UE_LOG(LogExporter, Log,  TEXT( "Not replacing %s because identical" ), *UniqueFilename );
                        Result = 1;
                        goto Done;
                    }
                    if( Prompt )
                    {
                        if( !GWarn->YesNof( FText::Format( NSLOCTEXT("Core", "Overwrite", "The file '{0}' needs to be updated.  Do you want to overwrite the existing version?"), FText::FromString( UniqueFilename ) ) ) )
                        {
                            Result = 1;
                            goto Done;
                        }
                    }
                }

                if( !FFileHelper::SaveArrayToFile( Buffer, *UniqueFilename ) )
                {
                    UE_LOG(LogExporter, Error, TEXT("Error exporting %s: couldn't open file '%s'"), *Object->GetFullName(), *UniqueFilename);
                    goto Done;
                }
            }
        }
        Result = 1;
    }
Done:
    CurrentFilename = TEXT("");

    return Result;
#else
    return 0;
#endif
}
Esempio n. 10
0
bool ANUTActor::NotifyControlMessage(UNetConnection* Connection, uint8 MessageType, FInBunch& Bunch)
{
	bool bHandledMessage = false;

	if (MessageType == NMT_NUTControl)
	{
		uint8 CmdType = 0;
		FString Command;
		FNetControlMessage<NMT_NUTControl>::Receive(Bunch, CmdType, Command);

		// Console command
		if (CmdType == ENUTControlCommand::Command_NoResult || CmdType == ENUTControlCommand::Command_SendResult)
		{
			UE_LOG(LogUnitTest, Log, TEXT("NMT_NUTControl: Executing command: %s"), *Command);

			FStringOutputDevice CmdResult;
			CmdResult.SetAutoEmitLineTerminator(true);

			bool bCmdSuccess = false;

			bCmdSuccess = GEngine->Exec(GetWorld(), *Command, CmdResult);

			UE_LOG(LogUnitTest, Log, TEXT("NMT_NUTControl: Command result: %s"), *CmdResult);


			bool bSendResult = CmdType == ENUTControlCommand::Command_SendResult;

			if (bSendResult)
			{
				uint8 ReturnCmdType = (bCmdSuccess ? ENUTControlCommand::CommandResult_Success :
										ENUTControlCommand::CommandResult_Failed);

				FNetControlMessage<NMT_NUTControl>::Send(Connection, ReturnCmdType, CmdResult);
			}
		}
		// Console command result
		else if (CmdType == ENUTControlCommand::CommandResult_Failed || CmdType == ENUTControlCommand::CommandResult_Success)
		{
			bool bCmdSuccess = CmdType == ENUTControlCommand::CommandResult_Success;

			if (bCmdSuccess)
			{
				UE_LOG(LogUnitTest, Log, TEXT("NMT_NUTControl: Got command result:"));
				UE_LOG(LogUnitTest, Log, TEXT("%s"), *Command);
			}
			else
			{
				UE_LOG(LogUnitTest, Log, TEXT("NMT_NUTControl: Failed to execute command"));
			}
		}
		// Ping request
		else if (CmdType == ENUTControlCommand::Ping)
		{
			uint8 TempCmdType = ENUTControlCommand::Pong;
			FString Dud;

			FNetControlMessage<NMT_NUTControl>::Send(Connection, TempCmdType, Dud);
		}
		// Pong reply - this should only be implemented by custom unit tests; hence the assert
		else if (CmdType == ENUTControlCommand::Pong)
		{
			UNIT_ASSERT(false);
		}
		// Custom implemented events, with the result triggered through 'NotifyEvent'
		else if (CmdType == ENUTControlCommand::WatchEvent)
		{
			// NOTE: Only the last NetConnection to request a WatchEvent, will receive notifications
			EventWatcher = Connection;

			// Watch for the end of seamless travel
			if (Command == TEXT("SeamlessTravelEnd"))
			{
				FCoreUObjectDelegates::PostLoadMap.AddStatic(&ANUTActor::NotifyPostLoadMap);
			}
		}
		// Event watch notification - should only be implemented by custom unit tests
		else if (CmdType == ENUTControlCommand::NotifyEvent)
		{
			UNIT_ASSERT(false);
		}
		// Create an actor instance (the 'summon' console command, doesn't work without a cheat manager)
		else if (CmdType == ENUTControlCommand::Summon)
		{
			const TCHAR* Cmd = *Command;
			FString SpawnClassName = FParse::Token(Cmd, false);
			bool bForceBeginPlay = FParse::Param(Cmd, TEXT("ForceBeginPlay"));

			// Hack specifically for getting the GameplayDebugger working - think the mainline code is broken
			bool bGameplayDebuggerHack = FParse::Param(Cmd, TEXT("GameplayDebuggerHack"));

			UClass* SpawnClass = FindObject<UClass>(NULL, *SpawnClassName);

			if (SpawnClass != NULL)
			{
				FActorSpawnParameters SpawnParms;
				SpawnParms.Owner = GetOwner();

				AActor* NewActor = GetWorld()->SpawnActor<AActor>(SpawnClass, SpawnParms);

				if (NewActor != NULL)
				{
					UE_LOG(LogUnitTest, Log, TEXT("Successfully summoned actor of class '%s'"), *SpawnClassName);

					if (bForceBeginPlay && !NewActor->HasActorBegunPlay())
					{
						UE_LOG(LogUnitTest, Log, TEXT("Forcing call to 'BeginPlay' on newly spawned actor."));

						NewActor->BeginPlay();
					}

					if (bGameplayDebuggerHack)
					{
						// Assign the LocalPlayerOwner property, to the PC owning this NUTActor, using reflection (to avoid dependency)
						UObjectProperty* LocalPlayerOwnerProp =
								FindField<UObjectProperty>(NewActor->GetClass(), TEXT("LocalPlayerOwner"));

						if (LocalPlayerOwnerProp != NULL)
						{
							LocalPlayerOwnerProp->SetObjectPropertyValue(
								LocalPlayerOwnerProp->ContainerPtrToValuePtr<UObject*>(NewActor), GetOwner());
						}
						else
						{
							UE_LOG(LogUnitTest, Log, TEXT("WARNING: Failed to find 'LocalPlayerOwner' property. Unit test broken."));
						}

						// Also hack-disable ticking, so that the replicator doesn't spawn a second replicator
						NewActor->SetActorTickEnabled(false);
					}
				}
				else
				{
					UE_LOG(LogUnitTest, Log, TEXT("SpawnActor failed for class '%s'"), *Command);
				}
			}
			else
			{
				UE_LOG(LogUnitTest, Log, TEXT("Could not find actor class '%s'"), *Command);
			}
		}
		// Suspend the game, until a resume request is received (used for giving time, to attach a debugger)
		else if (CmdType == ENUTControlCommand::SuspendProcess)
		{
			UE_LOG(LogUnitTest, Log, TEXT("Suspend start."));


			// Setup a named pipe, to monitor for the resume request
			FString ResumePipeName = FString::Printf(TEXT("%s%u"), NUT_SUSPEND_PIPE, FPlatformProcess::GetCurrentProcessId());
			FPlatformNamedPipe ResumePipe;
			bool bPipeCreated = ResumePipe.Create(ResumePipeName, true, false);

			if (bPipeCreated)
			{
				if (!ResumePipe.OpenConnection())
				{
					UE_LOG(LogUnitTest, Log, TEXT("WARNING: Failed to open pipe connection."));
				}
			}
			else
			{
				UE_LOG(LogUnitTest, Log, TEXT("WARNING: Failed to create resume pipe."));
			}



			// Spin/sleep (effectively suspended) until a resume request is received
			while (true)
			{
				if (bPipeCreated && ResumePipe.IsReadyForRW())
				{
					int32 ResumeVal = 0;

					if (ResumePipe.ReadInt32(ResumeVal) && !!ResumeVal)
					{
						UE_LOG(LogUnitTest, Log, TEXT("Got resume request."));
						break;
					}
				}


				FPlatformProcess::Sleep(1.0f);
			}


			ResumePipe.Destroy();

			UE_LOG(LogUnitTest, Log, TEXT("Suspend end."));
		}

		bHandledMessage = true;
	}

	return bHandledMessage;
}
bool FPerfCounters::ProcessRequest(uint8* Buffer, int32 BufferLen, FResponse& Response)
{
	bool bSuccess = false;

	// scan the buffer for a line
	FUTF8ToTCHAR WideBuffer(reinterpret_cast<const ANSICHAR*>(Buffer));
	const TCHAR* BufferEnd = FCString::Strstr(WideBuffer.Get(), TEXT("\r\n"));
	if (BufferEnd != nullptr)
	{
		// crack into pieces
		FString MainLine(BufferEnd - WideBuffer.Get(), WideBuffer.Get());
		TArray<FString> Tokens;
		MainLine.ParseIntoArrayWS(Tokens);
		if (Tokens.Num() >= 2)
		{
			FString ContentType(TEXT("application/json"));
			Response.Code = 200;

			// handle the request
			if (Tokens[0] != TEXT("GET"))
			{
				Response.Body = FString::Printf(TEXT("{ \"error\": \"Method %s not allowed\" }"), *Tokens[0]);
				Response.Code = 405;
			}
			else if (Tokens[1].StartsWith(TEXT("/stats")))
			{
				Response.Body = GetAllCountersAsJson();
			}
			else if (Tokens[1].StartsWith(TEXT("/exec?c=")))
			{
				FString ExecCmd = Tokens[1].Mid(8);
				FString ExecCmdDecoded = FPlatformHttp::UrlDecode(ExecCmd);

				FStringOutputDevice StringOutDevice;
				StringOutDevice.SetAutoEmitLineTerminator(true);

				bool bResult = false;
				if (ExecCmdCallback.IsBound())
				{
					bResult = ExecCmdCallback.Execute(ExecCmdDecoded, StringOutDevice);
					Response.Body = StringOutDevice;
					ContentType = TEXT("text/text");
				}
				else
				{
					Response.Body = FString::Printf(TEXT("{ \"error\": \"exec handler not found\" }"));
				}

				Response.Code = bResult ? 200 : 404;
			}
			else
			{
				Response.Body = FString::Printf(TEXT("{ \"error\": \"%s not found\" }"), *Tokens[1]);
				Response.Code = 404;
			}

			// send the response headers
			Response.Header = FString::Printf(TEXT("HTTP/1.0 %d\r\nContent-Length: %d\r\nContent-Type: %s\r\n\r\n"), Response.Code, Response.Body.Len(), *ContentType);
			bSuccess = true;
		}
		else
		{
			UE_LOG(LogPerfCounters, Warning, TEXT("Unable to parse HTTP request header: %s"), *MainLine);
		}
	}
	else
	{
		UE_LOG(LogPerfCounters, Warning, TEXT("Unable to immediately receive full request header"));
	}

	return bSuccess;
}